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

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

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

前言

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

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

Spring可以做到,難道Mybatis做不到嗎?難道Mybatis技術不行?

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

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

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

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

Spring獲取參數名稱的兩種方式

1、StandardReflectionParameterNameDiscoverer

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

1、要求jdk8以上

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

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

2、LocalVariableTableParameterNameDiscoverer

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

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

兩種方式對比

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

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

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

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

通常,我們

在這里插入圖片描述

二、Mybatis為什么沒有向Spring學習?

Mybatis要獲取的是接口方法的參數名稱

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

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

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

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

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

三、總結

最后總結一下:

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

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

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

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

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

四、深入拓展

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

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

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

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

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參數后,.class會多出LocalVariableTable的信息,里面可以看到有方法參數的名字“helloWord”。

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

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

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

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

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

3、看看接口在不同參數編譯下的.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é)碼文件才帶有 接口方法參數名的信息,-g 編譯出來的和默認的都是沒有的。

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

五、結束

看到這里應該弄清楚,獲取參數名稱的套路了吧!

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

相關文章

  • SpringBoot結合SpringSecurity實現圖形驗證碼功能

    SpringBoot結合SpringSecurity實現圖形驗證碼功能

    這篇文章主要介紹了SpringBoot + SpringSecurity 實現圖形驗證碼功能,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • mybatis-plus的自動填充時間的問題(添加到數據庫的時間比當前時間多4個小時)

    mybatis-plus的自動填充時間的問題(添加到數據庫的時間比當前時間多4個小時)

    這篇文章主要介紹了mybatis-plus的自動填充時間的問題(添加到數據庫的時間比當前時間多4個小時),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09
  • springboot編程式事務TransactionTemplate的使用說明

    springboot編程式事務TransactionTemplate的使用說明

    這篇文章主要介紹了springboot編程式事務TransactionTemplate的使用說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java單線程ThreadLocal串值問題解決方案

    Java單線程ThreadLocal串值問題解決方案

    這篇文章主要介紹了Java單線程ThreadLocal串值問題解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-04-04
  • 基于Spring AMQP實現消息隊列的示例代碼

    基于Spring AMQP實現消息隊列的示例代碼

    Spring AMQP作為Spring框架的一部分,是一套用于支持高級消息隊列協(xié)議(AMQP)的工具,AMQP是一種強大的消息協(xié)議,旨在支持可靠的消息傳遞,本文給大家介紹了如何基于Spring AMQP實現消息隊列,需要的朋友可以參考下
    2024-03-03
  • 淺談JSP是如何編譯成servlet并提供服務的

    淺談JSP是如何編譯成servlet并提供服務的

    JSP是Servlet的一種特殊形式,JSP頁面最終是編譯為Servlet執(zhí)行的,那么本文主要介紹了JSP是如何編譯成servlet并提供服務的,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Java實現的數組去重與排序操作詳解

    Java實現的數組去重與排序操作詳解

    這篇文章主要介紹了Java實現的數組去重與排序操作,結合實例形式分析了Java針對數組去重及排序操作相關遍歷、排序、判斷等使用技巧與注意事項,需要的朋友可以參考下
    2018-07-07
  • springboot如何統(tǒng)一設置時區(qū)

    springboot如何統(tǒng)一設置時區(qū)

    這篇文章主要介紹了springboot如何統(tǒng)一設置時區(qū)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Struts 2中的constant配置詳解

    Struts 2中的constant配置詳解

    通過對這些屬性的配置,可以改變Struts 2 框架的一些默認行為,這些配置可以在struts.xml文件中完成,也可以在struts.properties文件中完成
    2016-09-09
  • Java?生成透明圖片的設置實現demo

    Java?生成透明圖片的設置實現demo

    這篇文章主要為大家介紹了Java?生成透明圖片的設置實現demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02

最新評論