Spring 中 AOP 使用

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {

}

或xml中配置

<aop:aspectj-autoproxy/>

声明一个 Aspect

@Aspect
@Component
public class NotVeryUsefulAspect {
}

声明一个切点

@Pointcut("execution(* transfer(..))")// the pointcut expression
private void anyOldTransfer() {}// the pointcut signature

支持的切点类型

  • execution
  • within
  • this
  • target
  • args
  • @target
  • @args
  • @within
  • @annotation

组合切点

@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {}

@Pointcut("within(com.xyz.someapp.trading..*)")
private void inTrading() {}

@Pointcut("anyPublicOperation() && inTrading()")
private void tradingOperation() {}

spring doc

增强

Before

@Aspect
public class BeforeExample {

    @Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
    public void doAccessCheck() {
        // ...
    }

}

AfterReturning

	@AfterReturning("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
    public void doAccessCheck() {
        // ...
    }

获取返回的对象

    @AfterReturning(
        pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",
        returning="retVal")
    public void doAccessCheck(Object retVal) {
        // ...
    }

AfterThrowing

    @AfterThrowing("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
    public void doRecoveryActions() {
        // ...
    }
    @AfterThrowing(
        pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",
        throwing="ex")
    public void doRecoveryActions(DataAccessException ex) {
        // ...
    }

After

    @After("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
    public void doReleaseLock() {
        // ...
    }

Around

    @Around("com.xyz.myapp.SystemArchitecture.businessService()")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
        // start stopwatch
        Object retVal = pjp.proceed();
        // stop stopwatch
        return retVal;
    }

例子

package com.example.value.demo;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Aspect
@Component
public class LogAspectJ {
    @Pointcut("execution(* com.example.value.demo.HelloService*.*(..))")
    public void publicPoint() {

    }

    @Around("publicPoint()")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
        // start stopwatch
        System.out.println("调用方法 : " + pjp.getSignature().toLongString());
        System.out.println("方法参数 : " + Arrays.toString(pjp.getArgs()));
        Object retVal = pjp.proceed();
        // stop stopwatch
        System.out.println("方法返回 : " + retVal);
        return retVal;
    }
}