使用 AOP(面向切面编程)和自定义注解实现日志记录

一、导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

二、定义自定义注解 

@Target(作用在类、字段或方法)

@Rentention(一般选Runntime)

@Retention(RetentionPolicy.RUNTIME)//定义注解的使用范围,编译时,还是运行时。。。
@Target(ElementType.METHOD)//定义注解用在哪里class,method。。。
public @interface Login {
    String value() default "";
}

三、注解贴在需要的地方

四、切点表达式 拿注解

作用域 切点表达式 切点表达式
作用在字段上 get
作用在方法上 @annotation 只能用于选择带有特定注解的方法作为连接点 execution 则可以根据更多的方法特征进行匹配。比如参数、方法名
作用在类上 within

@Around、@Before和@AfterReturning 是方法级别的三个注解。

其中@Around是在方法执行前后,如果方法执行失败了,可以捕捉异常,自己处理,或者抛出。如果抛出,则不再执行后续代码。

@Before在方法执行前

@AfterReturning 是在方法成功返回后(如果执行失败,抛异常,不执行这个切面方法)

以下以自定义注解,做全局日志记录为例 ,展示作用在方法上的注解,的@Around使用形式。

@Aspect
@Component
public class SystemLogAspect {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(SystemLogAspect.class);

    @Around("@annotation(com.example.annotation.SystemLog)")
    public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();

        SystemLog systemLog = method.getAnnotation(SystemLog.class);
        String message = systemLog.value();

        Long startTime = System.currentTimeMillis();
        Object result;
        try {
            result = joinPoint.proceed();
        } catch (Throwable throwable) {
            throw throwable;
        } finally {
            Long endTime = System.currentTimeMillis();
            long time = endTime - startTime;
            
            LOGGER.info("[SystemLog] {}.{}: {}ms", 
                joinPoint.getTarget().getClass().getName(), 
                method.getName(), time);
        }
        return result;
    }
}

猜你喜欢

转载自blog.csdn.net/tomorrow9813/article/details/131412127