spring 中aop 切面实战

切面相关注解:

@Aspect : 声明该类为一个注解类

@Pointcut : 定义一个切点

@Before : 在切点之前执行

@After : 在切点之后执行 不管目标方法是否执行成功

@AfterReturning : 切点返回内容后执行代码,可以对切点的返回值进行封装

@AfterThrowing : 切点抛出异常后执行

@Around : 环绕,在切点前后执行代

1.自定义注解:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface timingAnnotation {
}

2.切面类

@Aspect
@Component
@Slf4j
public class AspectDemo {

    @Pointcut("@annotation(com.wl.demo.demos.aop.timingAnnotation)")
    public void pointCut() {
    }

    @Before("pointCut()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        log.info("IP: {}", request.getRemoteAddr());
        log.info("URL: {}", request.getRequestURL().toString());
        log.info("HTTP Method: {}", request.getMethod());
        log.info("Class Method: {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
    }

    @Around("pointCut()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
        Object proceed = proceedingJoinPoint.proceed();
        long endTime = System.currentTimeMillis();
        log.info("[方法耗时]" + methodSignature.getDeclaringTypeName() + "." + methodSignature.getMethod().getName() + " 耗时: " + (endTime - startTime) + "毫秒");
        return proceed;
    }


    @After("pointCut()")
    public void doAfter(JoinPoint joinPoint) {
        log.info("目标方法执行完之后执行");
    }

    @AfterThrowing(pointcut = "pointCut()", throwing = "e")
    public void doAfterThrow(JoinPoint joinPoint, RuntimeException e) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        log.info("HTTP Method: {}", request.getMethod());
        log.info("Class Method: {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
    }

}

注:引入aspect 需要引入jar:

<!--引入aop aspectj-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>

 补充: 记录调用接口的请求信息

@Slf4j
@Aspect
@Component
public class LogAspect {
    @Autowired
    private LogMapper logMapper;

    @AfterReturning(returning = "obj" ,pointcut ="@annotation(com.chunmi.store.provider.order.annotation.StoreLog)" )
    public void saveLog(JoinPoint joinPoint, Object obj) {
        Log log = new Log();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        StoreLog sysLogAnnotation = method.getAnnotation(StoreLog.class);
        //获取请求的类名
        String className = joinPoint.getTarget().getClass().getName();
        //获取请求的方法名
        String methodName = method.getName();
        log.setRequestMethod(className + "." + methodName);
        //请求的参数
        Object[] args = joinPoint.getArgs();
        log.setRequestData(JSON.toJSONString(args));
     //接口返回信息obj log.setResponseData(JSON.toJSONString(obj)); logMapper.insert(log); } }

 注解放在接口实现的普通方法上失效情况:是由于接口实现方法中调用其他的方法并未实现代理,可以通过((类名)AopContext.currentProxy()).method() 加入代理实现,类上添加注解@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)

 

原文地址:https://www.cnblogs.com/wlong-blog/p/13857806.html