国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

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

認(rèn)識Lombok的坑

Oct 09, 2020 pm 05:00 PM
lombok

java基礎(chǔ)教學(xué)專欄為大家介紹認(rèn)識Lombok的坑,好用。

認(rèn)識Lombok的坑

序言

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

Setter-Getter方法的坑

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

我們在專案當(dāng)中主要使用Lombok的Setter-Getter方法的註解,也就是組合註解@Data,但在一次使用Mybatis插入資料的過程當(dāng)中,出現(xiàn)了一個(gè)問題,問題描述如下:

我們有個(gè)實(shí)體類:
@Data
public class NMetaVerify{
    private NMetaType nMetaType;
    private Long id;
    ....其他屬性
}復(fù)制代碼

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

解決

當(dāng)我debug專案程式碼到呼叫Mybatis的插入SQL對應(yīng)的方法的時(shí)候,我看到NMetaVerify物件的nMetaType屬性還是有資料的,但是執(zhí)行插入之後,資料庫的nMetaType字段就是一直是null,原先我以為是我的枚舉類型寫法不正確,看了下別的同樣具有枚舉類型的字段,也是正常能插入到數(shù)據(jù)庫當(dāng)中的,這更讓我感覺到疑惑了.於是,我就追蹤Mybatis的源碼,發(fā)現(xiàn)Mybatis在取得這個(gè)nMetaType屬性的時(shí)候使用了反射,使用的是getxxxx方法來獲取的,但是我發(fā)現(xiàn)nMetaType的get方法好像有點(diǎn)和Mybatis需要的getxxxx方法長的好像不一樣.問題找到了!

原因

Lombok對於第一個(gè)字母小寫,第二個(gè)字母大寫的屬性生成的get-set方法和Mybatis以及idea或者說是Java官方認(rèn)可的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,第一個(gè)n字母大寫了,
        nMetaVerify.getNMetaType();                                  //getxxxx方法也是大寫
    }
}復(fù)制代碼
#idea,Mybatis,Java官方默認(rèn)的行為為:
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屬性的第一個(gè)字母小寫
        return nMetaType;
    }

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

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}復(fù)制代碼

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類型,直接從第二個(gè)(索引)開始截取(簡單粗暴)
                    name = name.substring(2);
            } else if (name.startsWith("get") || name.startsWith("set")) {//set-get的就從第三個(gè)(索引)開始截取
                    name = name.substring(3);
            } else {
                    throw new ReflectionException("Error parsing property name '" + name + "'.  Didn't start with 'is', 'get' or 'set'.");
            }
            //下面這個(gè)判斷很重要,可以分成兩句話開始解釋,解釋如下
            //第一句話:name.length()==1
            //                      對于屬性只有一個(gè)字母的,例如private int x;
            //                      對應(yīng)的get-set方法是getX();setX(int x);
            //第二句話:name.length() > 1 && !Character.isUpperCase(name.charAt(1)))
            //                      屬性名字長度大于1,并且第二個(gè)(代碼中的charAt(1),這個(gè)1是數(shù)組下標(biāo))字母是小寫的
            //                      如果第二個(gè)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);//讓屬性名第一個(gè)字母小寫,然后加上后面的內(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");
        }

}復(fù)制代碼

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)));
    }
    
    #輸出結(jié)果如下:
    方法名字是:isName 屬性名字:name 
    方法名字是:getName 屬性名字:name 
    方法名字是:getnMetaType 屬性名字:nMetaType //這個(gè)以及下面的屬性第二個(gè)字母都是大寫,所以直接返回name
    方法名字是:getNMetaType 屬性名字:NMetaType復(fù)制代碼

解決方案

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

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

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

在使用easyexcel(github.com/alibaba/eas…) 匯出的時(shí)候,發(fā)現(xiàn)以前的實(shí)體類別導(dǎo)出都很正常,但是現(xiàn)在新加的實(shí)體類別不正常了,比對了發(fā)現(xiàn),新加的實(shí)體類別增加了@Accessor(chain = true)註解,我們的目的主要是方便我們鍊式呼叫set方法:

new UserDto()
.setUserName("")
.setAge(10)
........
.setBirthday(new Date());復(fù)制代碼

原因

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

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

最底層的是cglib的BeanMap的這個(gè)方法調(diào)用

abstract public Object put(Object bean, Object key, Object value);復(fù)制代碼

但是cglib使用的是Java的rt .jar裡面的一個(gè)Introspector這個(gè)類別的方法:

# 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);
    }
}復(fù)制代碼

解決方案

1.去掉Accessor注解
2.要么就等待easyexcel的作者替換掉底層的cglib或者是其他,反正是支持獲取返回值不是void的setxxx方法就行復(fù)制代碼

相關(guān)免費(fèi)學(xué)習(xí)推薦:##java基礎(chǔ)教學(xué)

以上是認(rèn)識Lombok的坑的詳細(xì)內(nèi)容。更多資訊請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

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

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Laravel 教程
1601
29
PHP教程
1502
276
專業(yè)指導(dǎo):如何成功安裝Eclipse Lombok外掛程式的專家建議與步驟 專業(yè)指導(dǎo):如何成功安裝Eclipse Lombok外掛程式的專家建議與步驟 Jan 28, 2024 am 09:15 AM

專業(yè)指導(dǎo):Eclipse安裝Lombok外掛程式的專家建議和步驟,需要具體程式碼範(fàn)例摘要:Lombok是一種Java庫,能夠透過註解的方式簡化Java程式碼的編寫,並提供了一些強(qiáng)大的工具。本文將向讀者介紹如何在Eclipse中安裝和設(shè)定Lombok插件的步驟,並提供一些具體的程式碼範(fàn)例,以便讀者能夠更好地理解和使用Lombok插件。下載Lombok插件首先,我們需

簡單教學(xué):在Eclipse中快速安裝Lombok插件 簡單教學(xué):在Eclipse中快速安裝Lombok插件 Jan 28, 2024 am 08:06 AM

快速入門:Eclipse中安裝Lombok插件的簡易教學(xué),需要具體程式碼範(fàn)例在開發(fā)Java專案過程中,常常會使用到Lombok這個(gè)實(shí)用的插件。 Lombok可以幫助我們簡化Java程式碼,減少樣板程式碼的編寫,提升開發(fā)效率。本文將為你介紹如何在Eclipse中安裝和設(shè)定Lombok插件,並提供具體的程式碼範(fàn)例。步驟一:下載Lombok外掛首先,我們需要從Lombok官

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

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

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

完整指南:Eclipse如何安裝Lombok插件,需要具體程式碼範(fàn)例引言:Eclipse是一個(gè)廣泛使用的整合開發(fā)環(huán)境(IDE),用於Java開發(fā)。 Lombok是一個(gè)Java函式庫,可以自動化一些繁瑣的程式碼,進(jìn)而提高開發(fā)效率。本文將詳細(xì)介紹如何在Eclipse中安裝Lombok插件,並提供具體的程式碼範(fàn)例。第一步:下載Lombok外掛程式開啟Eclipse,選擇「Help

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

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

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

Lombok是什麼Lombok是一個(gè)旨在減少程式碼開發(fā)工作的Java庫。它提供了一些簡單的註解,並以此來消除java中臃腫的模版程式碼,例如pojo中最常見的setter/getter方法,例如toString方法,例如equals方法等等,還可以幫助我們關(guān)閉串流,即使JDK7中已經(jīng)有了TWR特性,但這個(gè)包很值得一試。透過幾個(gè)簡單的註解,將模版程式碼在編譯時(shí)寫入程式。使用eclipse可以在Outline視窗看到產(chǎn)生的方法,但是在源碼裡是乾淨(jìng)的.安裝首先去lombok官網(wǎng)下載jar包。只是把jar包下載

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

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

java中Lombok有什麼註解 java中Lombok有什麼註解 Apr 30, 2023 pm 03:52 PM

註解舉例1、@ToString:實(shí)作toString()方法2、@Data:註解在類別上;提供類別所有屬性的getting和setting方法,此外還提供了equals、canEqual、hashCode、toString方法3、@Setter:註解在屬性上;為屬性提供setting方法。 @Getter:註解在屬性上;為屬性提供getting方法@Log4j:註解在類別上;為類別提供一個(gè)屬性名為log的log4j日誌物件@NoArgsConstructor:註解在類別上;為類別提供一個(gè)無參的構(gòu)造方法@All

See all articles