SpringBoot开发随记--AOP的使用

SpringBoot开发随记--AOP的使用


Aop原理

1、什么是Aop

aop 全称 Aspect Oriented Programming,面向切面,AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。其与设计模式完成的任务差不多,是提供另一种角度来思考程序的结构,来弥补面向对象编程的不足。

AOP技术利用一种称为“横切”的技术,解剖封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,这样就能减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。


2、AOP常用术语

  • 切面Aspect-----通常是一个类,里面可以定义切入点和通知
    一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。在Spring AOP中,切面可以使用基于模式或者基于@Aspect注解的方式来实现。

  • 连接点Joinpoint
    在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。在Spring AOP中,一个连接点总是表示一个方法的执行。

  • 通知Advice
    在切面的某个特定的连接点上执行的动作。其中包括了“around”、“before”和“after”等不同类型的通知(通知的类型将在后面部分进行讨论)。许多AOP框架(包括Spring)都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链

  • 切入点Pointcut
    匹配连接点的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时)。切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法。

  • 引入introduction
    用来给一个类型声明额外的方法或属性(也被称为连接类型声明(inter-type declaration))。Spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。例如,你可以使用引入来使一个bean实现IsModified接口,以便简化缓存机制。

  • **目标对象Target Object **
    被一个或者多个切面所通知的对象。也被称做被通知(advised)对象。既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理(proxied)对象。

  • Aop代理
    AOP框架创建的对象,用来实现切面契约(例如通知方法执行等等)。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

  • 织入 Weaving
    把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

3、AOP execution表达式语法

execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)

  • 表达式示例:execution(* com.package..*. * (..))
标识符 含义
execution() 表达式的主体
第一个“*”符号 表示返回值的类型任意
com.package AOP所切的服务的包名,即,需要进行横切的业务类
包名后面的“..” 表示当前包及子包
第二个“*” 表示类名,*即所有类
.*(..) 表示任何方法名,括号表示参数,两个点表示任何参数类型

不同维度的描述

  • 通过注解定义切点
  • @annotation( 注解的路径)
  • 通过方法修饰符定义切点

匹配所有的public修饰符的方法:

  • execution(public * *(..))
  • 通过方法名定义切点

匹配所有”set”开头的方法:

  • execution(* set*(..))
  • 通过类定义切点

匹配AccountService 接口的所有方法:

  • execution(* com.xyz.service.AccountService.*(..))
  • 通过包定义切点

匹配service包中的所有类的方法:

  • execution(* com.xyz.service.*(..))

匹配service包及其子包中的所有方法:

  • execution(* com.xyz.service..*(..))

4、AOP通知类型

1、Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可

2、AfterReturning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值

3、AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名来访问目标方法中所抛出的异常对象

4、After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式

5、Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint

代码示范


@Component
@Aspect
public class AOPTest {


   /**
    * 定义一个切入点
    */
   @Pointcut("execution(* cn.hhu..bbs..*.*(..))")
   public void pointcut1(){}

   @Before("pointcut1()")
   public void before(JoinPoint joinPoint){

       System.out.println("before");
   }
   @After("pointcut1()")
   public void after(JoinPoint joinPoint){
       System.out.println("after");

   }
   @AfterReturning(pointcut = "pointcut1()",returning = "returnVal")
   public void afterReturning(JoinPoint joinPoint,Object returnVal){

       System.out.println("afterReturning:result+"+returnVal);

   }

   @Around("pointcut1()")
   public void around(ProceedingJoinPoint proceedingJoinPoint){
       System.out.println("around 前");
       try {
           proceedingJoinPoint.proceed();
       } catch (Throwable throwable) {
           throwable.printStackTrace();
       }
       System.out.println("around后");
   }
}
around 前
before
执行方法体
around后
after
afterReturning:result+null
这里 AfterReturing 的返回值为null 是因为存在环绕通知,在没有环绕通知下可以取到返回值

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容