Spring AOP面向切面编程实现日志功能
首先我们引入日志slf4j相关依赖
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>2.0.9</version> 
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-slf4j2-impl</artifactId>
      <version>2.20.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>2.20.0</version>
    </dependency>
再引入spring-aop依赖
	<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.3.23</version>
    </dependency>
为了方便编码,lombok也是必不可少的
	<dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.34</version>
      <scope>provided</scope>
    </dependency>
我们创建以下类,就能用切面对user相关的功能进行权限控制
@Aspect
@Component
public class UserAspect {
    private static final Logger logger = LoggerFactory.getLogger(UserAspect.class);
    private UserCache cache;
    public UserAspect(UserCache cache) {
        this.cache = cache;
    }
    @After("execution(* com.homework.UserServiceImpl.*(..))")
    public void logMethodAccess(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        logger.debug("方法名: {}, 参数: {}", methodName, args);
    }
    @Around("execution(* com.homework.UserServiceImpl.addUser(..)) || " +
            "execution(* com.homework.UserServiceImpl.deleteUser(..))")
    public Object checkPermission(ProceedingJoinPoint joinPoint) throws Throwable {
        if (!"admin".equals(cache.getUserName())) {
            logger.warn("权限不足: 当前用户 {} 无法执行 {}", cache.getUserName(), joinPoint.getSignature().getName());
            return false;
        }
        return joinPoint.proceed();
    }
}
其中@After和@Before注释的方法可以看作是execution里的方法的前置操作以及后置操作,无论是否有异常都会进行,无法控制中间方法的进行与否。
 三者的主要功能如下
 @After可以进行资源释放、日志记录等功能
 @Before可以进行参数校验、日志记录等功能
 @Around方法会完全控制目标方法,可以进行权限检查、性能监控、事务管理等功能
 如果需要完全控制目标方法的执行,使用 @Around
 如果只需要在目标方法执行前或后做一些操作,使用 @Before或 @After
 其中@Around方法的传入参数是ProceedingJoinPoint,这个方法和其它两种注解的传入参数的最大区别就是它会控制进程,只有返回 joinPoint.proceed() 了才会让这个方法继续进行,否则将会直接停止,而其它两种方法的返回值是 void 它们无法影响到方法的执行与停止。
