最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

聊聊在獲取方法參數(shù)名方面,Spring真的就比Mybatis強?

 更新時間:2021年12月16日 09:51:09   作者:KinYang_Lau  
在獲取方法參數(shù)名方面,Spring真的就比Mybatis強嗎?今天就帶大家聊聊這個話題,如有錯誤或未考慮完全的地方,望不吝賜教

前言

在使用 Spring MVC 寫Controller的時候,即使不使用注解,只要參數(shù)名和請求參數(shù)的key對應(yīng)上了,就能自動完成數(shù)值的封裝。

但是在使用 Mybatis框架寫接口方法向xml里的SQL語句傳參時,必須使用@Param('')指定key值,在SQL中才可以取到。

Spring可以做到,難道Mybatis做不到嗎?難道Mybatis技術(shù)不行?

一、Spring是如何獲取方法參數(shù)名稱的?

Spring框架自己寫了一個工具類,用來專門獲取方法參數(shù)名稱,DefaultParameterNameDiscoverer類是一個聚合類,維護了一個LinkedList集合,里面的是真正處理的業(yè)務(wù)的類對象。

真正處理獲取方法參數(shù)名稱有三種情況:

  • 一種是處理Kotlin的情況(KotlinReflectionParameterNameDiscoverer)
  • 一種是通過java的反射方式獲?。⊿tandardReflectionParameterNameDiscoverer)
  • 最后是通過ASM字節(jié)碼方式從LocalVariableTable中獲?。↙ocalVariableTableParameterNameDiscoverer)
public class DefaultParameterNameDiscoverer extends PrioritizedParameterNameDiscoverer {
	  默認添加幾個參數(shù)名稱獲取的工具
	public DefaultParameterNameDiscoverer() {
		if (KotlinDetector.isKotlinReflectPresent() && !GraalDetector.inImageCode()) {
			addDiscoverer(new KotlinReflectionParameterNameDiscoverer());
		}
		/// add 會添加到一個 LinkedList 集合中,是一個有序的集合
		///  所以這里也就是按照優(yōu)先級進行添加的
		 StandardReflectionParameterNameDiscoverer 這個類要求JDK1.8以上的版本,且編譯要加上 -parameters 參數(shù)
		///  其實就是調(diào)用了  method.getParameters() 方法
		addDiscoverer(new StandardReflectionParameterNameDiscoverer());
		/// LocalVariableTableParameterNameDiscoverer 沒有jdk版本要求,
		// 是通過ASM提供的通過字節(jié)碼獲取方法的參數(shù)名稱
		// 但是依賴 javac 編譯的時候 添加上 -g 參數(shù)
		addDiscoverer(new LocalVariableTableParameterNameDiscoverer());
	}
}

Spring獲取參數(shù)名稱的兩種方式

1、StandardReflectionParameterNameDiscoverer

這種是通過java的反射來后去參數(shù)名稱的。但是通過反射獲取方法參數(shù)名稱是有前置條件的:

1、要求jdk8以上

2、編譯的時候,必須加-parameters參數(shù),例如:javac -parameters xxxx.java

只有滿足以上條件編譯出來的.class,才能通過反射獲取到方法參數(shù)的名稱。

2、LocalVariableTableParameterNameDiscoverer

這種是通過ASM框架,解析字節(jié)碼文件來得到方法參數(shù)名稱的。同樣,此種方法也有前置條件:

1、編譯的時候,必須添加-g參數(shù),javac -g xxxx.java

兩種方式對比

可以看出來,spring會先采用StandardReflectionParameterNameDiscoverer嘗試去獲取參數(shù)名稱

如果獲取不到就嘗試通過LocalVariableTableParameterNameDiscoverer后去參數(shù)名稱。

通過java反射獲取參數(shù)名稱的方法,前置條件比較嚴格,但是獲取方式比較簡單,直接通過反射的api調(diào)用就行,不依賴其他三方框架。

而ASM解析字節(jié)碼方式的前置條件相對比較寬松,只需要編譯的時候添加 -g參數(shù)就行,缺點就是依賴于ASM框架。(Spring已經(jīng)把asm框架通過源碼的形式加入到spring框架中了,所以不需要單獨在去引用asm框架)

通常,我們

在這里插入圖片描述

二、Mybatis為什么沒有向Spring學(xué)習(xí)?

Mybatis要獲取的是接口方法的參數(shù)名稱

Mybatis團隊難道不知道ASM技術(shù)嗎?這個肯定不是。

其實真正原因在于,Mybatis框架需要獲取的是接口的方法參數(shù)名稱,而Spring需要獲取的是類的方法的參數(shù)名稱。這是類方法和接口方法是完全不一樣的兩個東西。

Java 要獲取接口或者抽象方法的參數(shù)的名稱,必須的是JDK8以上,而且編譯的時候加上-parameters參數(shù),只有這種情況下編譯出來的.class才能獲取到參數(shù)的名稱。無論你是通過java反射還是asm字節(jié)碼技術(shù),前面兩個條件必須同時滿足。

所以當(dāng)達到上述兩個條件后,直接通過java的反射就可以直接獲取參數(shù)名稱,根本沒必要通過asm技術(shù)去獲取。

所以!Mybatis不是拿不到參數(shù)名稱,而是必須要 jdk8 以上而且還得是-parameters編譯才可以,當(dāng)滿足這兩個條件的時候,你也可以不加@Param('')注解。

三、總結(jié)

最后總結(jié)一下:

SpringMVC也不是什么時候都可以在不借助注解的情況下獲取到參數(shù)名稱,完成自動綁定的,只不過是要到達的前置條件比較寬松,需要編譯的時候添加-g參數(shù),而-g這個參數(shù)一般編譯的時候都會加上,因為有了這個參數(shù),在生成的class文件中,添加具體的 line,source,vars 信息。在輸出日志的時候,才能看到行號等信息,如果發(fā)生錯誤了,就很容易定位。一般在idea這種開發(fā)工具中運行代碼的時候,都是默認有這個參數(shù)的。所以你再idea寫測試代碼的時候,通過asm總是能獲取到方法的參數(shù)名稱,及時沒有設(shè)置-g參數(shù),那是因為開發(fā)工具編譯的時候,就默認給你添加了。

不信的話,你可以手動編譯一個java文件,只通過javac 不添加任何參數(shù),然后運行,asm框架也獲取不到方法參數(shù)名稱。

maven打包好像是默認都會加-g參數(shù),所以你碰到的絕大多數(shù)情況,下通過asm都是可以獲取到參數(shù)名稱的,給人一種asm一定能獲取參數(shù)名稱的錯覺。

所以在使用Spring框架的時候,一般不用加注解,通常情況下框架也是可以拿到參數(shù)名稱的。

Mybatis,一般情況下都要加注解@Param,是因為,Mybatis需要獲取的是接口的方法參數(shù)名稱,要想拿到接口方法的參數(shù)名稱的話,就必須在jdk8以上的環(huán)境下,而且編譯必須加-parameters參數(shù)的時候才能獲取到,這種情況一般生產(chǎn)環(huán)境下不會有-parameters參數(shù),所以在寫Mybatis的接口的時候最好加上@Param參數(shù),以保證程序正常運行。

四、深入拓展

1、從字節(jié)碼說起

java源文件經(jīng)過java編譯器編譯為.class字節(jié)碼文件,之后才能被JVM執(zhí)行,所以我們可以獲取到的信息都存在.class文件中,但是編譯器編譯.class的的文件默認不保留方法參數(shù)名。所以如果只是通過javac命令不添加任何參數(shù)情況下,編譯出來的.class文件,是無論如何也不能獲取到方法的參數(shù)名稱的。

2、看看普通類在不同參數(shù)編譯下的.class字節(jié)碼里面都有什么

下面我們通過javac編譯一個類,然后通過javap 看看里面的內(nèi)容都有什么!

public class TestBean {
    public String myMethod(String helloWord){
        return "";
    }
}

我們分別用三種方式進行編譯,然后通過javap -verbose TestBean.class 進行查看

javac TestBean.java
javac -g TestBean.java
javac -parameters TestBean.java

在這里插入圖片描述

從上面截圖可以看出來:

添加-g參數(shù)后,.class會多出LocalVariableTable的信息,里面可以看到有方法參數(shù)的名字“helloWord”。

添加-parameters參數(shù)后,.class會多出MethodParameters的信息,里面也可以看到有方法參數(shù)的名字“helloWord”。

而javac不加任何參數(shù)的話,則在任何地方都找不到方法參數(shù)名“helloword”的信息。

所以:也驗證了前面所說的,默認情況下,無論是asm還是java反射都是無法獲取方法參數(shù)名稱的,因為字節(jié)碼里面就沒有參數(shù)名的信息。

但是如果是有-g參數(shù)編譯的話,字節(jié)碼里會在LocalVariableTable將方法的參數(shù)名稱進行保存,而ASM框架是基于字節(jié)碼技術(shù)的,所以是可以解析出參數(shù)名稱的。但是java的反射API并未提供獲取LocalVariableTable信息的內(nèi)容,所以-g產(chǎn)生的信息,只能通過自己解析字節(jié)碼獲取,所以asm是可以做到的。

如果是有-parameters參數(shù)編譯的話,字節(jié)碼里面保存MethodParameters信息,里面就是方法參數(shù)名稱的信息,java的反射api提供的接口可以直接獲取到里面的信息。但是-parameters 是jdk8以后才提供的新特性,所以要想通過反射api獲取的話,只能是jdk8及以上版本通過添加-parameters參數(shù)才可以。

3、看看接口在不同參數(shù)編譯下的.class字節(jié)碼里面都有什么

先寫一個普通的接口

public interface TestInterfaceBean {
    public String testInterfaceMethod (String iName);
}

然后再用三種方式進行編譯,最后通過javap -verbose TestInterfaceBean.class 進行查看

javac TestInterfaceBean.java
javac -g TestInterfaceBean.java
javac -parameters TestInterfaceBean.java

在這里插入圖片描述

從上面三張截圖可以看出來,只有 javac -parameters 編譯出來的.class字節(jié)碼文件才帶有 接口方法參數(shù)名的信息,-g 編譯出來的和默認的都是沒有的。

所以嘛,對于接口而言,只有通過-parameters 編譯的字節(jié)碼才能有方法參數(shù)名稱。這也就明白了為什么Mybatis的接口要加注解了吧,因為你如果不通過注解信息去獲取的話,你不論是java反射也好,asm也好都拿不到參數(shù)名稱,除非你編譯的時候添加-parameters,而生產(chǎn)環(huán)境通常是不會加這個參數(shù)的。

五、結(jié)束

看到這里應(yīng)該弄清楚,獲取參數(shù)名稱的套路了吧!

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解Java中super的幾種用法并與this的區(qū)別

    詳解Java中super的幾種用法并與this的區(qū)別

    這篇文章主要介紹了Java中super的幾種用法并與this的區(qū)別,有需要的朋友可以參考一下
    2013-12-12
  • Java實現(xiàn)抽獎算法的示例代碼

    Java實現(xiàn)抽獎算法的示例代碼

    這篇文章主要為大家詳細介紹了如何利用Java語言實現(xiàn)抽獎算法,文中的示例代碼講解詳細,對我們學(xué)習(xí)Java有一定幫助,需要的可以參考一下
    2022-04-04
  • Redis緩存,泛型集合與json字符串的相互轉(zhuǎn)換實例

    Redis緩存,泛型集合與json字符串的相互轉(zhuǎn)換實例

    這篇文章主要介紹了Redis緩存,泛型集合與json字符串的相互轉(zhuǎn)換實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • Java使用Jdbc連接Oracle執(zhí)行簡單查詢操作示例

    Java使用Jdbc連接Oracle執(zhí)行簡單查詢操作示例

    這篇文章主要介紹了Java使用Jdbc連接Oracle執(zhí)行簡單查詢操作,結(jié)合實例形式詳細分析了java基于jdbc實現(xiàn)Oracle數(shù)據(jù)庫的連接與查詢相關(guān)操作技巧,需要的朋友可以參考下
    2019-09-09
  • 如何基于FTP4J實現(xiàn)FTPS連接過程解析

    如何基于FTP4J實現(xiàn)FTPS連接過程解析

    這篇文章主要介紹了如何基于FTP4J實現(xiàn)FTPS連接過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-10-10
  • java實現(xiàn)本地緩存的示例代碼

    java實現(xiàn)本地緩存的示例代碼

    在高性能服務(wù)架構(gòu)設(shè)計中,緩存是不可或缺的環(huán)節(jié),因此這篇文章主要為大家詳細介紹了java中如何實現(xiàn)本地緩存,感興趣的小伙伴可以了解一下
    2024-01-01
  • springmvc+mybatis 做分頁sql 語句實例代碼

    springmvc+mybatis 做分頁sql 語句實例代碼

    本文通過一段實例代碼給大家介紹了springmvc+mybatis 做分頁sql 語句的方法,代碼簡單易懂,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2017-07-07
  • idea快速實現(xiàn)將SpringBoot項目打包Docker鏡像并部署

    idea快速實現(xiàn)將SpringBoot項目打包Docker鏡像并部署

    本文主要介紹了idea快速實現(xiàn)將SpringBoot項目打包Docker鏡像并部署,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • Java?HashSet的Removals()方法注意事項

    Java?HashSet的Removals()方法注意事項

    這篇文章主要介紹了Java?HashSet的Removals()方法注意事項,文章圍繞制主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-06-06
  • SpringBoot中的ThreadLocal保存請求用戶信息的實例demo

    SpringBoot中的ThreadLocal保存請求用戶信息的實例demo

    線程局部變量,創(chuàng)建一個線程變量后,針對這個變量可以讓每個線程擁有自己的變量副本,每個線程是訪問的自己的副本,與其他線程的相互獨立,本文介紹SpringBoot中的ThreadLocal保存請求用戶信息,需要的朋友可以參考下
    2024-05-05

最新評論

余庆县| 原阳县| 克山县| 靖西县| 巴彦县| 南昌县| 阿瓦提县| 玉溪市| 泸水县| 阆中市| 洛扎县| 布拖县| 大竹县| 临桂县| 哈尔滨市| 池州市| 启东市| 手游| 孟村| 临桂县| 开化县| 基隆市| 丹棱县| 奉化市| 霍林郭勒市| 高淳县| 墨脱县| 宁德市| 平谷区| 潞西市| 修水县| 开江县| 乌兰浩特市| 通化市| 莎车县| 灵璧县| 苗栗县| 溧阳市| 钟祥市| 紫云| 新密市|