亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

目錄
序言
Setter-Getter方法的坑
問題發(fā)現(xiàn)
解決
原因
Mybatis(3.4.6版本)解析get-set方法獲取屬性名字的源碼:
Mybatis解析get-set方法為屬性名字測試
解決方案
@Accessor(chain = true)注解的問題
首頁 Java Java基礎 認識Lombok的坑

認識Lombok的坑

Oct 09, 2020 pm 05:00 PM
lombok

java基礎教程欄目為大家介紹認識Lombok的坑,好用。

認識Lombok的坑

序言

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

Setter-Getter方法的坑

問題發(fā)現(xiàn)

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

我們有個實體類:
@Data
public class NMetaVerify{
    private NMetaType nMetaType;
    private Long id;
    ....其他屬性
}復制代碼

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

解決

當我debug項目代碼到調(diào)用Mybatis的插入SQL對應的方法的時候,我看到NMetaVerify對象的nMetaType屬性還是有數(shù)據(jù)的,但是執(zhí)行插入之后,數(shù)據(jù)庫的nMetaType字段就是一直是null,原先我以為是我的枚舉類型寫法不正確,看了下別的同樣具有枚舉類型的字段,也是正常能插入到數(shù)據(jù)庫當中的,這更讓我感覺到疑惑了.于是,我就跟蹤Mybatis的源碼,發(fā)現(xiàn)Mybatis在獲取這個nMetaType屬性的時候使用了反射,使用的是getxxxx方法來獲取的,但是我發(fā)現(xiàn)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是數(shù)組下標)字母是小寫的
            //                      如果第二個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);//讓屬性名第一個字母小寫,然后加上后面的內(nèi)容
            }

            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.如果數(shù)據(jù)庫已經(jīng)設計好,并且前后端接口對接好了,不想修改,那就專門為這種特殊的屬性使用idea生成get-set方法復制代碼

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

問題發(fā)現(xiàn)

在使用easyexcel(github.com/alibaba/eas…) 導出的時候,發(fā)現(xiàn)以前的實體類導出都很正常,但是現(xiàn)在新加的實體類不正常了,比對了發(fā)現(xiàn),新加的實體類增加了@Accessor(chain = true)注解,我們的目的主要是方便我們鏈式調(diào)用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的這個方法調(diào)用

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.要么就等待easyexcel的作者替換掉底層的cglib或者是其他,反正是支持獲取返回值不是void的setxxx方法就行復制代碼

相關免費學習推薦:java基礎教程

以上是認識Lombok的坑的詳細內(nèi)容。更多信息請關注PHP中文網(wǎng)其他相關文章!

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻,版權歸原作者所有,本站不承擔相應法律責任。如您發(fā)現(xiàn)有涉嫌抄襲侵權的內(nèi)容,請聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動的應用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機

Video Face Swap

Video Face Swap

使用我們完全免費的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級代碼編輯軟件(SublimeText3)

熱門話題

Laravel 教程
1597
29
PHP教程
1488
72
專業(yè)指導:如何成功安裝Eclipse Lombok插件的專家建議和步驟 專業(yè)指導:如何成功安裝Eclipse Lombok插件的專家建議和步驟 Jan 28, 2024 am 09:15 AM

專業(yè)指導:Eclipse安裝Lombok插件的專家建議和步驟,需要具體代碼示例摘要:Lombok是一種Java庫,能夠通過注解的方式簡化Java代碼的編寫,并提供了一些功能強大的工具。本文將向讀者介紹如何在Eclipse中安裝和配置Lombok插件的步驟,并提供一些具體的代碼示例,以便讀者能夠更好地理解和使用Lombok插件。下載Lombok插件首先,我們需

簡單教程:在Eclipse中快速安裝Lombok插件 簡單教程:在Eclipse中快速安裝Lombok插件 Jan 28, 2024 am 08:06 AM

快速入門:Eclipse中安裝Lombok插件的簡易教程,需要具體代碼示例在開發(fā)Java項目過程中,常常會使用到Lombok這個實用的插件。Lombok可以幫助我們簡化Java代碼,減少樣板代碼的編寫,提升開發(fā)效率。本文將為你介紹如何在Eclipse中安裝和配置Lombok插件,并提供具體的代碼示例。步驟一:下載Lombok插件首先,我們需要從Lombok官

SpringBoot整合Lombok及常見問題怎么解決 SpringBoot整合Lombok及常見問題怎么解決 May 20, 2023 pm 12:46 PM

LombokLombok能以簡單的注解形式來簡化java代碼,從而提高開發(fā)人員的開發(fā)效率。其本身是一個優(yōu)秀的Java代碼庫,它采用了一種投機取巧的語法糖,簡化了Java的編碼,為Java代碼的精簡提供了一種方式,但Lombok并非一個標準的Java庫。在web開發(fā)過程中經(jīng)常需要寫的Java類,都需要花時間去添加相應的getter/setter、構造器和equals等方法。當屬性多時會出現(xiàn)大量的getter/setter方法,這些顯得很冗長也沒有太多技術含量,一旦修改屬性,容易出現(xiàn)忘記修改對應方法

Eclipse Lombok插件安裝的完整指南 Eclipse Lombok插件安裝的完整指南 Jan 28, 2024 am 09:58 AM

完全指南:Eclipse如何安裝Lombok插件,需要具體代碼示例引言:Eclipse是一個廣泛使用的集成開發(fā)環(huán)境(IDE),用于Java開發(fā)。Lombok是一個Java庫,可以自動化一些繁瑣的代碼,從而提高開發(fā)效率。本文將詳細介紹如何在Eclipse中安裝Lombok插件,并提供具體的代碼示例。第一步:下載Lombok插件打開Eclipse,選擇“Help

簡便安裝:在Eclipse中安裝Lombok插件的小技巧 簡便安裝:在Eclipse中安裝Lombok插件的小技巧 Jan 28, 2024 am 09:29 AM

實用技巧:Eclipse如何輕松安裝Lombok插件,需要具體代碼示例在日常的Java開發(fā)中,我們經(jīng)常會使用到Eclipse作為主要的集成開發(fā)環(huán)境。而在實際開發(fā)中,我們可能會遇到一些繁瑣的操作,比如Getter和Setter方法的手動編寫。為了簡化這些操作,我們可以使用Lombok插件來自動幫助我們生成這些代碼。下面將介紹如何在Eclipse中輕松安裝和配置

Java庫lombok及注解如何使用 Java庫lombok及注解如何使用 Jun 03, 2023 pm 09:28 PM

Lombok是什么Lombok是一個旨在減少代碼開發(fā)工作的Java庫。它提供了一些簡單的注解,并以此來消除java中臃腫的模版代碼,比如pojo中最常見的setter/getter方法,比如toString方法,比如equals方法等等,還可以幫助我們關閉流,即使JDK7中已經(jīng)有了TWR特性,但這個包很值得一試。通過幾個簡單的注解,將模版代碼在編譯時寫入程序。使用eclipse可以在Outline窗口看到生成的方法,但是在源碼里是干凈的.安裝首先去lombok官網(wǎng)下載jar包。只是把jar包下載

Java API 開發(fā)中使用 Lombok 進行編碼簡化 Java API 開發(fā)中使用 Lombok 進行編碼簡化 Jun 18, 2023 pm 11:34 PM

Java是一種常用的編程語言,廣泛應用于開發(fā)各種類型的應用程序。JavaAPI是Java語言的核心部分之一,它為開發(fā)人員提供了許多可重用的代碼和庫,可以加速應用程序的開發(fā)和部署過程。在JavaAPI的開發(fā)過程中,經(jīng)常需要使用一些簡化編碼的工具和技術,以提高代碼的可讀性和可維護性。Lombok是一款非常實用的Java庫,可以在Java

java中Lombok有什么注解 java中Lombok有什么注解 Apr 30, 2023 pm 03:52 PM

注解舉例1、@ToString:實現(xiàn)toString()方法2、@Data:注解在類上;提供類所有屬性的getting和setting方法,此外還提供了equals、canEqual、hashCode、toString方法3、@Setter:注解在屬性上;為屬性提供setting方法。@Getter:注解在屬性上;為屬性提供getting方法@Log4j:注解在類上;為類提供一個屬性名為log的log4j日志對象@NoArgsConstructor:注解在類上;為類提供一個無參的構造方法@All

See all articles