java注解之运行时修改字段的注解值操作

 更新时间:2020年08月22日 15:46:51   作者:蓝色土耳其18  
这篇文章主要介绍了java注解之运行时修改字段的注解值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

今天遇到需求:导入Excel时候列头会发生变化,客户是大爷要求你改代码,

导入Excel是用easypoi做的,识别表头是用注解@Excel(name = "xxx")通过这个name来匹配

那你表头要动,我这个注解是硬编码

所以就有动态设置这个表头

public class JavaVo{
@Excel(name = "xxx")
private String userName;
//省略getset方法
}

ExcelImportUtil.importExcel(file.getInputStream(), configClass(JavaVo.class), params);

代码如下

 private Class configClass(Class c , String val) {
   
   Field[] fields = c.getDeclaredFields();
   try {
  for(int i = 0;i < fields.length;i++){
  Field f = fields[i];
  Excel excelAn = f.getAnnotation(Excel.class);//Excel是注解类型
  if(excelAn == null){
   continue;
  }
  InvocationHandler h = Proxy.getInvocationHandler(excelAn);
  Field hField = h.getClass().getDeclaredField("memberValues");
    // 因为这个字段事 private final 修饰,所以要打开权限
    hField.setAccessible(true);
    // 获取 memberValues
    Map memberValues = (Map) hField.get(h);
    // 修改 value 属性值 这里修改的是@Excel(name = "姓名")
        //name是key
    memberValues.put("name", val);
  }
 } catch (Exception e) {
  e.printStackTrace();
 }
 return c;
 }

补充知识:java动态修改 注解的值,控制对象转化为json字符串的字段是否序列化

定义一个对象使用@JSONField控制该对象属性是否需要序列化

import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;

@Data
public class A {
  @JSONField(serialize = false)
  private String extendParams;

  @JSONField(serialize = true)
  private String sad;
}

编写工具类

import com.alibaba.fastjson.annotation.JSONField;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Map;
import lombok.val;

/**
 * 动态操作注解属性
 * @since 2020年8月13日20:49:26
 */
public class AnnotationUtils<T> {
  /**
   * 查看注解属性
   * @param t
   * @param name
   * @return
   * @throws NoSuchFieldException
   */
  public Object getJSONFieldProp(T t, String name) throws NoSuchFieldException {
    Field field = t.getClass().getDeclaredField(name);
    JSONField annotation = field.getAnnotation(JSONField.class);
    val serialize = annotation.serialize();
    return serialize;
  }

  /**
   * 修改注解属性
   * @param t
   * @param value
   * @return
   * @throws NoSuchFieldException
   * @throws IllegalAccessException
   */
  public Object setJSONFieldProp(T t,String name, Object value) throws NoSuchFieldException, IllegalAccessException {
    Field field = t.getClass().getDeclaredField(name);
    JSONField annotation = field.getAnnotation(JSONField.class);
    InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
    Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
    memberValues.setAccessible(true);
    Map map = (Map) memberValues.get(invocationHandler);
    map.put("serialize",value);
    val serialize = annotation.serialize();
    return serialize;
  }
}

测试

import com.alibaba.fastjson.JSON;

public class TT {

  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    AnnotationUtils<A> aAnnotationUtils = new AnnotationUtils<>();
    A a = new A();
    a.setExtendParams("exex");
    a.setSad("sadsad");

    Object extendParams = aAnnotationUtils.getJSONFieldProp(a, "extendParams");//查询注解的值
    System.out.println(extendParams.toString());
//    System.out.println(JSON.toJSONString(a));

    Object extendParams1 = aAnnotationUtils.setJSONFieldProp(a, "extendParams", true);//修改注解的值
    System.out.println(extendParams1.toString());
    System.out.println(JSON.toJSONString(a));
  }
}

去掉main里面的注解看看效果,这个好像是发生了jvm优化导致的问题。。。

注释第一个print 打印结果如下:

false
true
{"extendParams":"exex","sad":"sadsad"}

不注释第一个print 打印结果如下:

false
{"sad":"sadsad"}
true
{"sad":"sadsad"}

接下来我们在做一个测试

  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    List<A> aList = new ArrayList<>();
    for(int i=0; i<10; i++){
      AnnotationUtils<A> aAnnotationUtils = new AnnotationUtils<>();
      A a = new A();
      a.setExtendParams("exex");
      a.setSad("sadsad");
      if(i%2 == 0) {
        aAnnotationUtils.setJSONFieldProp(a, "extendParams", true);//修改注解的值
      }
      aList.add(a);
    }
    System.out.println(JSON.toJSONString(aList));
  }

打印结果

[{"extendParams":"exex","sad":"sadsad"},{"extendParams":"exex","sad":"sadsad"},{"extendParams":"exex","sad":"sadsad"},{"extendParams":"exex","sad":"sadsad"},{"extendParams":"exex","sad":"sadsad"},{"extendParams":"exex","sad":"sadsad"},{"extendParams":"exex","sad":"sadsad"},{"extendParams":"exex","sad":"sadsad"},{"extendParams":"exex","sad":"sadsad"},{"extendParams":"exex","sad":"sadsad"}]

我本想用修改注解的方式来修改某个字段的序列化与不序列化,但是我发现注解是在class层面的并不是在对象层面。所以我的设想失败了。。

以上这篇java注解之运行时修改字段的注解值操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Spring Security 构建rest服务实现rememberme 记住我功能

    Spring Security 构建rest服务实现rememberme 记住我功能

    这篇文章主要介绍了Spring Security 构建rest服务实现rememberme 记住我功能,需要的朋友可以参考下
    2018-03-03
  • 解析spring cloud ouath2中的Eureka

    解析spring cloud ouath2中的Eureka

    这篇文章主要介绍了spring cloud ouath2中的Eureka,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • 关于使用ContextClassLoader遇到的问题

    关于使用ContextClassLoader遇到的问题

    这篇文章主要介绍了关于使用ContextClassLoader遇到的问题,ContextClassLoader是通过Thread.currentThread().getContextClassLoader()返回该线程上下文的ClassLoader,需要的朋友可以参考下
    2023-10-10
  • Springboot启动后执行方法小结

    Springboot启动后执行方法小结

    本文主要介绍了Springboot启动后执行方法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • 关于Gateway网关中配置跨域的三种方案

    关于Gateway网关中配置跨域的三种方案

    文章总结:介绍了三种处理跨域请求的方法:在Controller类上添加注解、通过配置类实现重写WebMvcConfigurer接口和在配置文件中统一设置,希望这些方法能帮助读者解决跨域问题
    2024-11-11
  • springboot枚举类型传递的步骤

    springboot枚举类型传递的步骤

    这篇文章主要介绍了springboot枚举类型传递的步骤,帮助大家更好的理解和学习使用springboot,感兴趣的朋友可以了解下
    2021-04-04
  • Java文件读写详解

    Java文件读写详解

    在真实的应用场景中,很多时候需要使用 Java 读写文件。比如说,读取配置文件信息、读取用户输入等。本篇文章将会详细介绍 Java 文件读写的相关知识,其中包括:读取文件、写入文件、复制文件和删除文件等操作,需要的朋友可以参考下
    2023-05-05
  • Java 垃圾回收机制详解及实例代码

    Java 垃圾回收机制详解及实例代码

    这篇文章主要介绍了 Java 垃圾回收机制详解及实例代码的相关资料,需要的朋友可以参考下
    2017-02-02
  • Java实现简单GUI登录和注册界面

    Java实现简单GUI登录和注册界面

    这篇文章主要为大家详细介绍了Java实现简单GUI登录和注册界面,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • RestTemplate未使用线程池问题的解决方法

    RestTemplate未使用线程池问题的解决方法

    今天给大家带来的是关于Springboot的相关知识,文章围绕着RestTemplate未使用线程池展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06

最新评论