Skip to content

AOP

约 536 字大约 2 分钟

2024-12-25

面向切面编程,

编写切面

@Around("@annotation(cn.lut.imserver.aop.Monitored) || @within(cn.lut.imserver.aop.Monitored)") 标记切入点,@annotation标记表示拦截 Monitored 注解的方法,@within标记表示该注解类中的所有方法

对于使用被切面标记的注释的 bean,其在初始化时会被创建代理类,此后该 bean 被调用时都会经过切面进行处理

ProceedingJoinPoint 代理对象被调用时会创建该类,构建拦截器链,将该对象交给切面进行处理

@Slf4j  
@Aspect  
@Component  
public class ControllerLoggingAspect {  
  
    @Around("@annotation(cn.lut.imserver.aop.Monitored) || @within(cn.lut.imserver.aop.Monitored)")  
    public Object logAround(ProceedingJoinPoint pjp) {  
        MethodSignature sig = (MethodSignature) pjp.getSignature();  
        String className = sig.getDeclaringType().getSimpleName();  
        String methodName = sig.getName();  
        String method = className + "." + methodName;  
        log.info("Invoke method {}", method);  
        long start = System.currentTimeMillis();  
        try {  
            return pjp.proceed();  
        } catch (Throwable e) {  
            throw new RuntimeException(e);  
        } finally {  
            long end = System.currentTimeMillis();  
            log.info("Method {} end with {} ms", method, end - start);  
        }  
    }  
}

概念

切面

通知+切入点,在什么地方 (切入点),执行什么逻辑 (通知)

连接点

程序中可以被拦截的执行点

切入点

匹配某些连接点的表达式,用于从连接点中选出需要增强的的点

@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethod() {}

匹配com.example.service包下的所有所有的方法,讲这些方法作为需要增强的点

  • execution():方法执行切入点
  • 第一个*:表示任意返回类型
  • com.example.service:包路径
  • 包路径.*:该包下的任意类
  • 包路径.*.*:类中的任意方法
  • (..):任意参数列表

通知

对于匹配的连接点执行的增强逻辑

前置通知

在方法执行前

@Before("execution(* cn.codeartist.spring.aop.advice.*.*(..))")
public void doBefore() {
 // 自定义逻辑
}

环绕通知

获取切入点(对代理类的控制),定义方法执行前后的逻辑,如果不执行joinPoint.proceed(),那么该方法将不会执行

@Around("execution(* cn.codeartist.spring.aop.advice.*.*(..))")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
 // 方法执行前逻辑
 Object retVal = joinPoint.proceed();
 // 方法执行后逻辑
 return retVal;
}

后置通知

方法正常返回后

@AfterReturning("execution(* cn.codeartist.spring.aop.advice.*.*(..))")
 public void doAfterReturning() {
     // 自定义逻辑
 }

工作原理

为被切入点规则匹配的连接点创建代理类(JDK 或 CGLIB),这些类中的方法被调用时,