首页 > 代码库 > spring AOP
spring AOP
1. 目标类
Waiter
package com.smart.aop.advice.pointcut;public class Waiter { private int age; //省略setter.getter public void greetTo(String name) { System.out.println("Waiter greet to " + name + " ..."); } public void serverTo(String name) { System.out.println("waiter server to " + name + " ..."); }}
Seller
package com.smart.aop.advice.pointcut;public class Seller { private int age; //省略setter.getter public void greetTo(String name) { System.out.println("seller greet to " + name + " ..."); } public void serverTo(String name) { System.out.println("seller server to " + name + " ..."); }}
2. 前置增强类GreetingBeforeAdvice
package com.smart.aop.advice.pointcut;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;/** * 前置增强类 */public class GreetingBeforeAdvice implements MethodBeforeAdvice { /** * method, 目标类的方法 * args, 目标类方法的入参 * target, 目标类实例 */ @Override public void before(Method method, Object[] args, Object target) throws Throwable { //输出切点信息 --- 哪个类的哪个方法 System.out.println("在前置增强中输出切点信息:" + target.getClass().getName() + "." + method.getName()); if (target instanceof Waiter) { Waiter waiter = (Waiter)target; System.out.println("在前置增强中访问目标实例waiter.age=" + waiter.getAge()); } else if (target instanceof Seller) { Seller seller = (Seller) target; System.out.println("在前置增强中访问目标实例seller.age=" + seller.getAge()); } String clientName = (String) args[0]; System.out.println("How are you! Mr." + clientName); }}
3. 静态方法名匹配切面
1 package com.smart.aop.advice.pointcut; 2 3 import java.lang.reflect.Method; 4 import org.springframework.aop.ClassFilter; 5 import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor; 6 7 8 /** 9 * 静态方法名匹配切面10 */11 public class GreetingPointcutAdvisor extends StaticMethodMatcherPointcutAdvisor {12 13 /**14 * 切点pointcut方法匹配规则 -- 匹配名为greetTo的方法15 */16 @Override17 public boolean matches(Method method, Class<?> targetClass) {18 19 //输出切点信息 --- 哪个类的哪个方法20 System.out.println("在切面的matches方法中输出切点信息:" + targetClass.getName() + "." + method.getName());21 22 return "greetTo".equals(method.getName());23 }24 25 /**26 * 切点类匹配规则 -- 匹配Waiter类及其子类27 */28 public ClassFilter getClassFilter() {29 return new ClassFilter() {30 31 @Override32 public boolean matches(Class<?> clazz) {33 34 System.out.println("在切面的getClassFilter方法中输出切点信息:" + clazz.getName());35 /*36 * 如果Waiter是clazz参数类型的超类,或clazz本身就是Waiter类型,则返回true37 * 即仅匹配Waitr类及其子类38 */39 return Waiter.class.isAssignableFrom(clazz);40 }41 };42 }43 }
4. 手工编码的方式织入切面生成代理
1 package com.smart.aop.advice.pointcut; 2 3 import org.springframework.aop.framework.ProxyFactory; 4 import org.testng.annotations.BeforeTest; 5 import org.testng.annotations.Test; 6 7 public class PointcutAdvisorTest { 8 9 private Seller sellerTarget; //目标实例10 private GreetingPointcutAdvisor pointcutAdvisor; //静态方法名切面11 private ProxyFactory pFactory; //代理工厂12 13 @BeforeTest14 public void init() {15 sellerTarget = new Seller();16 pointcutAdvisor = new GreetingPointcutAdvisor();17 pFactory = new ProxyFactory();18 pFactory.setTarget(sellerTarget);19 pFactory.addAdvisor(pointcutAdvisor);20 }21 22 @Test23 public void beforeAdvice() {24 Seller sellerProxy = (Seller) pFactory.getProxy();25 sellerProxy.greetTo("john");26 }27 }
输出结果:
在切面的getClassFilter方法中输出切点信息:com.smart.aop.advice.pointcut.Seller
在切面的getClassFilter方法中输出切点信息:com.smart.aop.advice.pointcut.Seller
在切面的getClassFilter方法中输出切点信息:com.smart.aop.advice.pointcut.Seller
在切面的getClassFilter方法中输出切点信息:com.smart.aop.advice.pointcut.Seller
在切面的getClassFilter方法中输出切点信息:com.smart.aop.advice.pointcut.Seller
在切面的getClassFilter方法中输出切点信息:com.smart.aop.advice.pointcut.Seller
在切面的getClassFilter方法中输出切点信息:com.smart.aop.advice.pointcut.Seller
seller greet to john ...
5.1 使用Spring配置定义切面
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <beans xmlns="http://www.springframework.org/schema/beans" 4 xmlns:p="http://www.springframework.org/schema/p" 5 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 6 xsi:schemaLocation=" 7 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 8 "> 9 10 <!-- 目标实例bean -->11 <bean id="waiterTarget" class="com.smart.aop.advice.pointcut.Waiter" p:age="13"/>12 <bean id="sellerTarget" class="com.smart.aop.advice.pointcut.Seller" p:age="33"/>13 <!-- 前置增强 -->14 <bean id="greetingBeforeAdvice" class="com.smart.aop.advice.pointcut.GreetingBeforeAdvice" />15 <!-- 定义一个切面,向其注入前置增强 -->16 <bean id="greetingPointcutAdvisor" class="com.smart.aop.advice.pointcut.GreetingPointcutAdvisor" 17 p:advice-ref="greetingBeforeAdvice"/>18 <!-- 定义一个抽象代理bean -->19 <bean id="parent" abstract="true" class="org.springframework.aop.framework.ProxyFactoryBean"20 p:proxyTargetClass="true"21 p:interceptorNames="greetingPointcutAdvisor" />22 <!-- 具体代理 -->23 <bean id="waiter" parent="parent" p:target-ref="waiterTarget" />24 <bean id="seller" parent="parent" p:target-ref="sellerTarget" />25
///////////////////////////////
//// 使用上面已定义的目标bean实例(waiterTarget, sellerTarget)和前置增强greetingBeforeAdvice
//// 通过正则表达式,定义一个与上述"静态方法名匹配切面"等价的"正则表达式方法名匹配切面"
26 <!-- 通过正则表达式定义一个切面,即"正则表达式方法名匹配切面" -->27 <bean id="regexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" 28 p:advice-ref="greetingBeforeAdvice">29 <property name="patterns">30 <list>31 <value>.*greet.*</value>32 </list>33 </property>34 </bean>35 <!-- 定义目标类的代理 -->36 <bean id="waiter1" class="org.springframework.aop.framework.ProxyFactoryBean"37 p:proxyTargetClass="true"38 p:target-ref="waiterTarget"39 p:interceptorNames="regexpAdvisor" />40 <bean id="seller1" class="org.springframework.aop.framework.ProxyFactoryBean"41 p:proxyTargetClass="true"42 p:target-ref="sellerTarget"43 p:interceptorNames="regexpAdvisor" />44 </beans>
5.2 测试
1 package com.smart.aop.advice.pointcut; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 import org.testng.annotations.Test; 6 7 public class SpringPointcutAdviceTest { 8 9 @Test10 public void testAdvice() { 11 12 ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com/smart/aop/advice/pointcut/beans-pointcut.xml");13 14 Waiter waiter = ctx.getBean("waiter", Waiter.class); //静态方法名匹配切面织入增强逻辑15 waiter.greetTo("john");16 17 Seller seller = ctx.getBean("seller1", Seller.class); //正则表达式方法匹配织入增强逻辑18 seller.greetTo("jack");19 }20 }
输出结果:
在切面的getClassFilter方法中输出切点信息:com.smart.aop.advice.pointcut.Waiter
在切面的matches方法中输出切点信息:com.smart.aop.advice.pointcut.Waiter.greetTo
在切面的getClassFilter方法中输出切点信息:com.smart.aop.advice.pointcut.Waiter
在切面的matches方法中输出切点信息:com.smart.aop.advice.pointcut.Waiter.getAge
在切面的getClassFilter方法中输出切点信息:com.smart.aop.advice.pointcut.Waiter
在切面的matches方法中输出切点信息:com.smart.aop.advice.pointcut.Waiter.setAge
在切面的getClassFilter方法中输出切点信息:com.smart.aop.advice.pointcut.Waiter
在切面的matches方法中输出切点信息:com.smart.aop.advice.pointcut.Waiter.serverTo
在切面的getClassFilter方法中输出切点信息:com.smart.aop.advice.pointcut.Waiter
在切面的matches方法中输出切点信息:com.smart.aop.advice.pointcut.Waiter.toString
在切面的getClassFilter方法中输出切点信息:com.smart.aop.advice.pointcut.Waiter
在切面的matches方法中输出切点信息:com.smart.aop.advice.pointcut.Waiter.clone
在切面的getClassFilter方法中输出切点信息:com.smart.aop.advice.pointcut.Waiter
在切面的matches方法中输出切点信息:com.smart.aop.advice.pointcut.Waiter.greetTo
在前置增强中输出切点信息:com.smart.aop.advice.pointcut.Waiter.greetTo
在前置增强中访问目标实例waiter.age=13
How are you! Mr.john
Waiter greet to john ...
在前置增强中输出切点信息:com.smart.aop.advice.pointcut.Seller.greetTo
在前置增强中访问目标实例seller.age=33
How are you! Mr.jack
seller greet to jack ...
spring AOP