Spring AOP知识点复习

CY 2018年02月03日 667次浏览

概念

对于重复的代码,或者已经写好的方法想要扩展,可以使用动态代理的方式来进行增强,如果待增强的类实现了接口,那么可以使用JDKProxy,如果待增强的类没有接口,可以使用CglibEnhancer.create()

Joinpoint 连接点:可以插入切面的点,Spring中就是方法

Pointcut 切入点:待增强的连接点,例如execution(* *..*.*(..))

Advice 通知/增强:增强要做的事情,前置,后置,异常,最终,环绕

Aspect 切面:是PointcutAdvice 的结合

使用XML配置AOP

aop:config 标签: 用于声明开始 aop 的配置

aop:config的子标签aop:pointcut :用于配置切入点表达式,表达式用于指定对哪些类的哪些方法进行增强

aop:config的子标签aop:aspect 标签:用于配置切面 @Aspect

  • id:给切面一个唯一标识
  • ref:引用做通知的类,称为通知类Advice,我习惯用后缀Advice命名类

aop:aspect 的子标签:

  • aop:before:用于配置前置通知
  • aop:after:用于配置后置通知
  • aop:after-returning:用于配置最终通知
  • aop:after-throwing:用于配置异常通知
  • aop:around : 环绕通知,在增强方法中需要使用ProceedingJoinPoint接口,来控制目标方法何时执行,例子

他们都有以下的几个属性:

  • method:用于规定对应的通知类中增强方法的名称
  • pointcut-ref:用于指定aop:pointcutid的引用(表达式)
  • poinitcut :如果没有上面的ref,这里可以直接指定切入点表达式

切入点表达式的说明

execution表达式语法:

execution([修饰符] 返回值类型 包名.类名.方法名(参数))

写法:

  • 全匹配方式

    public void com.cy.Service.methodName(com.cy.Param)
    
  • 访问修饰符可以省略

    void com.cy.Service.methodName(com.cy.Param)
    
  • 返回值可以使用*号,表示任意返回值

    * com.cy.Service.methodName(com.cy.Param)
    
  • 包名可以使用*号,表示任意包,但是有几级包,需要写几个*

    * *.*.Service.methodName(com.cy.Param)
    
  • 使用..来表示当前包,及其子包

    * com..Service.methodName(com.cy.Param)
    
  • 类名可以使用*号,表示任意类

    * com..*.methodName(com.cy.Param)
    
  • 方法名可以使用*号,表示任意方法

    * com..*.*(com.cy.Param)
    
  • 参数列表可以使用*,表示参数可以是任意数据类型,但是必须有参数

    * com..*.*(*)
    
  • 参数列表可以使用..表示有无参数均可,有参数可以是任意类型

    * com..*.*(..)
    
  • 全通配方式

    * *..*.*(..)
    

环绕通知的实现方式

/**
 * 环绕通知
 *
 * @param joinPoint 
 * Spring提供了一个接口: ProceedingJoinPoint
 * 它可以作为环绕通知的方法参数
 * 在环绕通知执行时,Spring 框架会为我们提供该接口的实现类对象
 */
public Object aroundMethod(ProceedingJoinPoint joinPoint) {
    // 定义返回值
    Object returnValue = null;
    try {
        // 获取方法执行所需的参数
        Object[] args = joinPoint.getArgs();
        // 前置通知...
        returnValue = joinPoint.proceed(args); //执行方法
        // 后置通知...
    } catch (Throwable e) {
        // 异常通知...
        e.printStackTrace();
    } finally {
        // 最终通知...
    }
    return returnValue;
}

注解AOP

首先主要将自定义的Advice类上面加上@Component注解,然后加上@Aspect来表示当前类是一个切面类

然后将下面的注解用在Advice类的方法上

@Before前置通知

@After后置通知

@AfterReturning最终通知

@AfterThrowing异常通知

@Around环绕通知,参数中自动注入ProceedingJoinPoint

@Pointcut切入点表达式

// 下面代码定义切入点表达式
// 其他注解引用的时候一定要带上括号,例如@Around("servicePointcut()")
@Pointcut("execution(* com.cy.service.*.*(..))")
private void servicePointcut() {}

@EnableAspectJAutoProxy使用注解启用AOPSpringBoot项目可以不加,但是需要导入spring-boot-starter-aop,如果使用了SpringDataJPA就不用导入了