欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Lombok的坑

 更新時間:2020年11月04日 10:18:46   作者:liuxuzxx  
這篇文章主要介紹了詳解Lombok的坑,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

序言

去年在項目當中引入了Lombok插件,著實解放了雙手,代替了一些重復的簡單工作(Getter,Setter,toString等方法的編寫),但是,在使用的過程當中,也發(fā)現了一些坑,開始的時候并沒有察覺到是Lombok的問題,后來跟蹤了對應的其他組件的源碼,才發(fā)現是Lombok的問題!

Setter-Getter方法的坑

問題發(fā)現

我們在項目當中主要使用Lombok的Setter-Getter方法的注解,也就是組合注解@Data,但是在一次使用Mybatis插入數據的過程當中,出現了一個問題,問題描述如下:

我們有個實體類:

@Data
public class NMetaVerify{
  private NMetaType nMetaType;
  private Long id;
  ....其他屬性
}

當我們使用Mybatis插入數據的時候,發(fā)現,其他屬性都能正常的插入,但是就是nMetaType屬性在數據庫一直是null.

解決

當我debug項目代碼到調用Mybatis的插入SQL對應的方法的時候,我看到NMetaVerify對象的nMetaType屬性還是有數據的,但是執(zhí)行插入之后,數據庫的nMetaType字段就是一直是null,原先我以為是我的枚舉類型寫法不正確,看了下別的同樣具有枚舉類型的字段,也是正常能插入到數據庫當中的,這更讓我感覺到疑惑了.于是,我就跟蹤Mybatis的源碼,發(fā)現Mybatis在獲取這個nMetaType屬性的時候使用了反射,使用的是getxxxx方法來獲取的,但是我發(fā)現nMetaType的get方法好像有點和Mybatis需要的getxxxx方法長的好像不一樣.問題找到了!

原因

Lombok對于第一個字母小寫,第二個字母大寫的屬性生成的get-set方法和Mybatis以及idea或者說是Java官方認可的get-set方法生成的不一樣:

#Lombok生成的Get-Set方法
@Data
public class NMetaVerify {
  private Long id;
  private NMetaType nMetaType;
  private Date createTime;
  
  public void lombokFound(){
    NMetaVerify nMetaVerify = new NMetaVerify();
    nMetaVerify.setNMetaType(NMetaType.TWO); //注意:nMetaType的set方法為setNMetaType,第一個n字母大寫了,
    nMetaVerify.getNMetaType();                 //getxxxx方法也是大寫
  }
}

#idea,Mybatis,Java官方默認的行為為:
public class NMetaVerify {
  private Long id;
  private NMetaType nMetaType;
  private Date createTime;

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public NMetaType getnMetaType() {//注意:nMetaType屬性的第一個字母小寫
    return nMetaType;
  }

  public void setnMetaType(NMetaType nMetaType) {//注意:nMetaType屬性的第一個字母小寫
    this.nMetaType = nMetaType;
  }

  public Date getCreateTime() {
    return createTime;
  }

  public void setCreateTime(Date createTime) {
    this.createTime = createTime;
  }
}

Mybatis(3.4.6版本)解析get-set方法獲取屬性名字的源碼:

package org.apache.ibatis.reflection.property;

import java.util.Locale;

import org.apache.ibatis.reflection.ReflectionException;

/**
 * @author Clinton Begin
 */
public final class PropertyNamer {

   private PropertyNamer() {
     // Prevent Instantiation of Static Class
    }

  public static String methodToProperty(String name) {
   if (name.startsWith("is")) {//is開頭的一般是bool類型,直接從第二個(索引)開始截取(簡單粗暴)
     name = name.substring(2);
   } else if (name.startsWith("get") || name.startsWith("set")) {//set-get的就從第三個(索引)開始截取
     name = name.substring(3);
   } else {
     throw new ReflectionException("Error parsing property name '" + name + "'. Didn't start with 'is', 'get' or 'set'.");
   }
      //下面這個判斷很重要,可以分成兩句話開始解釋,解釋如下
      //第一句話:name.length()==1
      //    對于屬性只有一個字母的,例如private int x;
      //     對應的get-set方法是getX();setX(int x);
      //第二句話:name.length() > 1 && !Character.isUpperCase(name.charAt(1)))
      //   屬性名字長度大于1,并且第二個(代碼中的charAt(1),這個1是數組下標)字母是小寫的
      //   如果第二個char是大寫的,那就直接返回name
   if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
     name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);//讓屬性名第一個字母小寫,然后加上后面的內容
   }

   return name;
  }

  public static boolean isProperty(String name) {
    return name.startsWith("get") || name.startsWith("set") || name.startsWith("is");
  }

  public static boolean isGetter(String name) {
    return name.startsWith("get") || name.startsWith("is");
  }

  public static boolean isSetter(String name) {
    return name.startsWith("set");
  }

}

Mybatis解析get-set方法為屬性名字測試

  @Test
  public void foundPropertyNamer() {
    String isName = "isName";
    String getName = "getName";
    String getnMetaType = "getnMetaType";
    String getNMetaType = "getNMetaType";

    Stream.of(isName,getName,getnMetaType,getNMetaType)
        .forEach(methodName->System.out.println("方法名字是:"+methodName+" 屬性名字:"+ PropertyNamer.methodToProperty(methodName)));
  }
  
  #輸出結果如下:
  方法名字是:isName 屬性名字:name 
  方法名字是:getName 屬性名字:name 
  方法名字是:getnMetaType 屬性名字:nMetaType //這個以及下面的屬性第二個字母都是大寫,所以直接返回name
  方法名字是:getNMetaType 屬性名字:NMetaType

解決方案
1.修改屬性名字,讓第二個字母小寫,或者說是規(guī)定所有的屬性的前兩個字母必須小寫
2.如果數據庫已經設計好,并且前后端接口對接好了,不想修改,那就專門為這種特殊的屬性使用idea生成get-set方法

@Accessor(chain = true)注解的問題

問題發(fā)現

在使用easyexcel(https://github.com/alibaba/easyexcel) 導出的時候,發(fā)現以前的實體類導出都很正常,但是現在新加的實體類不正常了,比對了發(fā)現,新加的實體類增加了@Accessor(chain = true)注解,我們的目的主要是方便我們鏈式調用set方法:

new UserDto()
.setUserName("")
.setAge(10)
........
.setBirthday(new Date());

原因

easyexcel底層使用的是cglib來做反射工具包的:

com.alibaba.excel.read.listener.ModelBuildEventListener 類的第130行
BeanMap.create(resultModel).putAll(map);

最底層的是cglib的BeanMap的這個方法調用

abstract public Object put(Object bean, Object key, Object value);

但是cglib使用的是Java的rt.jar里面的一個Introspector這個類的方法:

# Introspector.java 第520行
if (int.class.equals(argTypes[0]) && name.startsWith(GET_PREFIX)) {
  pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, method, null);
  //下面這行判斷,只獲取返回值是void類型的setxxxx方法
 } else if (void.class.equals(resultType) && name.startsWith(SET_PREFIX)) {
  // Simple setter
  pd = new PropertyDescriptor(this.beanClass, name.substring(3), null, method);
  if (throwsException(method, PropertyVetoException.class)) {
    pd.setConstrained(true);
  }
}

解決方案
1.去掉Accessor注解
2.要么就等待easye

到此這篇關于詳解Lombok的坑的文章就介紹到這了,更多相關Lombok 坑內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java基于rest assured實現接口測試過程解析

    Java基于rest assured實現接口測試過程解析

    這篇文章主要介紹了Java基于rest assured實現接口測試過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03
  • 深入理解 Java注解及實例

    深入理解 Java注解及實例

    這篇文章主要介紹了深入理解 Java注解及實例的相關資料,希望通過本文大家能夠掌握java注解的知識,需要的朋友可以參考下
    2017-09-09
  • java 中死鎖問題的實例詳解

    java 中死鎖問題的實例詳解

    這篇文章主要介紹了java 中死鎖問題的實例詳解的相關資料,希望通過本文大家能夠理解掌握死鎖的問題,需要的朋友可以參考下
    2017-09-09
  • Spring之@DependsOn注解詳細解析

    Spring之@DependsOn注解詳細解析

    這篇文章主要介紹了Spring之@DependsOn注解詳細解析,@DependsOn注解是Spring中提供的一個指定Spring創(chuàng)建Bean的依賴順序的注解,需要的朋友可以參考下
    2024-01-01
  • SpringBoot整合mybatis結合pageHelper插件實現分頁

    SpringBoot整合mybatis結合pageHelper插件實現分頁

    在本篇文章里小編給大家整理的是關于SpringBoot整合mybatis使用pageHelper插件進行分頁操作相關知識點,需要的朋友們學習下。
    2020-02-02
  • Java和Redis實現熱搜功能

    Java和Redis實現熱搜功能

    這篇文章主要介紹了Java和Redis實現熱搜功能,在存儲和傳輸用戶搜索數據時,考慮到數據的機密性和隱私保護,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-01-01
  • flink?RichFunction之坑及解決

    flink?RichFunction之坑及解決

    這篇文章主要介紹了flink?RichFunction之坑及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 一個JAVA小項目--Web應用自動生成Word

    一個JAVA小項目--Web應用自動生成Word

    前段時間接到一個Web應用自動生成Word的需求,現整理了下一些關鍵步驟拿來分享一下。
    2014-05-05
  • 關于@Component注解下的類無法@Autowired問題

    關于@Component注解下的類無法@Autowired問題

    這篇文章主要介紹了關于@Component注解下的類無法@Autowired問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • idea2023設置啟動參數、單元測試啟動參數

    idea2023設置啟動參數、單元測試啟動參數

    在使用IDEA進行開發(fā)時,我們可以通過設置一些啟動參數來優(yōu)化開發(fā)環(huán)境的性能和體驗,具有一定的參考價值,感興趣的可以了解一下
    2023-11-11

最新評論