需求:通过spring aop 提供的面向切面编程的思想,利用自定义注解的方式,实现对接口的功能的增强
一:自定义一个注解类
- @Document:指明修饰的注解,可以被类似javadoc之类的工具类文档化,只负责标记,没有成员取值
- @Retention:指明修饰注解的生存周期,即会保留到哪个阶段
- RetentionPolicy的取值包含以下三种
-
SOURCE:源码级别保留,编译后即丢弃
-
CLASS:编译级别的保留,编译后的class文件中存在,在jvm运行时丢弃,这是默认值
-
RUNTIME:运行级别的保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用
-
- RetentionPolicy的取值包含以下三种
- @Target:指明了修饰的这个注解的使用范围,即被描述的注解可以用在哪里
- ElementType的取值包含以下几种:
-
TYPE:类,接口,枚举
-
FIELD:字段声明,包含枚举常量
-
METHOD:方法
-
PARAMETER:参数
-
CONSTRUCTOR:构造方法
-
LOCAL_VARIABLE:局部变量
-
ANNOTATION_TYPE:注解类型
-
PACKAGE:包
-
- ElementType的取值包含以下几种:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
String lockKey();
String cacheKey();
}
二:切面逻辑
@Aspect
@Component
public class AopCache {
@Pointcut("@annotation(com.example.demo.anno.MyAnnotation) && within(com.example.demo..*)")
public void addAdvice(){}
@Around("addAdvice()")
public Object Interceptor(ProceedingJoinPoint pjp) throws Throwable {
try {
Method targetMethod = this.getTargetMethod(pjp);
MyAnnotation annotation = targetMethod.getAnnotation(MyAnnotation.class);
String cacheKey = annotation.cacheKey();
String lockKey = annotation.lockKey();
//spel获取自定义注解参数值
ExpressionParser parser = new SpelExpressionParser();
LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
String[] params = discoverer.getParameterNames(targetMethod);
Object[] args = pjp.getArgs();
EvaluationContext context = new StandardEvaluationContext();
for (int len = 0; len < params.length; len++) {
context.setVariable(params[len], args[len]);
}
Expression expression = parser.parseExpression(lockKey);
String id = expression.getValue(context, String.class);
expression = parser.parseExpression(cacheKey);
String number = expression.getValue(context, String.class);
System.out.print("cacheKey: "+number+" ,lockKey: "+id);
if (lockKey.equals("abc")){
return "hello world!!";
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return pjp.proceed();
}
private Method getTargetMethod(ProceedingJoinPoint pjp) throws NoSuchMethodException {
Signature signature = pjp.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
return pjp.getTarget().getClass().getMethod(method.getName(),method.getParameterTypes());
}
}
三:controller测试类
@RestController
@RequestMapping("/web")
public class DemoController {
@MyAnnotation(lockKey = "#id",cacheKey = "#number")
@RequestMapping("/add1")
public Object getOgj(String id,String number){
System.out.print(id+" --- "+number);
return "success...";
}
@MyAnnotation(lockKey = "#id",cacheKey = "#number")
@RequestMapping("/add3")
public String addData3(String id,String number) {
System.out.print(id+" --- "+number);
return "success";
}
@RequestMapping("/add4")
public String addData4(String id,String number) {
System.out.println();
System.out.print(id+" --- "+number);
return "success";
}
}