springAop实现自定义注解功能

71 阅读1分钟

定义注解

package com.example.studydemo2.annotion;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
}

引入所需要的切面依赖

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

定义aspect切面类

@Around 环绕通知,@Before(前置通知), @After(后置通知)

joinPoint需要调用,并将结果返回,否则返回的是空数据

package com.example.studydemo2.config.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Component //交由ioc管理
@Aspect //声明该类是个切面类
@Slf4j
public class LogAspect {
    @Around("@annotation(com.example.studydemo2.annotion.Log)")//环绕通知
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        //joinPoint指向目标方法
        log.info("doAround--->{}", System.currentTimeMillis());
        log.info("signature--->{}", joinPoint.getSignature().getName());
        //获取方法参数列表
        Object[] args = joinPoint.getArgs();
        //拿到方法所在的类的信息
        //获取类的字节码对象,通过字节码对象获取方法信息
        Class<?> targetCls = joinPoint.getTarget().getClass();
        //获取方法签名(通过此签名获取目标方法信息)
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        //获取目标方法上的注解指定的操作名称
        Method targetMethod =
                targetCls.getDeclaredMethod(
                        ms.getName(),//方法名
                        ms.getParameterTypes());
        //从方法上拿到Log.class的注解
        Log requiredLog =targetMethod.getAnnotation(Log.class);
        String operation = requiredLog.value();//拿到注解上的值
        System.out.println("targetMethod=" + targetMethod);
      	Object result=joinPoint.proceed()//调用目标方法
        for (Object arg : args) {
            log.info("参数{}", (String) arg);
        }
        return result;
    }
}
// 当需要注入对应注解的对象时,可以使用如下方式,将对应注解的首字母小写填入`@annotation`
@Around("@annotation(log)")//环绕通知
// 在切面方法直接注入Log注解的对象即可
public Object doAround(ProceedingJoinPoint joinPoint,Log log) throws Throwable {

}

使用注解

package com.example.studydemo2.controller;

import com.example.studydemo2.annotion.Log;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class testController {
    @GetMapping()
    @Log
    public String test(String name) {
        return "test" + name;
    }
}