概述
target()切点函数通过判断目标类是否按类型匹配指定类来决定连接点是否匹配. 用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;
this()切点函数则通过判断代理类是否按类型匹配指定类来决定是否和切点匹配。 用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配。 this中使用的表达式必须是类型全限定名,不支持通配符。
两者都仅接受类名的入参,虽然类名可以带“+”,但是对于这两个函数来讲,使用或者不是用,效果完全相同。
实例
代码已托管到Github—> https://github.com/yangshangwei/SpringMaster
target()
target(M)表示如果目标类按类型匹配于M,这目标类的所有方法都匹配切点。
target(com.xgj.IBussiness)
:IBussiness为接口,匹配接口实现类中所有方法,包括未在接口中声明的方法target(com.xgj.IBussiness)
等同于target(com.xgj.IBussiness+)
接口
package com.xgj.aop.spring.advisor.aspectJ.function.target; public interface IBussinessService { String doSomething(); }
目标Bean
package com.xgj.aop.spring.advisor.aspectJ.function.target; import org.springframework.stereotype.Component; /** * * * @ClassName: BussinessService * * @Description: @Component标注的bean * * @author: Mr.Yang * * @date: 2017年9月5日 下午8:18:03 */ @Component public class BussinessService { public String doSomething() { System.out.println("doSomething executed"); return "success"; } }
切面
package com.xgj.aop.spring.advisor.aspectJ.function.target; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; /** * * * @ClassName: TargetAspect * * @Description: @Aspect标注的切面 * target(com.xgj.aop.spring.advisor.aspectJ.function. * target.Class1)等同于 * target(com.xgj.aop.spring.advisor.aspectJ.function * .target.Class1+) * * @author: Mr.Yang * * @date: 2017年9月5日 下午7:53:52 */ @Aspect public class TargetAspect { @AfterReturning("target(com.xgj.aop.spring.advisor.aspectJ.function.target.IBussinessService)") public void crossCuttingCode() { System.out.println("some logic is here"); } }
配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- (1)声明Context命名空间以及Schema文件 (2)扫描类包以及应用注解定义的bean --> <context:component-scan base-package="com.xgj.aop.spring.advisor.aspectJ.function.target"/> <!-- 基于@AspectJ切面的驱动器 --> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 使用了@AspectJ注解的切面类 --> <bean class="com.xgj.aop.spring.advisor.aspectJ.function.target.TargetAspect"/> </beans>
测试类
package com.xgj.aop.spring.advisor.aspectJ.function.target; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TargetAspectTest { private ApplicationContext applicationContext; @Test public void test() { applicationContext = new ClassPathXmlApplicationContext( "classpath:com/xgj/aop/spring/advisor/aspectJ/function/target/conf-target.xml"); BussinessService bussinessService = applicationContext.getBean( "bussinessService", BussinessService.class); // 织入增强 bussinessService.doSomething(); // 织入增强 bussinessService.doAnother(); } }
运行结果:
2017-09-05 20:37:52,147 INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@285211ef: startup date [Tue Sep 05 20:37:52 BOT 2017]; root of context hierarchy 2017-09-05 20:37:52,264 INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/target/conf-target.xml] doSomething executed some logic is here doAnother executed some logic is here
this()
一般情况下,使用this()和target()来匹配定义切点,二者是等效的
target(com.xgj.IBussiness)
等价于this(com.xgj.IBussiness)
target(com.xgj.BussinessService)
等价于this(com.xgj.BussinessService)
二者的区别体现在通过引介切面产生代理对象时的具体表现。
看个例子:
接口
package com.xgj.aop.spring.advisor.aspectJ.function.thisFun; public interface IBussinessService { String doBussiness(); }
实现类
package com.xgj.aop.spring.advisor.aspectJ.function.thisFun; import org.springframework.stereotype.Component; /** * * * @ClassName: BussinessService * * @Description: @Component标注的bean * * @author: Mr.Yang * * @date: 2017年9月5日 下午8:18:03 */ @Component public class BussinessService implements IBussinessService { @Override public String doBussiness() { System.out.println("doBussiness executed"); return "success"; } public String doAnother() { System.out.println("doAnother executed"); return "success"; } }
另外一个通过引介切面要实现的接口
package com.xgj.aop.spring.advisor.aspectJ.function.thisFun; public interface ITransportService { public void doTransport(); }
实现类
package com.xgj.aop.spring.advisor.aspectJ.function.thisFun; public class TransportService implements ITransportService { @Override public void doTransport() { System.out.println("doTransport executed"); } }
为Bussiness添加 ITransportService接口的切面
package com.xgj.aop.spring.advisor.aspectJ.function.thisFun; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.DeclareParents; import org.springframework.core.Ordered; /** * * * @ClassName: AddTransportForBussinessAspect * * @Description: 为Bussiness添加 ITransportService接口的切面 * * @author: Mr.Yang * * @date: 2017年9月5日 下午9:18:50 */ @Aspect public class AddTransportForBussinessAspect implements Ordered { // (1)value 为BussinessService添加接口实现, (2)defaultImpl要添加的接口的默认的接口实现类 @DeclareParents(value = "com.xgj.aop.spring.advisor.aspectJ.function.thisFun.BussinessService", defaultImpl = TransportService.class) public ITransportService iTransportService; // (3) 要实现的目标接口 @Override public int getOrder() { return 2; } }
横切逻辑切面
package com.xgj.aop.spring.advisor.aspectJ.function.thisFun; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.springframework.core.Ordered; /** * * * @ClassName: ThisAspect * * @Description: @Aspectn标注的切面 * * * @author: Mr.Yang * * @date: 2017年9月5日 下午8:50:26 */ @Aspect public class ThisAspect implements Ordered { // 织入任何运行期对象为ITransportService的Bean中 @AfterReturning("this(com.xgj.aop.spring.advisor.aspectJ.function.thisFun.ITransportService)") public void corssCuttingCode() { System.out.println("some logic is here \n "); } @Override public int getOrder() { return 1; } }
配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- (1)声明Context命名空间以及Schema文件 (2)扫描类包以及应用注解定义的bean --> <context:component-scan base-package="com.xgj.aop.spring.advisor.aspectJ.function.thisFun"/> <!-- 基于@AspectJ切面的驱动器 --> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 使用了@AspectJ注解的切面类 --> <bean class="com.xgj.aop.spring.advisor.aspectJ.function.thisFun.ThisAspect"/> <bean class="com.xgj.aop.spring.advisor.aspectJ.function.thisFun.AddTransportForBussinessAspect"/> </beans>
测试类
package com.xgj.aop.spring.advisor.aspectJ.function.thisFun; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ThisAspectTest { private ApplicationContext applicationContext; @Test public void test() { applicationContext = new ClassPathXmlApplicationContext( "classpath:com/xgj/aop/spring/advisor/aspectJ/function/thisFun/conf-this.xml"); BussinessService bussinessService = (BussinessService) applicationContext .getBean("bussinessService"); // 匹配 this bussinessService.doBussiness(); // 匹配 this bussinessService.doAnother(); // 匹配 this ((ITransportService) bussinessService).doTransport(); } }
运行结果
2017-09-05 22:24:03,301 INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@24177697: startup date [Tue Sep 05 22:24:03 BOT 2017]; root of context hierarchy 2017-09-05 22:24:03,397 INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/thisFun/conf-this.xml] doBussiness executed some logic is here doAnother executed some logic is here doTransport executed some logic is here
如果有多个切面,注意多切面织入的顺序,如果不加织入的顺序, doTransport 方法的切面无法织入。
可见代理对象的方法都织入了this()函数定义的切面。