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

java反射獲取方法參數(shù)名的幾種方式總結(jié)

 更新時(shí)間:2025年02月24日 10:01:17   作者:笨豬大難臨頭  
這篇文章主要介紹了如何通過添加編譯參數(shù)或使用Spring的工具類來獲取方法參數(shù)名,還總結(jié)了不同版本的JDK和Spring項(xiàng)目中參數(shù)名獲取的優(yōu)缺點(diǎn),并提供了應(yīng)用場(chǎng)景舉例,需要的朋友可以參考下

1、前言

一般當(dāng)我們用類似下面的反射去獲取方法參數(shù)名時(shí)得到的一般是 arg0、arg1, 參數(shù)名默認(rèn)會(huì)丟失, 導(dǎo)致無法獲取到真實(shí)的方法參數(shù)名,下面介紹如何通過其他方式解決。

    class A {
        void getUser(String userName, String userId){}
    }
    
    Method method = A.class.getMethod(String.class,String.class);
    Parameter[] parameters = method.getParameters();
    for (Parameter parameter : parameters) {
        String name = parameter.getName();
        System.out.println(name); // 得到的是arg0, arg1 而非 userName、userId
    }

2、解決方式

方式2.1: 添加編譯參數(shù)配置 -parameters

java默認(rèn)在編譯工程代碼為class文件時(shí),會(huì)將方法參數(shù)名擦除,替換成arg0、arg1之類。但是我們可以在編譯時(shí)配置將參數(shù)名也一并編譯進(jìn)去,在maven中新增如下編譯插件配置

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <!-- 配置編譯時(shí)將方法參數(shù)名保留 -->
                    <compilerArgs>
                        <arg>-parameters</arg>
                    </compilerArgs>
                </configuration>
            </plugin>

對(duì)于較新的 maven 版本(>= 3.6.2), 也可以直接使用 parameters 配置項(xiàng):

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <parameters>true</parameters>
    </configuration>
</plugin>

添加-parameters的編譯參數(shù)后,可以看到我們編譯后的class文件是源碼的參數(shù)名,而非原來的arg0、arg1。 之后我們用原生的反射Parameter.getName() 就可以獲取到的方法參數(shù)的真實(shí)參數(shù)名了

注意: 該方式僅對(duì)JDK8及以上版本有效, 以前版本JDK沒有提供該保留機(jī)制

方式2.2: 使用Spring的內(nèi)部工具類 - ParameterNameDiscoverer

如果正好你的項(xiàng)目依賴了spring,則可以直接使用spring的內(nèi)部工具類ParameterNameDiscoverer去獲取到方法真實(shí)參數(shù)名。ParameterNameDiscoverer的實(shí)現(xiàn)類
主要包含 LocalVariableTableParameterNameDiscoverer、StandardReflectionParameterNameDiscoverer 。 下面介紹如何使用

1、StandardReflectionParameterNameDiscoverer的使用

該發(fā)現(xiàn)器需要與 方式2.1: 添加編譯參數(shù)配置 -parameters 一樣添加編譯配置, 因?yàn)榈讓右彩侵苯佑梅瓷銹arameter去獲取而已

  // 創(chuàng)建參數(shù)名發(fā)現(xiàn)器
  ParameterNameDiscoverer discoverer = new StandardReflectionParameterNameDiscoverer();

  Method method = A.class.getMethod(String.class,String.class);

  // 獲取方法真實(shí)參數(shù)名.  userName, userId
  String[] parameterNames = discoverer.getParameterNames(method);

2、LocalVariableTableParameterNameDiscoverer的使用

  // 創(chuàng)建參數(shù)名發(fā)現(xiàn)器
  ParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();

  Method method = A.class.getMethod(String.class,String.class);

  // 獲取方法真實(shí)參數(shù)名.  userName, userId
  String[] parameterNames = discoverer.getParameterNames(method);

該發(fā)現(xiàn)器底層原理是在編譯類時(shí)生成一個(gè)調(diào)試信息的局部變量表LocalVariableTable,然后基于ASM字節(jié)碼技術(shù)去解析LocalVariableTable得到參數(shù)名, 所以它也需要在編譯時(shí)額外添加
編譯配置, 請(qǐng)?jiān)趍aven中添加如下-g的編譯參數(shù)配置

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <compilerArgs>
                        <!-- 生成局部變量表 -->
                        <arg>-g:vars</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>

該方法優(yōu)點(diǎn)是JDK8以下版本也能使用,但是缺點(diǎn)是無法獲取到接口的方法參數(shù)名

3、DefaultParameterNameDiscoverer的使用

  // 創(chuàng)建參數(shù)名發(fā)現(xiàn)器
  ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();

  Method method = A.class.getMethod(String.class,String.class);

  // 獲取方法真實(shí)參數(shù)名.  userName, userId
  String[] parameterNames = discoverer.getParameterNames(method);

這個(gè)參數(shù)名發(fā)現(xiàn)器是一個(gè)組合模式的發(fā)現(xiàn)器, 本身不去實(shí)現(xiàn)獲取參數(shù)名的邏輯,而是組合其他參數(shù)名發(fā)現(xiàn)器, 然后迭代調(diào)用每個(gè)參數(shù)名發(fā)現(xiàn)器直到找到真實(shí)參數(shù)名。 從下面源碼來看

主要內(nèi)置了前面講到的兩種StandardReflectionParameterNameDiscoverer 和 LocalVariableTableParameterNameDiscoverer。 所以如果要讓對(duì)應(yīng)的參數(shù)名發(fā)現(xiàn)器生效,需要配合對(duì)應(yīng)發(fā)現(xiàn)器的使用邏輯

否則一樣無法獲取到方法參數(shù)名。

// 源碼
public class DefaultParameterNameDiscoverer extends PrioritizedParameterNameDiscoverer {

	public DefaultParameterNameDiscoverer() {
		if (!GraalDetector.inImageCode()) {
			if (KotlinDetector.isKotlinReflectPresent()) {
				addDiscoverer(new KotlinReflectionParameterNameDiscoverer());
			}
			addDiscoverer(new StandardReflectionParameterNameDiscoverer()); // 依賴編譯參數(shù) -parameters
			addDiscoverer(new LocalVariableTableParameterNameDiscoverer()); //  // 依賴編譯參數(shù) -g
		}
	}

}

使用總結(jié)

1、參數(shù)名獲取的本質(zhì)

  • 所有方案都依賴編譯時(shí)保留參數(shù)名信息(通過-parameters或-g參數(shù)), 所以編譯的時(shí)候有就是有,沒有就是沒有,尤其是一些第三方依賴的類
  • 如果是第三方依賴的類若未攜帶調(diào)試信息(如未使用上述編譯參數(shù)進(jìn)行編譯),則無論如何也是無法獲取真實(shí)參數(shù)名, 除非第三方庫已使用-parameters編譯,仍可通過反射獲?。ǖ珜?shí)際場(chǎng)景較少見)

2、版本適配建議

  • JDK8+項(xiàng)目:
    優(yōu)先使用-parameters編譯參數(shù)(性能最佳), 配合StandardReflectionParameterNameDiscoverer
  • JDK7及以下: 使用-g編譯參數(shù), 配合LocalVariableTableParameterNameDiscoverer
  • Spring項(xiàng)目: 推薦使用DefaultParameterNameDiscoverer(自動(dòng)適配最優(yōu)策略), 可同時(shí)配置兩種編譯參數(shù)提升兼容性:

3、在一些springBoot 2.0以后版本中spring-boot-starter-parent會(huì)內(nèi)置了編譯參數(shù)配置,所以不用配也可以直接使用ParameterNameDiscoverer, 當(dāng)然需要確保項(xiàng)目是否覆蓋了默認(rèn)配置導(dǎo)致失效,需要重新配

知名應(yīng)用場(chǎng)景舉例

  • spring-mvc 的 @RequestParam 參數(shù)名的可省略配置
  • mybatis 的 @Param 也可以不用配置

總結(jié) 

到此這篇關(guān)于java反射獲取方法參數(shù)名的幾種方式總結(jié)的文章就介紹到這了,更多相關(guān)java反射獲取方法參數(shù)名內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • OpenFeign如何解決Get請(qǐng)求自動(dòng)轉(zhuǎn)化成POST的問題

    OpenFeign如何解決Get請(qǐng)求自動(dòng)轉(zhuǎn)化成POST的問題

    這篇文章主要介紹了OpenFeign如何解決Get請(qǐng)求自動(dòng)轉(zhuǎn)化成POST的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • springboot 整合 freemarker代碼實(shí)例

    springboot 整合 freemarker代碼實(shí)例

    這篇文章主要介紹了springboot 整合 freemarker代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • 本地安裝Nacos的踩坑過程及解決

    本地安裝Nacos的踩坑過程及解決

    這篇文章主要介紹了本地安裝Nacos的踩坑過程及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • SpringBoot之bootstrap和application的區(qū)別解讀

    SpringBoot之bootstrap和application的區(qū)別解讀

    這篇文章主要介紹了SpringBoot之bootstrap和application的區(qū)別及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 將內(nèi)容寫到txt文檔里面并讀取及刪除的方法

    將內(nèi)容寫到txt文檔里面并讀取及刪除的方法

    本文有個(gè)不錯(cuò)的示例,主要講解如何將內(nèi)容寫到txt文檔里面、讀取文件里面的內(nèi)容以及清除txt文件里面的內(nèi)容
    2014-01-01
  • Java用局域網(wǎng)實(shí)現(xiàn)聊天室功能

    Java用局域網(wǎng)實(shí)現(xiàn)聊天室功能

    這篇文章主要為大家詳細(xì)介紹了Java用局域網(wǎng)實(shí)現(xiàn)聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • 使用Spring-Retry解決Spring Boot應(yīng)用程序中的重試問題

    使用Spring-Retry解決Spring Boot應(yīng)用程序中的重試問題

    重試的使用場(chǎng)景比較多,比如調(diào)用遠(yuǎn)程服務(wù)時(shí),由于網(wǎng)絡(luò)或者服務(wù)端響應(yīng)慢導(dǎo)致調(diào)用超時(shí),此時(shí)可以多重試幾次。用定時(shí)任務(wù)也可以實(shí)現(xiàn)重試的效果,但比較麻煩,用Spring Retry的話一個(gè)注解搞定所有,感興趣的可以了解一下
    2023-04-04
  • Java實(shí)現(xiàn)創(chuàng)建運(yùn)行時(shí)類的對(duì)象操作示例

    Java實(shí)現(xiàn)創(chuàng)建運(yùn)行時(shí)類的對(duì)象操作示例

    這篇文章主要介紹了Java實(shí)現(xiàn)創(chuàng)建運(yùn)行時(shí)類的對(duì)象操作,結(jié)合實(shí)例形式分析了Java動(dòng)態(tài)創(chuàng)建對(duì)象的原理與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2018-08-08
  • Redis打開rdb文件常用方法詳解

    Redis打開rdb文件常用方法詳解

    這篇文章主要介紹了Redis打開rdb文件常用方法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Java current并發(fā)包超詳細(xì)分析

    Java current并發(fā)包超詳細(xì)分析

    current并發(fā)包、在JDK1.5之前Java并沒有提供線程安全的一些工具類去操作多線程,需要開發(fā)人員自行編寫實(shí)現(xiàn)線程安全,但仍然無法完全避免低性能、死鎖、資源管理等問題。在JDK1.5時(shí)新增了java.util.current并發(fā)包,其中提供了許多供我們使用的并發(fā)編程工具類
    2023-02-02

最新評(píng)論

兴宁市| 邮箱| 池州市| 涿鹿县| 玉山县| 建昌县| 神农架林区| 阳春市| 兴业县| 大宁县| 罗甸县| 密山市| 类乌齐县| 惠来县| 东明县| 霍州市| 桦川县| 息烽县| 郓城县| 衡阳市| 奎屯市| 香格里拉县| 秦皇岛市| 榆中县| 大同县| 高陵县| 池州市| 凉山| 隆昌县| 麻城市| 连州市| 定襄县| 清丰县| 河南省| 麦盖提县| 应用必备| 秭归县| 浙江省| 鞍山市| 武定县| 瑞金市|