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

1. Spring AOP 术语

这里写图片描述

这里写图片描述


2. 使用Spring AOP

2.1 java 方式

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

@Configurable
@EnableAspectJAutoProxy //启用 AspectJ自动代理
@ComponentScan
public 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()调用前后执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值