淺談Spring6中的反射機(jī)制
一:回顧反射機(jī)制
這種重點(diǎn)回顧一下反射Method!
為什么要回顧反射機(jī)制呢?因?yàn)槲覀兒竺嬉謱?xiě)一個(gè)簡(jiǎn)易的Spring框架,便于我們理解其中的核心原理!
1. 分析方法四要素
我們先來(lái)看一下,不使用反射機(jī)制調(diào)用一個(gè)方法需要幾個(gè)要素的參與!
定義一個(gè)SomeService方法
package com.bjpowernode.reflect; public class SomeService { // 沒(méi)有參數(shù)、沒(méi)有返回值的方法 public void doSome(){ System.out.println("public void doSome()執(zhí)行。"); } // 一個(gè)參數(shù),返回String的方法 public String doSome(String s){ System.out.println("public String doSome(String s)執(zhí)行。"); return s; } // 兩個(gè)參數(shù),返回String的方法 public String doSome(String s, int i){ System.out.println("public String doSome(String s, int i)執(zhí)行。"); return s + i; } }
進(jìn)行測(cè)試,分析方法的要素
package com.bjpowernode.reflect; public class Test { public static void main(String[] args) { // 不使用反射機(jī)制調(diào)用這些方法 SomeService someService = new SomeService(); // 無(wú)參數(shù) someService.doSome(); // 一個(gè)參數(shù) String s1 = someService.doSome("張三"); System.out.println(s1); // 兩個(gè)參數(shù) String s2 = someService.doSome("李四", 250); System.out.println(s2); } }
通過(guò)以上測(cè)試代碼,我們可以得出調(diào)用一個(gè)方法,一般涉及到4個(gè)要素:
①調(diào)用哪個(gè)對(duì)象的(SomeService)
②哪個(gè)方法(doSome)
③傳什么參數(shù)("張三")
④返回什么值(String類(lèi)型)
總結(jié):調(diào)用哪個(gè)對(duì)象的哪個(gè)方法?傳什么值?返回什么值?
2. 獲取Method
要使用反射機(jī)制調(diào)用一個(gè)方法,首先你要獲取到這個(gè)方法。
在反射機(jī)制中Method實(shí)例代表的是一個(gè)方法,那么怎么獲取Method實(shí)例呢?
編寫(xiě)測(cè)試
(1)要想調(diào)用方法,首先我們要先獲取對(duì)應(yīng)的類(lèi),使用Class.forName,參數(shù)是全限定類(lèi)名
(2)然后調(diào)用這個(gè)類(lèi)的getDeclaredMethod方法,參數(shù)一個(gè)是方法名、另一個(gè)參數(shù)是可變可變長(zhǎng)度參數(shù),類(lèi)型是class;這樣就能獲取到方法。
(3)方法獲取到,我們就可以調(diào)用invoke(調(diào)用)方法,參數(shù)一個(gè)是obj,就是要把對(duì)象傳過(guò)來(lái),所以我們就需要先創(chuàng)建一個(gè)對(duì)象、另一個(gè)參數(shù)也是可變長(zhǎng)度參數(shù),傳具體的值。
例如以下程序的四要素:調(diào)用哪個(gè)對(duì)象、哪個(gè)方法、傳什么參數(shù)、返回什么值?
①obj 要素:哪個(gè)對(duì)象
②doSomeMethod 要素:哪個(gè)方法
③"李四", 250 要素:傳什么參數(shù)
④retValue 要素:返回什么值
package com.bjpowernode.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class Test2 { public static void main(String[] args) throws Exception{ // 使用反射機(jī)制調(diào)用方法 // 第一步:獲取類(lèi) Class<?> clazz = Class.forName("com.bjpowernode.reflect.SomeService"); // 第二步:獲取方法 Method doSomeMethod = clazz.getDeclaredMethod("doSome", String.class, int.class); // 第三步:調(diào)用方法,四要素 // 創(chuàng)建對(duì)象 Object obj = clazz.newInstance(); // 這個(gè)方法已經(jīng)過(guò)時(shí),也可以采用其它方式 // 也可以先獲取到無(wú)參數(shù)構(gòu)造方法,然后在創(chuàng)建對(duì)象 Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(); Object obj1 = declaredConstructor.newInstance(); // 調(diào)用invoke方法 Object retValue = doSomeMethod.invoke(obj, "李四", 250); System.out.println(retValue); } }
3. SpringDI核心實(shí)現(xiàn)原理
我們?cè)诳匆幌孪旅孢@種需求,假設(shè)你現(xiàn)在已知以下信息: ①有這樣一個(gè)類(lèi),類(lèi)名叫做:com.powernode.reflect.User ②這個(gè)類(lèi)符合javabean規(guī)范。屬性私有化,對(duì)外提供公開(kāi)的setter和getter方法。 ③你還知道這個(gè)類(lèi)當(dāng)中有一個(gè)屬性,屬性的名字叫做 age ④并且你還知道age屬性的類(lèi)型是int類(lèi)型。要求:請(qǐng)使用反射機(jī)制調(diào)用set方法,給User對(duì)象的age屬性賦值!
User類(lèi)
package com.bjpowernode.reflect; public class User { private String name; private int age; public User() { } public User(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
使用反射機(jī)制進(jìn)行賦值,通用代碼
第一步:還是通過(guò)反射機(jī)制先獲取類(lèi),Class.forName
第二步:調(diào)用getDeclaredMethod方法獲取方法,參數(shù)有兩個(gè),怎么樣動(dòng)態(tài)獲取呢?
①已知了屬性名是age,又符合javabean規(guī)范,所以我們可以動(dòng)態(tài)拼接出方法名:先拼接上“set”,再調(diào)用toUpperCase方法全部轉(zhuǎn)換成大寫(xiě),然后調(diào)用charAt方法截取第一個(gè)字符;最后在調(diào)用substring方法拼接上后面的字符串;得到完整的方法名:getAge
②已知了屬性名是age,調(diào)用類(lèi)的getDeclaredField方法,參數(shù)是屬性名age,就可以獲取對(duì)應(yīng)的屬性類(lèi)型,但是我們需要的是.class,所以在調(diào)用參數(shù)類(lèi)型的getType方法;得到完整的屬性類(lèi)型(.class形式):int.class
第三步:最后就可以創(chuàng)建對(duì)象,調(diào)用invoke方法,給屬性賦值,這個(gè)方法沒(méi)有返回值類(lèi)型,所以什么都不要返回;最后輸出這個(gè)對(duì)象即可!
package com.bjpowernode.reflect; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Locale; public class Test4 { public static void main(String[] args) throws Exception { // 已知類(lèi)名和屬性名 String className = "com.bjpowernode.reflect.User"; String propertyName = "age"; // 使用反射機(jī)制,給age屬性賦值 // 第一步:獲取類(lèi) Class<?> clazz = Class.forName(className); // 第二步:獲取方法 // 根據(jù)屬性獲取方法名---字符串拼接 String setMethodName = "set"+propertyName.toUpperCase().charAt(0)+propertyName.substring(1); // 根據(jù)屬性獲取屬性的類(lèi)型 Field filedType = clazz.getDeclaredField(propertyName); // 獲取方法 Method setMethod = clazz.getDeclaredMethod(setMethodName, filedType.getType()); // 第三步:調(diào)用 // 創(chuàng)建對(duì)象 Object obj = clazz.newInstance(); setMethod.invoke(obj,18); // 沒(méi)有返回值類(lèi)型 // 輸出打印這個(gè)對(duì)象 System.out.println(obj); } }
執(zhí)行結(jié)果:age屬性成功賦值
看到這里我們是不是想到了Spring容器的注入?我們?cè)诳匆幌挛覀兣渲玫膕pring.xml文件,就是指定了類(lèi)名和屬性名;然后底層通過(guò)反射機(jī)制進(jìn)行了對(duì)象的創(chuàng)建!
總結(jié):有了上面我們對(duì)反射機(jī)制的回顧學(xué)習(xí),后面我們就嘗試手寫(xiě)一個(gè)簡(jiǎn)易的Spring框架!
到此這篇關(guān)于淺談Spring6中的反射機(jī)制的文章就介紹到這了,更多相關(guān)Spring6反射機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
簡(jiǎn)單講解在Java編程中實(shí)現(xiàn)設(shè)計(jì)模式中的單例模式結(jié)構(gòu)
這篇文章主要介紹了簡(jiǎn)單講解在Java編程中實(shí)現(xiàn)設(shè)計(jì)模式中的單例模式結(jié)構(gòu),設(shè)計(jì)模式是最基本直白簡(jiǎn)單的一種設(shè)計(jì)模式,需要的朋友可以參考下2016-04-04Java?輸入輸出?IO?NIO?AIO三兄弟對(duì)比分析對(duì)比分析
這篇文章主要為大家介紹了Java?輸入輸出?IO?NIO?AIO三兄弟對(duì)比分析對(duì)比分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04idea 打包的jar運(yùn)行報(bào) "XXX中沒(méi)有主清單屬性"
這篇文章主要介紹了idea 打包的jar運(yùn)行報(bào) "XXX中沒(méi)有主清單屬性",文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03Java控制臺(tái)實(shí)現(xiàn)猜拳游戲小游戲
這篇文章主要為大家詳細(xì)介紹了Java控制臺(tái)實(shí)現(xiàn)猜拳游戲小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11Spring @Transaction 注解執(zhí)行事務(wù)的流程
這篇文章主要介紹了Spring @Transaction 注解執(zhí)行事務(wù)的流程,Spring 是如何開(kāi)啟事務(wù)的?又是如何進(jìn)行提交事務(wù)和關(guān)閉事務(wù)的,本文給大家詳細(xì)介紹,需要的朋友可以參考下2021-06-06springboot多租戶(hù)設(shè)計(jì)過(guò)程圖解
這篇文章主要介紹了springboot多租戶(hù)設(shè)計(jì)過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12