AOP 面向切面编程

核能气质少年 提交于 2020-02-26 07:02:25

1、AspectJ  补充了SpringAOP的功能.

2、AOP术语:

通知 advice:就等于用于切面的方法

连接点 join point: 在方法的什么时候通知,比如调用前,抛出异常时,甚至修改一个字段时。

切点 poincut: 明确或者正则来匹配在哪些类,哪些方法名,来应用通知。

切面 Aspect:通知和切点组成了一个切面。

引入 Introduction:引入允许我们向现有的类添加新方法或属性。

织入 weaving:  织入是把切面应用到目标对象并创建新的代理对象的过程。

                 编译时织入:需要特殊的编译器,AspectJ就时用这种方式织入

                 类加载器: 需要特殊的类加载器,AspectJ5 (load-time weaving)LTW支持这种方式

                 运行期:  运行期动态创建一个代理类,来完成织入SpringAOP的做法。

3、Spring 提供了4中类型的AOP支持   (Spring大量借鉴了AspectJ)

*基于代理的经典SpringAOP

*纯POJO 切面     (本质上还是基于代理的AOP,需要XML 配置)

*@AspectJ注解驱动的切面   (本质上还是基于代理的AOP,但是可以用类似AspectJ的方式,以注解的方式完成配置)

@注入式AspectJ切面(适用于Spring各版本,如果你的需求不仅仅是简单的方法调用,如构造器和属性拦截)

4、指示器语法

Spring使用了部分的AspectJ指示器。 除了execution是实际执行指示器,其他全是限制指示器。

例1:   execution(  *  com.XXX.method(..) )

第一段 指示器类型,说明在方法执行时触发;第二段 说明返回任意类型;第三段 方法所属的类;第四段 方法名;第五段 代表任何参数

 

例2:   execution(  *  com.XXX.method(..) ) && within (concert.*)

这种方式,额外增加了一个包限制,  第六段  && 代表(and、和);第七段被限制的包名

类似的  除了&& 和,还可以使用 ||  或 ,!  非, 来标识关系。 

因为& 在XML中有特殊含义,我们在XML中配置的时候可以使用 and、or、not

 

 例3:   execution(  *  com.XXX.method(..) ) and !bean ('apple')

切面的通知会被织入到所有ID不为 apple的bean中

 

5、使用注解来创建切面,AspectJ5新特性。

 

@After   方法返回或抛出异常后调用

@AferReturning  方法返回后调用

@AferThrowing 抛出异常后调用

@Around  将方法包围起来

@before    方法执行前执行

 

5、创建切面的两种方法

1)例子如下    

@Aspect
public class Audience{

   @Before("execution(** com.xsx.XXXMehtod(..))")
   public void method1(){
        Sytem.out.println("excute method1");
   }

   @AfterThrowing("execution(** com.xsx.XXXMehtod(..))")
   public void method2(){
        Sytem.out.println("excute method2");
   }

}

2)例子如下:   我们发现第一个例子中的指示器相同,这样我们可以把指示器提取出来

@Aspect
public class Audience{

   @Pointcut("execution(** com.xsx.XXXMehtod(..))")
   public void method(){
       //方法体中的内容没有任何意义,  空的就可以
   }

   @Before("method()")
   public void method1(){
        Sytem.out.println("excute method1");
   }

   @AfterThrowing("method()")
   public void method2(){
        Sytem.out.println("excute method2");
   }

}

为了使切面生效,如果我们使用javaConfig的话,我们还需要配置@EnableAspectJAutoProxy;如果使用xml的配置  <aop:aspectJ-autoproxy  />

3)例子如下(环绕通知)

@Aspect
public class Audience{

   @Pointcut("execution(** com.xsx.XXXMehtod(..))")
   public void method(){
       //方法体中的内容没有任何意义,  空的就可以
   }

   @Aroud("method()")
   public void watchPerformance(ProceedingJoinPoint jp){
       try{
          System.out.println("Silencing cell phones");
          System.out.println("taking seats");
          jp.proceed();
          System.out.println("CLAP CLAP CLAP");
       }catch(Throwable e){
          System.out.pringln("Demanding a refund");
       }
   }
}
//对于 环绕切面,注意到参数 ProceedingJoinPoint,  执行jp.proceed(),将控制权交给被通知的方法。如果不调用,通知的方法将被阻塞。可以利用这种特性,实现一种逻辑,再被通知方法失败后,进行重复尝试。

环绕通知的另一个好处,

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!