Spring AOP面向切面编程实现日志功能

首先我们引入日志slf4j相关依赖


    <dependency>
      <groupId>org.slf4jgroupId>
      <artifactId>slf4j-apiartifactId>
      <version>2.0.9version> 
    dependency>
    <dependency>
      <groupId>org.apache.logging.log4jgroupId>
      <artifactId>log4j-slf4j2-implartifactId>
      <version>2.20.0version>
    dependency>
    <dependency>
      <groupId>org.apache.logging.log4jgroupId>
      <artifactId>log4j-coreartifactId>
      <version>2.20.0version>
    dependency>

再引入spring-aop依赖

	<dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-aopartifactId>
      <version>5.3.23version>
    dependency>

为了方便编码,lombok也是必不可少的

	<dependency>
      <groupId>org.projectlombokgroupId>
      <artifactId>lombokartifactId>
      <version>1.18.34version>
      <scope>providedscope>
    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 它们无法影响到方法的执行与停止。

你可能感兴趣的:(Java后端,spring,单元测试,java)