基于@AspectJ注解配置切面与基于XML配置切面
1. Waiter目标类
1 package com.smart.aop.advice.pointcut; 2 3 public class Waiter { 4 5 public void greetTo(String name) { 6 System.out.println("Waiter greet to " + name + " ..."); 7 } 8 9 public void serverTo(String name) { 10 System.out.println("waiter server to " + name + " ..."); 11 } 12 }
2. 使用AspectJ注解定义切面
1 package com.smart.aop.advice.aspectj; 2 3 import org.aspectj.lang.annotation.Aspect; 4 import org.aspectj.lang.annotation.Before; 5 6 @Aspect 7 public class PreGreetingAspect { 8 9 @Before ("execution(* greetTo(..))") //定义连接点(连接点方位信息--前置增强, 切点--所有目标类的greetTo方法--可带任意的入参和返回值) 10 public void beforeGreeting() { 11 System.out.println("How are you!"); //方法体为增强逻辑 12 } 13 }
3. 通过编程的方式织入切面,为Waiter生成织入了xxx切面的代理
1 package com.smart.aop.advice.aspectj; 2 3 import org.springframework.aop.aspectj.annotation.AspectJProxyFactory; 4 import org.testng.annotations.Test; 5 import com.smart.aop.advice.pointcut.Waiter; 6 7 8 public class AspectJProxyTest { 9 10 @Test 11 public void beforeTest() { 12 13 Waiter waiter = new Waiter(); 14 AspectJProxyFactory pFactory = new AspectJProxyFactory(); 15 16 pFactory.setTarget(waiter); //设置目标实例 17 pFactory.addAspect(PreGreetingAspect.class); //添加切面类 18 19 Waiter proxyWaiter = pFactory.getProxy(); //生成织入代理的代理对象 20 21 /** 22 * 由切面类中的切点信息execution(* greetTo(..)) 23 * 可知代理对象proxyWaiter的greetTo方法织入了切面类所定义的增强逻辑 24 */ 25 proxyWaiter.greetTo("Jack"); 26 proxyWaiter.serverTo("Jack"); 27 } 28 }
输出结果:
How are you!
Waiter greet to Jack ...
waiter server to Jack ...
4. 通过Spring配置方式织入切面
1)xml 配置
1 <!-- 匹配切点的目标bean --> 2 <bean id="waiter" class="com.smart.aop.advice.pointcut.Waiter" /> 3 4 <!-- 使用@AspectJ标注的切面类 --> 5 <bean class="com.smart.aop.advice.aspectj.PreGreetingAspect" /> 6 7 <!-- 自动代理创建器,能够将@AspectJ标注的切面自动织入到目标bean中 --> 8 <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />
2)测试
1 package com.smart.aop.advice.aspectj; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 import org.testng.annotations.Test; 6 7 import com.smart.aop.advice.pointcut.Waiter; 8 9 public class SpringAspectJTest { 10 11 12 @Test 13 public void beforeTest() { 14 15 16 ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com/smart/aop/advice/aspectj/beans-aspectj.xml"); 17 Waiter waiter = ctx.getBean("waiter", Waiter.class); 18 19 waiter.greetTo("Jack"); 20 waiter.serverTo("Jack"); 21 } 22 }
------------------------------------------------------------------------
基于XML配置切面
把切面类中的通过@Aspect和@Before("execution(* greetTo(..))")配置的‘连接点(切点和增强类型)’信息从切面类中剥离出来放到XML中配置,使原来的切面类成为真正意义上的POJO
1. 切面类 --- 成为一个普通的java类
package com.smart.aop.advice.aspectj; public class PreGreetingAspect { public void preGreeting() { System.out.println("切入代码 How are you!"); } }
2. 在XML中配置切面
1 <!-- 目标bean实例 --> 2 <bean id="waiter" class="com.smart.aop.advice.pointcut.Waiter" /> 3 <!-- 切面实例 --> 4 <bean id="greetingAspect" class="com.smart.aop.advice.aspectj.PreGreetingAspect" /> 5 6 <!-- proxy-target-class 7 true, 声明的切面使用cglib代理技术 8 false, 声明的切面使用JDK代理技术 9 --> 10 <aop:config proxy-target-class="true"> 11 <aop:aspect ref="greetingAspect"> 12 <!-- 13 aop:before,为前置增强 14 method属性,指定增强方法 15 pointcut属性,定义切点表达式 16 --> 17 <aop:before method="preGreeting" pointcut="target(com.smart.aop.advice.pointcut.Waiter) and execution(* greetTo(..))"/> 18 </aop:aspect> 19 </aop:config>
使用4-2的方法测试,验证System.out.println("切入代码 How are you!");已织入到Waiter#greeTo()方法的前面。
加入后置增强
1. 切面类
package com.smart.aop.advice.aspectj; public class PreGreetingAspect { public void preGreeting() { System.out.println("Waiter#greetTo()方法执行前织入 How are you!"); } public void postGreeting() { System.out.println("Waiter#greetTo()方法执行后织入 Byte!"); } }
2. XML配置
1 <!-- 目标bean实例 --> 2 <bean id="waiter" class="com.smart.aop.advice.pointcut.Waiter" /> 3 <!-- 切面实例 --> 4 <bean id="greetingAspect" class="com.smart.aop.advice.aspectj.PreGreetingAspect" /> 5 6 7 <!-- proxy-target-class 8 true, 声明的切面使用cglib代理技术 9 false, 声明的切面使用JDK代理技术 10 --> 11 <aop:config proxy-target-class="true"> 12 13 <aop:pointcut id="greetToPointcut" 14 expression="target(com.smart.aop.advice.pointcut.Waiter) and execution(* greetTo(..))" /> 15 16 <!-- 定义一个切面greetingAspect --> 17 <aop:aspect ref="greetingAspect"> 18 <!-- 19 aop:before,为前置增强 20 method属性,指定增强方法 21 pointcut属性,定义切点表达式 22 --> 23 <aop:before method="preGreeting" pointcut-ref="greetToPointcut"/> 24 </aop:aspect> 25 26 <aop:aspect ref="greetingAspect"> 27 <aop:after method="postGreeting" pointcut-ref="greetToPointcut"/> 28 </aop:aspect> 29 </aop:config>
3. 测试
1 @Test 2 public void beforeTest() { 3 4 ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com/smart/aop/advice/aspectj/beans-aspectj.xml"); 5 Waiter waiter = ctx.getBean("waiter", Waiter.class); 6 7 waiter.greetTo("Jack"); 8 waiter.serverTo("Jack"); 9 }
输出结果:
Waiter#greetTo()方法执行前织入 How are you!
Waiter greet to Jack ...
Waiter#greetTo()方法执行后织入 Byte!
waiter server to Jack ...