java反射:动态修改注解上属性的值
需求:使用easypoi导出时,根据当前时间设置对应的表头信息,因为表头是通过@Excel注解中的属性进行,所以需要动态设置注解中的属性值。工具类代码如下:
package com.zkdj.common.utils.poi;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;/*** 类描述 -> 动态设置注解中的属性值** @Author: ywz* @Date: 2024/09/05*/
public class DynamicSetAnnotationValue {protected static final Logger logger = LoggerFactory.getLogger(DynamicSetAnnotationValue.class);/*** 方法描述 -> 变更注解的属性值** @param clazz 注解所在的实体类* @param tClass 注解类* @param filedName 要修改的注解属性名* @param value 要设置的属性值* @Author: ywz* @Date: 2024/09/05*/public static <A extends Annotation> Class<?> changeAnnotationValue(Class<?> clazz, Class<A> tClass, String filedName, Object value) {try {// 获取类中的所有属性Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {// 判断属性是否有指定注解A annotation = field.getAnnotation(tClass);if (annotation != null) {setAnnotationValue(annotation, filedName, value);}}} catch (Exception e) {logger.error("动态设置注解属性值失败");}return clazz;}/*** 方法描述 -> 动态设置注解的属性值, 通过指定的其他属性名和对应的值来设置** @param clazz 注解所在的实体类* @param tClass 注解类* @param assignProperty 指定的属性名* @param assignValues 指定的属性值(可以对多个不同的值进行设置)* @param filedName 要修改的注解属性名* @param value 要设置的属性值* @Author: ywz* @Date: 2024/09/05*/public static <A extends Annotation> Class<?> changeAnnotationValueByAssignProperty(Class<?> clazz, Class<A> tClass, String assignProperty, List<String> assignValues, String filedName, Object value) {try {// 获取类中的所有属性Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {// 判断属性是否有指定注解A annotation = field.getAnnotation(tClass);if (annotation != null) {String annotationValue = (String) getAnnotationValue(annotation, assignProperty);assignValues.forEach(assignValue -> {// 判断是否是要设置属性值的注解if (annotationValue.equals(assignValue)) {try {setAnnotationValue(annotation, filedName, value);} catch (NoSuchFieldException | IllegalAccessException e) {throw new RuntimeException(e);}}});}}} catch (Exception e) {logger.error("动态设置注解属性值失败");}return clazz;}/*** 方法描述 -> 设置注解中的字段值** @param annotation 要修改的注解实例* @param fieldName 要修改的注解属性名* @param value 要设置的属性值* @Author: ywz* @Date: 2024/09/05*/private static void setAnnotationValue(Annotation annotation, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {InvocationHandler handler = Proxy.getInvocationHandler(annotation);Field field = handler.getClass().getDeclaredField("memberValues");field.setAccessible(true);Map memberValues = (Map) field.get(handler);memberValues.put(fieldName, value);}/*** 方法描述 -> 获取注解中的属性值** @param annotation 要获取的注解实例* @param fieldName 要获取的注解属性名* @Author: ywz* @Date: 2024/09/05*/private static Object getAnnotationValue(Annotation annotation, String fieldName) throws NoSuchFieldException, IllegalAccessException {InvocationHandler handler = Proxy.getInvocationHandler(annotation);Field field = handler.getClass().getDeclaredField("memberValues");field.setAccessible(true);Map memberValues = (Map) field.get(handler);return memberValues.get(fieldName);}}
使用案例:导出时将第14到19列的groupName(合并单元格内容)设置为当前年份。
Class<?> exprotClass = DynamicSetAnnotationValue.changeAnnotationValueByAssignProperty(lastYearExprotClass, Excel.class, "orderNum", Arrays.asList("14", "15", "16", "17", "18", "19"), "groupName", calendar.get(Calendar.YEAR) + "年");