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

1. Spring AOP 术语

Spring核心机制(面向切面编程AOP)详解_第1张图片

Spring核心机制(面向切面编程AOP)详解_第2张图片


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
Spring核心机制(面向切面编程AOP)详解_第3张图片

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>
          
          <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()调用前后执行。

你可能感兴趣的:(spring)