美文网首页
SpringBoot开发随记--AOP的使用

SpringBoot开发随记--AOP的使用

作者: 我有一只喵喵 | 来源:发表于2019-01-04 15:26 被阅读0次

    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 是因为存在环绕通知,在没有环绕通知下可以取到返回值

    相关文章

      网友评论

          本文标题:SpringBoot开发随记--AOP的使用

          本文链接:https://www.haomeiwen.com/subject/sodhrqtx.html