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     @Override
17     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             @Override
32             public boolean matches(Class<?> clazz) {
33                 
34                 System.out.println("在切面的getClassFilter方法中输出切点信息:" + clazz.getName());
35                 /*
36                  *  如果Waiter是clazz参数类型的超类,或clazz本身就是Waiter类型,则返回true
37                  *  即仅匹配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     @BeforeTest
14     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     @Test
23     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     @Test
10     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 ...

 

posted @ 2014-12-19 18:14  asnjudy  阅读(255)  评论(0编辑  收藏  举报