1. 程式人生 > 程式設計 >java註解之執行時修改欄位的註解值操作

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,true);//修改註解的值
      }
      aList.add(a);
    }
    System.out.println(JSON.toJSONString(aList));
  }

列印結果

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

我本想用修改註解的方式來修改某個欄位的序列化與不序列化,但是我發現註解是在class層面的並不是在物件層面。所以我的設想失敗了。。

以上這篇java註解之執行時修改欄位的註解值操作就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。