lombok怎么使用,lombok插件

  lombok怎么使用,lombok插件

  基础java教程专栏给你介绍Lombok的坑,很好用。

  

序言

  去年项目中引入了Lombok插件,真正解放了双手,取代了一些重复简单的工作(Getter、Setter、toString等方法的编译)。但是在使用过程中,也发现了一些坑。一开始我们没有意识到是Lombok的问题,后来我们跟踪其他组件的源代码,才发现是Lombok的问题!

  

Setter-Getter方法的坑

  

问题发现

  我们在项目中主要使用Lombok的Setter-Getter方法的注释,即组合annotation @Data。但是在用Mybatis插入数据的过程中,出现了一个问题,描述如下:

  我们有一个实体类:

  @数据

  公共类NMetaVerify{

  私有NMetaType nMetaType

  私有长id;

  .其他属性

  }复制代码。当我们使用Mybatis插入数据时,发现其他属性都可以正常插入,但是nMetaType属性总是为null。在数据库里。

  

解决

  当我将项目代码调试到调用Mybatis的insert SQL对应方法时,看到NMetaVerify对象的nMetaType属性仍然有数据,但是执行insert后,数据库的nMetaType字段始终为null。最初,我认为我的枚举类型写得不正确。我查看了其他也有枚举类型的字段。还能正常插入数据库,这让我感觉更迷茫了。于是,我跟踪了Mybatis的源代码,发现Mybatis在获取这个nMetaType的属性时使用了反射,使用getxxxx方法获取。但是我发现NMETYPE的get方法好像比Mybatis要求的getxxxx方法长了一点。问题已经找到了!

  

原因

   Lombok对第一个字母小写,第二个字母大写的属性的get-set方法与Mybatis和idea生成的方法或Java官方认可的get-set方法不同:

  由#Lombok生成的Get-Set方法

  @数据

  公共类NMetaVerify {

  私有长id;

  私有NMetaType nMetaType

  私人日期创建时间;

  public void lombokFound(){

  NMetaVerify NMetaVerify=new NMetaVerify();

  nmetaverify . setnmetatype(NMetaType。二);//注意:nMetaType的set方法是setNMetaType,第一个N字母大写,

  nmetaverify . getnmetatype();//getxxxx方法也是大写的。

  }

  }复制代码#idea,Mybatis,Java官方默认的行为是:

  公共类NMetaVerify {

  私有长id;

  私有NMetaType nMetaType

  私人日期创建时间;

  公共Long getId() {

  返回id;

  }

  公共void集合id(长id) {

  this.id=id

  }

  public netatype getnMetaType(){//注意:nMetaType属性的首字母小写。

  返回nMetaType

  }

  void setnmetatype(nmetatype nmetatype){//注意:nmetatype属性的第一个字母是小写的。

  this.nMetaType=nMetaType

  }

  公共日期getCreateTime() {

  返回createTime

  }

  public void set create time(Date create time){

  this . create time=create time;

  }

  }复制代码

Mybatis(3.4.6版本)解析get-set方法获取属性名字的源码:

   package org . Apache . ibatis . reflection . property;

  导入Java . util . locale;

  import org . Apache . ibatis . reflection . reflection exception;

  /**

  * @作者克林顿贝京

  */

  公共最终类PropertyNamer {

  私有属性名(){

  //防止静态类的实例化

  }

  公共静态字符串methodToProperty(字符串名称){

  if(name . starts with( is ){//is以bool类型开始,直接从第二个(index)截取(简单粗暴)

  name=name . substring(2);

  } else if(名称。startswith (get) name。starts with( set ){//set-get从第三个(索引)开始截取

  name=name . substring(3);

  }否则{

  引发新的ReflectionException(分析属性名名称时出错。没有以“is”、“get”或“set”开头。);

  }

  //下面这个判断很重要,可以分成两句话开始解释,解释如下

  //第一句话:name.length()==1

  //对于属性只有一个字母的,例如私有int x;

  //对应的规定方法是getX();setX(int x);

  //第二句话:name.length() 1!性格。是大写字母(名称。charat(1)))

  //属性名字长度大于1,并且第二个(代码中的查拉特,这个一是数组下标)字母是小写的

  //如果第二个茶是大写的,那就直接返回名字

  如果(姓名。length()==1 (名称。长度()1!性格。是大写字母(名称。charat(1))){

  name=name.substring(0,1).toLowerCase(区域设置。英语)名。子串(1);//让属性名第一个字母小写,然后加上后面的内容

  }

  返回名称;

  }

  公共静态布尔isProperty(字符串名称){

  返回名称。以( get ) name开头。以( set ) name开头。以( is )开头;

  }

  公共静态布尔值更好(字符串名称){

  返回姓名。以( get ) name开头。以( is )开头;

  }

  公共静态布尔isSetter(字符串名){

  返回姓名。以( set )开头;

  }

  }复制代码

Mybatis解析get-set方法为属性名字测试

   @测试

  public void foundPropertyNamer(){

  string isName=" isName

  String getName= getName

  string getnMetaType= getnMetaType ;

  string getNMetaType= getNMetaType ;

  Stream.of(isName,getName,getnMetaType,getNMetaType)。forEach(方法名-系统。出去。println(方法名字是:"方法名"属性名字:属性命名器。方法到属性(方法名)));

  }

  #输出结果如下:

  方法名字是:isName属性名字:名称

  方法名字是:getName属性名字:名称

  方法名字是:getnMetaType属性名字:nMetaType //这个以及下面的属性第二个字母都是大写,所以直接返回名字

  方法名字是:getNMetaType属性名字:NMetaType复制代码

解决方案

   1.修改属性名字,让第二个字母小写,或者说是规定所有的属性的前两个字母必须小写

  2.如果数据库已经设计好,并且前后端接口对接好了,不想修改,那就专门为这种特殊的属性使用想法生成规定方法复制代码

@Accessor(chain = true)注解的问题

  

问题发现

   在使用easy excel(github。com/阿里巴巴/eas…)导出的时候,发现以前的实体类导出都很正常,但是现在新加的实体类不正常了,比对了发现,新加的实体类增加了@Accessor(chain=true)注解,我们的目的主要是方便我们链式调用设置方法:

  新用户数()。setUserName(" ")。设置(10)

  .设置生日(新日期());复制代码

原因

   easyexcel底层使用的是字节码生成来做反射工具包的:

  com。阿里巴巴。excel。阅读。听众。modelbuildeventlistener类的第130行

  BeanMap.create(resultModel).putAll(地图);

  最底层的是字节码生成的BeanMap的这个方法调用

  抽象公共对象放(对象豆子,对象钥匙,对象值);复制代码但是字节码生成使用的是爪哇的实时冲突里面的一个内省者这个类的方法:

  # Introspector.java第520行

  if(int。班级。equals(arg types[0])名称。以(GET _ PREFIX)开头){

  PD=new IndexedPropertyDescriptor(this。bean类,name.substring(3),null,null,method,null);

  //下面这行判断,只获取返回值是空的类型的setxxxx方法

  } else if(void。班级。等于(结果类型)名称。以(SET _ PREFIX)开头){

  //简单作曲者

  PD=新的属性描述符(this。bean类,name.substring(3),null,method);

  if (throwsException(method,PropertyVetoException.class)) {

  警察。set constrained(true);

  }

  }复制代码

解决方案

   1.去掉存取器注解

  2.要么等easyexcel的作者把底层的cglib换掉,要么等别的。反正支持返回值不为void的setxxx方法复制代码也是可以的。以上是知道龙目坑的细节。更多请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: