首页 > 代码库 > 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