自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by krun on 2017/9/18.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Foo {
String value();
}
自定义拦截器
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Date;
import java.util.Map;
/**
* 监听注解,并修改注解属性
*
* @author author
*/
// @Slf4j
@Aspect
@Component
public class MyAspect {
/**
* 获取注解参数当做方法入参
*
* @param joinPoint 切点方法
* @param annotationParameter 注解参数,要拦截的注解类型
* @return 方法执行的返回值
*/
@Around("@annotation(annotationParameter)")
@SuppressWarnings("unchecked")
public Object doAround(ProceedingJoinPoint joinPoint, Foo annotationParameter) {
try {
// 获取注解value属性的原值
String beforeValue = annotationParameter.value();
System.out.println("beforeValue = " + beforeValue);
// 获取注解参数的调用处理器
InvocationHandler handler = Proxy.getInvocationHandler(annotationParameter);
// AnnotationInvocationHandler 实现 InvocationHandler,
// 通过调用处理器获取AnnotationInvocationHandler的memberValues字段,该字段存储注解实例的所有属性键值对
Field memberValuesField = handler.getClass().getDeclaredField("memberValues");
memberValuesField.setAccessible(true);
// 获取该实例的所有属性键值对
Map memberValues = (Map) memberValuesField.get(handler);
// 为注解实例的value属性赋新值
memberValues.put("value", beforeValue + new Date().toString());
} catch (Exception e) {
System.out.println("赋值失败");
throw new RuntimeException("赋值失败");
}
Object proceed;
try {
proceed = joinPoint.proceed();
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
return proceed;
}
}
使用实例
import com.itheima.spring.Foo;
import org.springframework.stereotype.Controller;
@Controller("clientController")
public class ClientController {
@Foo(value = "2")
public void test() {
}
}
日志结果
修复拦截器bug
上述拦截器会将修改后的值永久保存给注解属性,再次访问该方法时,会在第一次修改完的基础上再次修改,多次使用将无限叠加,如果想每次使用完恢复原值,可以使用下面的拦截器
import com.pig4cloud.plugin.excel.annotation.ResponseExcel;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Map;
/**
* 拦截ResponseExcel注解,并修改name属性
*
* @author zhaoliyan
* @date 2021/9/2 08:55
*/
@Slf4j
@Aspect
@Component
public class ResponseExcelAnnotationAspect {
/**
* 拦截ResponseExcel注解,并修改name属性
*
* @param annotationParameter ResponseExcel注解实例
*/
@Before("@annotation(annotationParameter)")
public void doBefore(ResponseExcel annotationParameter) {
try {
// 获取ResponseExcel注解name属性的原值
String beforeValue = annotationParameter.name();
setName(annotationParameter, beforeValue + LocalDate.now().format(DateTimeFormatter.ofPattern("_yyyyMMdd")));
} catch (Exception e) {
log.error("ResponseExcel注解name属性赋新值失败");
throw new RuntimeException("ResponseExcel注解name属性赋新值失败");
}
}
/**
* 拦截ResponseExcel注解,并恢复name属性
*
* @param annotationParameter ResponseExcel注解实例
*/
@After("@annotation(annotationParameter)")
public void doAfter(ResponseExcel annotationParameter) {
try {
// 获取ResponseExcel注解name属性修改后的值
String afterValue = annotationParameter.name();
setName(annotationParameter, afterValue.substring(0, afterValue.lastIndexOf("_")));
} catch (Exception e) {
log.error("ResponseExcel注解name属性恢复原值失败");
throw new RuntimeException("ResponseExcel注解name属性恢复原值失败");
}
}
/**
* 修改ResponseExcel注解name属性值
*
* @param annotationParameter ResponseExcel注解实例
* @param value name属性新值
*/
@SuppressWarnings("unchecked")
private void setName(ResponseExcel annotationParameter, String value) throws NoSuchFieldException, IllegalAccessException {
// 获取注解参数的调用处理器
InvocationHandler handler = Proxy.getInvocationHandler(annotationParameter);
// AnnotationInvocationHandler 实现 InvocationHandler,
// 通过调用处理器获取AnnotationInvocationHandler的memberValues字段,该字段存储注解实例的所有属性键值对
Field memberValuesField = handler.getClass().getDeclaredField("memberValues");
memberValuesField.setAccessible(true);
// 获取该实例的所有属性键值对
Map<String, Object> memberValues = (Map<String, Object>) memberValuesField.get(handler);
// 为注解实例的name属性赋新值
memberValues.put("name", value);
}
}