Spring核心机制(面向切面编程AOP)详解

来源:互联网 发布:手机跟踪软件 编辑:程序博客网 时间:2024/05/29 12:30

1. Spring AOP 术语

这里写图片描述

这里写图片描述


2. 使用Spring AOP

2.1 java 方式

第一步: 使用 @EnableAspectJAutoProxy 注解 启用AspectJ注解的自动代理

@Configurable@EnableAspectJAutoProxy //启用 AspectJ自动代理@ComponentScanpublic class ConcerConfig {    @Bean     //声明Audience bean    public Audience audience(){        return new Audience();    }      }

第二步: 使用@AspectJ 注解 定义一个切面。表明Audience不仅仅是一个POJO,还是一个切面。Audience类中的方法都使用注 解来定义切面的具体行为。

    @Aspect     @Component    public class Audience {      ...略...    }

第三步: 使用@Pointcut 注解 定义一个切点。切点语法详解

    @Aspect     @Component    public class Audience {     /**      * 定义命名的切点      */                                 @Pointcut("execution(* springActualCombat.aop.annotationMode.Performance.perform(..))")      public void performance(){}      ...略...    }

第四步: 定义通知
1.Spring使用 使用 AspectJ注解来声明通知方法:

注解 通知 @After 通知方法会在目标方法返回或抛出异常后调用 @AfterReturning 通知方法会在目标方法返回后调用 @AfterThrowing 通知方法会在目标方法抛出异常后调用 @Around 通知方法会将目标方法封装起来 @Before 通知方法会在目标方法调用之前执行
    @Aspect     @Component    public class Audience {      /**     * 定义命名的切点     */                               @Pointcut("execution(* springActualCombat.aop.annotationMode.Performance.perform(..))")    public void performance(){}    /**     * 开场前     */    @Before("performance()")    public void silenceCellPhons(){        System.out.println("开场前,关掉手机!");    }    /**     * 开始表演前     */    @Before("performance()")    public void takeSeats(){        System.out.println("开始表演,鼓掌!");    }    /**     * 结束表演后     */    @AfterReturning("performance()")    public void applause(){        System.out.println("结束表演,鼓掌!");    }    /**     * 表演失败时     */    @AfterThrowing("performance()")    public void demandRefund(){        System.out.println("傻逼,退票!");    }/**----------------------------------------环绕通知-------------------------------------------*/        /**     * 环绕通知的切点     */    @Pointcut("execution(* springActualCombat.aop.annotationMode.Performance.performSurround(..))")    public void performanceSurround(){}    /**     * 环绕通知     */    @Around("performanceSurround()")    public void watchPerformance(ProceedingJoinPoint jp){        try {             System.out.println("开始表演,鼓掌!");              jp.proceed(); //必须调用             System.out.println("结束表演,鼓掌!");        } catch (Throwable e) {             System.out.println("傻逼,退票!");        }           }/**----------------------------------------带参数的通知--------------------------------------- */         Integer singCounts=0;    @Pointcut("execution(* springActualCombat.aop.annotationMode.Performance.singingCount(int))"+" && args(singCount)")    public void singCount(int singCount){};    @Before("singCount(singCount)")    public void performanceCount(int singCount){        singCounts +=singCount;        if (singCounts ==10) {            System.out.println("已演唱"+singCounts+"首!");        }           }}

2.2 xml 方式

1. 启用AOP
这里写图片描述

2. Spring AOP的 XML标签

AOP 配置元素 用途 < aop:config> AOP配置元素 < aop:declare-parents> 以透明的方式为被通知的对象引入额外的接口 < aop:aspectj-autoproxy> 启用@AspectJ注解驱动的切面 < aop:aspect> 定义一个切面 < aop:pointcut> 定义一个切点 < aop:advisor> 定义AOP通知器 < aop:after> 定义AOP后置通知(不管被通知的方法是否执行成功) < aop:after-returning> 定义AOP返回通知 < aop:after-throwing> 定义AOP异常通知 < aop:around> 定义AOP环绕通知 < aop:before> 定义一个AOP前置通知

3.XML配置方式:

    <bean id="performanceImp" class="springActualCombat.aop.xmlMode.PerformanceImp" />    <bean id="andience" class="springActualCombat.aop.xmlMode.Audience" />    <aop:config>          <!-- 引用audience Bean -->          <aop:aspect ref="andience">               <!-- 定义切点 -->                                                                                     <aop:pointcut id="performance" expression="execution(* springActualCombat.aop.xmlMode.Performance.perform(..))" />                       <!-- 前置通知 -->             <aop:before pointcut-ref="performance" method="silenceCellPhons"/>                        <!-- 前置通知 -->             <aop:before pointcut-ref="performance" method="takeSeats"/>                          <!-- 后置通知  -->             <aop:after pointcut-ref="performance" method="applause"/>                        <!-- 异常时 -->             <aop:after-throwing pointcut-ref="performance" method="demandRefund"/>                                  <!-- 环绕通知的切点 -->                <aop:pointcut id="performanceSurround" expression="execution(* springActualCombat.aop.xmlMode.Performance.performSurround(..))"/>               <!-- 声明环绕通知 -->            <aop:around pointcut-ref="performanceSurround" method="watchPerformance"/>              <!-- 带参数的通知 -->            <aop:pointcut id="singCount" expression="execution(* springActualCombat.aop.xmlMode.Performance.singingCount(int)) and args(singCount)" />            <aop:before pointcut-ref="singCount" method="performanceCount"/>          </aop:aspect>      </aop:config>

3. 总结

不管你是使用JavaConfig还是XML,Aspect J自动代理都会为使用@Aspect注解的bean 创建一个代理,这个代理会围绕着所有该切面的切点所匹配的bean 。在这种情况下,将会为Concertbean 创建一个代理,Audience类中的通知方法将会在perform()调用前后执行。