zoukankan      html  css  js  c++  java
  • Spring-AOP用法总结

    前言

        Spring AOP的实现方法很多,在项目开发中具体采用什么方式,需要按实际情况来选择,每一种的用法,有其一定的实用价值,所以本文将各种使用方法进行了具体实现。主要包括Advice的before、after、throwing、around四种拦截方式的实现,如何进行正则匹配,自动化代理及AspectJ注解形式的实现。

    AOP的定义

         Spring AOP(Aspect-oriented programming) 面向切面编程,是一种特殊的拦截器,将一组程序中的公共部分抽离出来进行单独管理,降低程序的耦合度,aop和oo互为补充,面向对象编程将程序分解成各个层次的对象,而面向切面编程将程序运行过程分解成各个切面。也可以这样理解,面向对象编程是从静态角度考虑程序结构,面向切面编程是从动态角度考虑程序运行过程。

       

     AOP中6个要素

    (1)通知(增强)Advice

      通知定义了切面是什么以及何时使用,应该应用在某个方法被调用之前?之后?还是抛出异常时?等等。

    (2)连接点 Join point

      连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时,抛出异常时,甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程中,并添加新的行为。

    (3)切点 Pointcut

      切点有助于缩小切面所通知的连接点的范围。如果说通知定义了切面的“什么”和“何时”的话,那么切点就定义了“何处”,切点会匹配通知所要织入的一个或多个连接点,一般常用正则表达式

    定义所匹配的类和方法名称来指定这些切点。

    (4)切面 Aspect

      切面是通知和切点的结合。通知和切点定义了切面的全部内容——它是什么,在何时何处完成其功能。

    (5)引入 Introduction

      引入允许我们向现有的类添加新方法或属性,从而无需修改这些现有类的情况下,让他们具有新的行为和状态。

    (6)织入 Weaving

      在过去我常常把织入与引入的概念混淆,我是这样来辨别的,“引入”我把它看做是一个定义,也就是一个名词,而“织入”我把它看做是一个动作,一个动词,也就是切面在指定的连接点被织

    入到目标对象中。

    AOP用法总结

    (1)Before advice 在方法执行前执行。

    (2)After  returning  advice 在方法执行后返回一个结果后执行。

    (3)After  throwing advice 在方法执行过程中抛出异常的时候执行。

    (4)Around  advice 在方法执行前后和抛出异常时执行,相当于综合了以上三种通知。

    (5)基于正则表达式,对符合匹配规则类或方法进行拦截处理。

    (6)基于自动代理,简少配置。

    (7)基于AspectJ注解形式,包括execution 表达式、@DeclareParents 注解、自动代理。

    实例

    1. Before advice 在方法执行前执行

    创建Product产品类

     1 package com.jk.work.aopone;
     2 /**
     3  * Title: 产品
     4  * Description: 该类的功能
     5  *
     6  * @author jihuan
     7  * @create 2017-05-18
     8  * @version: 1.0
     9  */
    10 public class Product {
    11     private  String  name;
    12     private  String  type;
    13     private   int    size;
    14 
    15     public String getName() {
    16         return name;
    17     }
    18 
    19     public void setName(String name) {
    20         this.name = name;
    21     }
    22 
    23     public String getType() {
    24         return type;
    25     }
    26 
    27     public void setType(String type) {
    28         this.type = type;
    29     }
    30 
    31     public int getSize() {
    32         return size;
    33     }
    34 
    35     public void setSize(int size) {
    36         this.size = size;
    37     }
    38 
    39     public  void  printName(){
    40         System.out.println("Product name "+ this.name);
    41     }
    42 
    43     public  void  printType(){
    44         System.out.println("Product type "+this.type);
    45     }
    46 
    47     public  void  printThrowException(){
    48         throw  new  IllegalArgumentException();
    49     }
    50 }

    创建BeforeMethod类

     1 package com.jk.work.aopone;
     2 import org.springframework.aop.MethodBeforeAdvice;
     3 import java.lang.reflect.Method;
     4 /**
     5  * Title: BeforeMethod
     6  * Description: 在方法执行前执行
     7  *
     8  * @author jihuan
     9  * @create 2017-05-19
    10  * @version: 1.0
    11  */
    12 public class BeforeMethod implements MethodBeforeAdvice {
    13     @Override
    14     public void before(Method method, Object[] objects, Object o) throws Throwable {
    15         System.out.println("Before  Method");
    16         System.out.println("--------------------");
    17     }
    18 }

    创建配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
        <bean id="product" class="com.jk.work.aopone.Product">
            <property name="name" value="p2p p2p p2p" />
            <property name="type" value="one year"/>
            <property name="size" value="30000" />
        </bean>
    
        <bean id="beforeMethodBean" class="com.jk.work.aopone.BeforeMethod" />
    
        <bean id="productProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target" ref="product"/>
            <property name="interceptorNames">
                <list>
                    <value>beforeMethodBean</value>
                </list>
            </property>
            <property name="proxyTargetClass" value="true"/> <!-- true 表 cglib,false 为jdkproxy(需要property 引入接口)-->
        </bean>
    </beans>

    创建测试类Test.java

    package com.jk.work.aopone;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    /**
     * Title: 类的主题(开发人员填写)
     * Description: 该类的功能
     *
     * @author jihuan
     * @create 2017-05-19
     * @version: 1.0
     */
    public class Test {
    
        public static void main(String[] args) {
            ApplicationContext context  = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
            Product   product  =   (Product) context.getBean("productProxy");
            System.out.println("---------------------");
            product.printName();
            System.out.println("---------------------");
            product.printType();
            System.out.println("----------------------");
            try{
                product.printThrowException();
            }catch(Exception e){
            }
        }
    }

     运行结果:

    ---------------------
    Before  Method
    --------------------
    Product name p2p p2p p2p
    ---------------------
    Before  Method
    --------------------
    Product type one year
    ----------------------
    Before  Method
    --------------------

      测试类可以采用编程式调用,简单实现: 

    package com.jk.work.aopone;
    import org.springframework.aop.framework.ProxyFactory;
    /**
     * Title: 编程式
     * Description: 该类的功能
     *
     * @author jihuan
     * @create 2017-05-19 00:26
     * @version: 1.0
     */
    public class Test2 {
    
        public static void main(String[] args) {
            ProxyFactory proxyFactory=new ProxyFactory() ;
            Product product1=new Product();
            product1.setName("p2p");
            proxyFactory.setTarget(product1);
            proxyFactory.addAdvice(new BeforeMethod());
            Product product=(Product)proxyFactory.getProxy();
            product.printName();
        }
    }

    运行结果:

    Before  Method
    --------------------
    Product name p2p

    2.After  returning  advice 方法之后执行

    创建AfterMethod类 

     1 package com.jk.work.aopone;
     2 import org.springframework.aop.AfterReturningAdvice;
     3 import java.lang.reflect.Method;
     4 /**
     5  * Title: 类的主题(开发人员填写)
     6  * Description: 该类的功能
     7  *
     8  * @author jihuan
     9  * @create 2017-05-19 00:09
    10  * @version: 1.0
    11  */
    12 public class AfterMethod implements AfterReturningAdvice {
    13     @Override
    14     public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
    15         System.out.println("-------------------");
    16         System.out.println("After  method ");
    17     }
    18 }

     创建配置文件 

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
        <bean id="product" class="com.jk.work.aopone.Product">
            <property name="name" value="p2p p2p p2p" />
            <property name="type" value="one year"/>
            <property name="size" value="30000" />
        </bean>
    
        <bean id="afterMethodBean" class="com.jk.work.aopone.AfterMethod" />
    
        <bean id="productProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target" ref="product"/>
            <property name="interceptorNames">
                <list>
                    <value>afterMethodBean</value>
                </list>
            </property>
            <property name="proxyTargetClass" value="true"/> <!-- true 表 cglib,false 为jdkproxy(需要property 引入接口)-->
        </bean>
    </beans> 

    创建测试类复用Test.java

    运行结果: 

    ---------------------
    Product name p2p p2p p2p
    -------------------
    After  method 
    ---------------------
    Product type one year
    -------------------
    After  method 
    ----------------------

    3. After  throwing advice 在方法执行过程中抛出异常的时候执行

    创建ThrowException类

     1 package com.jk.work.aopone;
     2 import org.springframework.aop.ThrowsAdvice;
     3 /**
     4  * Title: 类的主题(开发人员填写)
     5  * Description: 该类的功能
     6  *
     7  * @author jihuan
     8  * @create 2017-05-19
     9  * @version: 1.0
    10  */
    11 public class ThrowException  implements ThrowsAdvice {
    12     public  void  afterThrowing(IllegalArgumentException e)  throws  Throwable{
    13         System.out.println("after Throwing  Exception");
    14     }
    15 }

     创建配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
        <bean id="product" class="com.jk.work.aopone.Product">
            <property name="name" value="p2p p2p p2p" />
            <property name="type" value="one year"/>
            <property name="size" value="30000" />
        </bean>
    
        <bean id="throwException" class="com.jk.work.aopone.ThrowException" />
    
        <bean id="productProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target" ref="product"/>
            <property name="interceptorNames">
                <list>
                    <value>throwException</value>
                </list>
            </property>
            <property name="proxyTargetClass" value="true"/> <!-- true 表 cglib,false 为jdkproxy(需要property 引入接口)-->
        </bean>
    </beans>

    运行结果

    ---------------------
    Product name p2p p2p p2p
    ---------------------
    Product type one year
    ----------------------
    after Throwing  Exception

    4. Around  advice 在方法执行前后和抛出异常时执行,相当于综合了以上三种通知 

    创建AroundMethod类

     1 package com.jk.work.aopone;
     2 import org.aopalliance.intercept.MethodInterceptor;
     3 import org.aopalliance.intercept.MethodInvocation;
     4 import java.util.Arrays;
     5 /**
     6  * Title: 类的主题(开发人员填写)
     7  * Description: 该类的功能
     8  *
     9  * @author jihuan
    10  * @create 2017-05-19 
    11  * @version: 1.0
    12  */
    13 public class AroundMethod implements MethodInterceptor {
    14     @Override
    15     public Object invoke(MethodInvocation methodInvocation) throws Throwable {
    16         System.out.println("method  name:" + methodInvocation.getMethod().getName());
    17         System.out.println("method  arguments" + Arrays.toString(methodInvocation.getArguments()));
    18         System.out.println("Around  method : before ");
    19         try{
    20             Object result = methodInvocation.proceed();
    21             System.out.println("Around method : after ");
    22             return  result;
    23         }catch(IllegalArgumentException e){
    24             System.out.println("Around method : throw  an  exception ");
    25             throw  e;
    26         }
    27     }
    28 }

    创建配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
        <bean id="product" class="com.jk.work.aopone.Product">
            <property name="name" value="p2p p2p p2p" />
            <property name="type" value="one year"/>
            <property name="size" value="30000" />
        </bean>
    
        <bean id="aroundMethod"  class="com.jk.work.aopone.AroundMethod" />
    
        <bean id="productProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target" ref="product"/>
            <property name="interceptorNames">
                <list>
                    <value>aroundMethod</value>
                </list>
            </property>
            <property name="proxyTargetClass" value="true"/> <!-- true 表 cglib,false 为jdkproxy(需要property 引入接口)-->
        </bean>
    </beans>

    运行结果

    ---------------------
    method  name:printName
    method  arguments[]
    Around  method : before 
    Product name p2p p2p p2p
    Around method : after 
    ---------------------
    method  name:printType
    method  arguments[]
    Around  method : before 
    Product type one year
    Around method : after 
    ----------------------
    method  name:printThrowException
    method  arguments[]
    Around  method : before 
    Around method : throw  an  exception 

    5. 基于正则表达式的实现

        采用RegexpMethodPointcutAdvisor来实现。采用的正则匹配规则,大概有四点,举例说明:

    com.service..* 和 com.service..*Service..* 和 .*get.* 和 .get.*

    第一个表达式匹配的应该是com.service包下的所有方法
    第二个表达式匹配的应该是com.service包下所有类名以Service结尾的所有方法
    第三个表达式匹配的应该是所有类中含有get的方法
    第四个表达式匹配的应该是所有类中以get为前缀的方法

    具体如何实现,见下方实例:

    创建Garden接口

     1 package com.jk.work.aoptwo;
     2 
     3 /**
     4  * Created by jihuan on 17/5/20.
     5  */
     6 public interface Garden {
     7 
     8     void fruitPlant();
     9 
    10     void fruitGrow();
    11 
    12     void fruitHarvest();
    13 }

     创建Garden实现类

     1 package com.jk.work.aoptwo;
     2 /**
     3  * Title: 类的主题(开发人员填写)
     4  * Description: 该类的功能
     5  *
     6  * @author jihuan
     7  * @create 2017-05-20
     8  * @version: 1.0
     9  */
    10 public class AppleGarden implements Garden{
    11     @Override
    12     public void fruitPlant() {
    13         System.out.println("Apple plant...");
    14     }
    15 
    16     @Override
    17     public void fruitGrow() {
    18         System.out.println("Apple grow...");
    19     }
    20 
    21     @Override
    22     public void fruitHarvest() {
    23         System.out.println("Apple harvest...");
    24     }
    25 }

     创建拦截类,采用MethodInterceptor,实现方法前后拦截

     1 package com.jk.work.aoptwo;
     2 import org.aopalliance.intercept.MethodInterceptor;
     3 import org.aopalliance.intercept.MethodInvocation;
     4 /**
     5  * Title: 类的主题(开发人员填写)
     6  * Description: 该类的功能
     7  *
     8  * @author jihuan
     9  * @create 2017-05-20
    10  * @version: 1.0
    11  */
    12 public class GardenAroundAdvice implements MethodInterceptor {
    13     @Override
    14     public Object invoke(MethodInvocation methodInvocation) throws Throwable {
    15         before();
    16         Object result=methodInvocation.proceed();
    17         after();
    18         return result;
    19     }
    20     private void before(){
    21         System.out.println("before......");
    22     }
    23     private void after(){
    24         System.out.println("after......");
    25     }
    26

    创建配置文件,AppleGarden下所有以fruit开头的方法进行切面拦截

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">  
    
         <!--果园-->
        <bean id="appleGarden" class="com.jk.work.aoptwo.AppleGarden" />
        <bean id="gardenAroundAdvice" class="com.jk.work.aoptwo.GardenAroundAdvice" />
        <bean id="gardenAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name="advice" ref="gardenAroundAdvice" />
            <property name="pattern" value="com.jk.work.aoptwo.AppleGarden.fruit.*" />
        </bean>
    
        <bean id="productProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target" ref="appleGarden"/>
            <property name="interceptorNames">
                <list>
                    <value>gardenAdvisor</value>
                </list>
            </property>
            <property name="proxyTargetClass" value="true"/> <!-- true 表 cglib,false 为jdkproxy(需要property 引入接口)-->
        </bean>
    </beans>

     测试类

    package com.jk.work.aoptwo;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    /**
     * Title: 类的主题(开发人员填写)
     * Description: 该类的功能
     *
     * @author jihuan
     * @create 2017-05-20
     * @version: 1.0
     */
    public class Test {
        public static void main(String[] args) {
            ApplicationContext context  = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
            AppleGarden appleGarden  =   (AppleGarden) context.getBean("productProxy");
            System.out.println("----------1-----------");
            appleGarden.fruitPlant();
            System.out.println("----------2----------");
            appleGarden.fruitGrow();
            System.out.println("----------3-----------");
            appleGarden.fruitHarvest();
    
        }
    }

     运行效果:

    ----------1-----------
    before......
    Apple plant...
    after......
    ----------2----------
    before......
    Apple grow...
    after......
    ----------3-----------
    before......
    Apple harvest...
    after......
    
    Process finished with exit code 0

    6. 基于自动代理的实现

    采用自动代理的好处,可以减少配置,简化开发,spring的自动代理,采用了三种方式:

    1)Advisor形式,实现类为DefaultAdvisorAutoProxyCreator;

    2)Bean形式,实现类为BeanNameAutoProxyCreator;

    3)AspjectJ注解形式,实现方式是@Aspect。

    具体实例

     Advisor形式,实现类为DefaultAdvisorAutoProxyCreator

    创建sprng-aop.xml 配置

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
         <!--果园-->
        <bean id="appleGarden" class="com.jk.work.aoptwo.AppleGarden" />
        <bean id="gardenAroundAdvice" class="com.jk.work.aoptwo.GardenAroundAdvice" />
        <bean id="gardenAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name="advice" ref="gardenAroundAdvice" />
            <property name="pattern" value="com.jk.work.aoptwo.AppleGarden.fruit.*" />
        </bean>
        <!--自动代理-->
        <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
          <property name="optimize" value="true"/><!-- true 自动寻找代理类,有接口,使用jdkproxy,否则采用cglib-->
        </bean>
    </beans>

     测试类:

    package com.jk.work.aoptwo;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    /**
     * Title: 类的主题(开发人员填写)
     * Description: 该类的功能
     *
     * @author jihuan
     * @create 2017-05-20
     * @version: 1.0
     */
    public class Test2 {
        public static void main(String[] args) {
            ApplicationContext context  = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
            AppleGarden appleGarden  =   (AppleGarden) context.getBean("appleGarden");
            System.out.println("----------1-----------");
            appleGarden.fruitPlant();
            System.out.println("----------2----------");
            appleGarden.fruitGrow();
            System.out.println("----------3-----------");
            appleGarden.fruitHarvest();
        }
    }

     运行效果

    ----------1-----------
    before......
    Apple plant...
    after......
    ----------2----------
    before......
    Apple grow...
    after......
    ----------3-----------
    before......
    Apple harvest...
    after......

    Bean形式,实现类为BeanNameAutoProxyCreator

    创建spring-aop.xml 配置

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
         <!--果园-->
        <bean id="appleGarden" class="com.jk.work.aoptwo.AppleGarden" />
        <bean id="gardenAroundAdvice" class="com.jk.work.aoptwo.GardenAroundAdvice" />
        <bean id="gardenAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name="advice" ref="gardenAroundAdvice" />
            <property name="pattern" value="com.jk.work.aoptwo.AppleGarden.fruit.*" />
        </bean>
    
        <!--自动代理-->
        <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
            <property name="beanNames" value="*Garden" />
            <property name="interceptorNames" value="gardenAdvisor"/>
            <property name="optimize" value="true"/> <!--true 使用jdkproxy,false 采用cglib-->
        </bean>
    </beans>

      测试类:

    package com.jk.work.aoptwo;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    /**
     * Title: 类的主题(开发人员填写)
     * Description: 该类的功能
     *
     * @author jihuan
     * @create 2017-05-20
     * @version: 1.0
     */
    public class Test2 {
        public static void main(String[] args) {
            ApplicationContext context  = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
            AppleGarden appleGarden  =   (AppleGarden) context.getBean("appleGarden");
            System.out.println("----------1-----------");
            appleGarden.fruitPlant();
            System.out.println("----------2----------");
            appleGarden.fruitGrow();
            System.out.println("----------3-----------");
            appleGarden.fruitHarvest();
        }
    }

     运行效果

    ----------1-----------
    before......
    Apple plant...
    after......
    ----------2----------
    before......
    Apple grow...
    after......
    ----------3-----------
    before......
    Apple harvest...
    after......

     AspjectJ注解形式,实现类是AnnotationAwareAspectJAutoProxyCreator,在AspjectJ注解部分说明。

     

    7. AspectJ注解

     AspectJ注解方式,采用execution表达式进行切面拦截

    创建spring-aop配置

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="com.*"/>
         <!--果园-->
        <bean id="appleGarden" class="com.jk.work.aoptwo.AppleGarden" />
        <bean id="gardenAroundAdvice" class="com.jk.work.aoptwo.GardenAroundAdvice" />
        <bean id="gardenAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name="advice" ref="gardenAroundAdvice" />
            <property name="pattern" value="com.jk.work.aoptwo.AppleGarden.fruit.*" />
        </bean>
        <!--aspectj-->
        <aop:aspectj-autoproxy proxy-target-class="true"/>
    </beans>

      创建AroundAspect 拦截类

     1 package com.jk.work.aoptwo;
     2 import org.aspectj.lang.ProceedingJoinPoint;
     3 import org.aspectj.lang.annotation.Around;
     4 import org.aspectj.lang.annotation.Aspect;
     5 import org.springframework.stereotype.Component;
     6 
     7 /**
     8  * Title: 类的主题(开发人员填写)
     9  * Description: 该类的功能
    10  *
    11  * @author jihuan
    12  * @create 2017-05-20
    13  * @version: 1.0
    14  */
    15 @Aspect
    16 @Component
    17 public class AroundAspect {
    18     @Around("execution(* com.jk.work.aoptwo.AppleGarden.*(..))")
    19     public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
    20         handleBefore();
    21         Object rs=proceedingJoinPoint.proceed();
    22         handleAfter();
    23         return  rs;
    24     }
    25 
    26     private void handleBefore(){
    27         System.out.println("=====before=====");
    28     }
    29     private void handleAfter(){
    30         System.out.println("=====after=====");
    31     }
    32 }

     测试类

    package com.jk.work.aoptwo;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    /**
     * Title: 类的主题(开发人员填写)
     * Description: 该类的功能
     *
     * @author jihuan
     * @create 2017-05-20
     * @version: 1.0
     */
    public class Test2 {
        public static void main(String[] args) {
            ApplicationContext context  = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
            AppleGarden appleGarden  =   (AppleGarden) context.getBean("appleGarden");
            System.out.println("----------1-----------");
            appleGarden.fruitPlant();
            System.out.println("----------2----------");
            appleGarden.fruitGrow();
            System.out.println("----------3-----------");
            appleGarden.fruitHarvest();
        }
    }

     运行效果

    ----------1-----------
    =====before=====
    Apple plant...
    =====after=====
    ----------2----------
    =====before=====
    Apple grow...
    =====after=====
    ----------3-----------
    =====before=====
    Apple harvest...
    =====after=====

    AspectJ @DeclareParents 注解,目标是对于一个已有的类引入新的接口,可以使用另一个接口类的功能,属于一种对类的扩展

    创建新的接口Worker类

    1 package com.jk.work.aoptwo;
    2 
    3 /**
    4  * Created by jihuan on 17/5/20.
    5  */
    6 public interface Worker {
    7 
    8     void work(String task);
    9

    创建Worker的实现类

    package com.jk.work.aoptwo;
    /**
     * Title: 类的主题(开发人员填写)
     * Description: 该类的功能
     *
     * @author jihuan
     * @create 2017-05-20 17:43
     * @version: 1.0
     */
    public class AppleWorker implements Worker{
        @Override
        public void work(String task) {
            System.out.println("start work..."+task);
        }
    }

    创建拦截器AroundAspect2

    package com.jk.work.aoptwo;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.DeclareParents;
    import org.springframework.stereotype.Component;
    
    /**
     * Title: 类的主题(开发人员填写)
     * Description: 该类的功能
     *
     * @author jihuan
     * @create 2017-05-20 17:40
     * @version: 1.0
     */
    @Aspect
    @Component
    public class AroundAspect2 {
        @DeclareParents(value = "com.jk.work.aoptwo.AppleGarden",defaultImpl =AppleWorker.class )
        private Worker worker;
    }

    spring-aop.xml的配置

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="com.*"/>
         <!--果园-->
        <bean id="appleGarden" class="com.jk.work.aoptwo.AppleGarden" />
        <bean id="gardenAroundAdvice" class="com.jk.work.aoptwo.GardenAroundAdvice" />
        <bean id="gardenAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name="advice" ref="gardenAroundAdvice" />
            <property name="pattern" value="com.jk.work.aoptwo.AppleGarden.fruit.*" />
        </bean>
        <!--aspectj-->
        <aop:aspectj-autoproxy proxy-target-class="true"/>
    </beans>

    创建测试类

    package com.jk.work.aoptwo;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * Title: 类的主题(开发人员填写)
     * Description: 该类的功能
     *
     * @author jihuan
     * @create 2017-05-20 17:48
     * @version: 1.0
     */
    public class Test3 {
        public static void main(String[] args) {
            ApplicationContext context  = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
            AppleGarden appleGarden  =   (AppleGarden) context.getBean("appleGarden");
            Worker worker=(Worker)appleGarden;
            System.out.println("----------1-----------");
            worker.work("plant");
            appleGarden.fruitPlant();
            System.out.println("----------2----------");
            worker.work("watering");
            appleGarden.fruitGrow();
            System.out.println("----------3-----------");
            appleGarden.fruitHarvest();
            worker.work("Harvest");
        }
    }

     运行效果

    ----------1-----------
    start work...plant
    Apple plant...
    ----------2----------
    start work...watering
    Apple grow...
    ----------3-----------
    Apple harvest...
    start work...Harvest

     

    AspjectJ注解自动代理方式的实现

    创建拦截类

    package com.jk.work.aoptwo;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.stereotype.Component;
    /**
     * Title: 类的主题(开发人员填写)
     * Description: 该类的功能
     *
     * @author jihuan
     * @create 2017-05-20 17:21
     * @version: 1.0
     */
    @Aspect
    @Component
    public class AroundAspect {
        public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
            handleBefore();
            Object rs=proceedingJoinPoint.proceed();
            handleAfter();
            return  rs;
        }
    
        private void handleBefore(){
            System.out.println("=====before=====");
        }
        private void handleAfter(){
            System.out.println("=====after=====");
        }
    }

    spring-aop.xml 配置

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="com.*"/>
      
        <!--aspectj-->
        <aop:config>
            <aop:aspect ref="aroundAspect">
                <aop:around method="around" pointcut="execution(* com.jk.work.aoptwo.AppleGarden.*(..))"/>
            </aop:aspect>
        </aop:config>
        <aop:aspectj-autoproxy proxy-target-class="true"/>
    </beans>

    测试类

    package com.jk.work.aoptwo;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    /**
     * Title: 类的主题(开发人员填写)
     * Description: 该类的功能
     *
     * @author jihuan
     * @create 2017-05-20 11:04
     * @version: 1.0
     */
    public class Test2 {
        public static void main(String[] args) {
            ApplicationContext context  = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
            AppleGarden appleGarden  =   (AppleGarden) context.getBean("appleGarden");
            System.out.println("----------1-----------");
            appleGarden.fruitPlant();
            System.out.println("----------2----------");
            appleGarden.fruitGrow();
            System.out.println("----------3-----------");
            appleGarden.fruitHarvest();
        }
    }

    运行效果

    package com.jk.work.aoptwo;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    /**
     * Title: 类的主题(开发人员填写)
     * Description: 该类的功能
     *
     * @author jihuan
     * @create 2017-05-20 11:04
     * @version: 1.0
     */
    public class Test2 {
        public static void main(String[] args) {
            ApplicationContext context  = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
            AppleGarden appleGarden  =   (AppleGarden) context.getBean("appleGarden");
            System.out.println("----------1-----------");
            appleGarden.fruitPlant();
            System.out.println("----------2----------");
            appleGarden.fruitGrow();
            System.out.println("----------3-----------");
            appleGarden.fruitHarvest();
        }
    }

    总结

         AOP的用法较多,熟悉每一种用法,能更好的在项目中发挥作用。AOP其实就是一种拦截器,底层采用JDKProxy动态代理和Cglib实现动态代理。对于有接口的形式采用JDKProxy加载处理目标对象。对于没有接口的普通类采用Cglib进行对象的拦截对出。JDKProxy的底层是java反射,Cglib的底层是调asm开源包。

    如需转载,请标明本文作者:源码在深山,出处:博客园,原文链接:http://www.cnblogs.com/love-jk/p/spring-api.html

    参考:

    1) http://blog.csdn.net/topwqp/article/details/8695180

    2)   http://www.cnblogs.com/zhaozihan/p/5953063.html

    3)《轻量级Java EE企业应用实战》第三版

  • 相关阅读:
    什么是蓝绿部署和滚动部署
    北漂--我的2018
    辛苦俩月总结的面试题,掌握它怼翻面试官不是梦~
    记一次项目谈判的失败经历,要拒绝免费开发!
    程序员技术入股的那些坑
    记一次程序员在办公室里的“撕逼”经历
    公司来了个“奇葩”的程序员
    苦逼程序员如何在公司生存的经验分享
    (第二部)程序员逆天改命之胜天半子
    别闹了,颠覆世界不是为了让它变得更糟
  • 原文地址:https://www.cnblogs.com/love-jk/p/spring-api.html
Copyright © 2011-2022 走看看