zoukankan      html  css  js  c++  java
  • 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 ...

  • 相关阅读:
    Codeforces Round #296 (Div. 2B. Error Correct System
    实验十二 图的建立与遍历
    1561: (More) Multiplication
    1562: Fun House
    hdu 2203 亲和串
    hdu 3549Flow Problem
    poj 2182 Lost Cows
    poj 3468A Simple Problem with Integers
    hdu1698 Just a Hook
    栈和队列的面试题Java实现
  • 原文地址:https://www.cnblogs.com/asnjudy/p/4174534.html
Copyright © 2011-2022 走看看