摘要:有多種注入的策略,比如按照裝配名稱,或者是默認(rèn)實(shí)現(xiàn)了接口或者抽象類的子類實(shí)例對(duì)象來注入。這個(gè)方法中,做了一些簡單的判斷,如果這個(gè)類本身就不是一個(gè)抽象類或者不是一個(gè)接口,那么這個(gè)類就是第一個(gè)合適的類。
申明:本文不是講解Spring如何使用注解,本文只是通過一個(gè)簡單的實(shí)現(xiàn),來理解Spring是如何注入一個(gè)對(duì)象的。
??用過Spring的同學(xué)都知道,Spring利用注解來實(shí)現(xiàn)依賴注入,使得各個(gè)類之間的耦合性極大的降低了。但是僅僅是使用,并不能理解到Spring內(nèi)部是怎么實(shí)現(xiàn)的。筆者沒有看過Spring的源碼。只能從自己的角度來談?wù)凷pring是怎么實(shí)現(xiàn)的。感興趣的同學(xué)可以在看過本文之后,深入的了解Spring.
??很多時(shí)候,我們都有這樣的應(yīng)用場景。比如DAO層,你會(huì)先申明一個(gè)接口,比如IUserDao,表示用來處理User的一個(gè)接口,然后再寫一個(gè)實(shí)現(xiàn)類UserDaoImpl實(shí)現(xiàn)了IUserDao中的方法,然后在上層service層中注入。啟動(dòng)之后Spring將自己掃描自動(dòng)為我們注入實(shí)例化的對(duì)象,使得我們不用在意各個(gè)對(duì)象的生命周期。接下來就來聊聊具體是怎么注入的。
假設(shè)現(xiàn)在已經(jīng)有以下的類:
public interface IUserDao { public void setData(String data); public String getData(); } public class UserDaoImpl implements IUserDao{ @Override public void setData(String data) { System.out.println("data is : " + data); } @Override public String getData() { return "just test"; } }
??其中FieldInject是筆者模仿寫的一個(gè)注解,具體定義如下
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FieldInject { //假設(shè)有一些變量用于控制策略 }
??具體關(guān)于注解上面的元注解的含義,可以看另外一篇博客。這里就不展開說明了。
以上就是準(zhǔn)備工作了,接下來就是講解真正的初始化方法了。
??假設(shè)我們現(xiàn)在有一個(gè)類的Class對(duì)象,那么我們可以根據(jù)這個(gè)Class對(duì)象找到哪些成員變量是加了指定的注解的。代碼如下
//下面開始注入 for(int i=0; i??在這段代碼中,筆者查詢的注解是自己實(shí)現(xiàn)的一個(gè)FieldInject注解,注解本身并不影響代碼的執(zhí)行。通過判斷是否為空可以得出某個(gè)成員變量是否加了指定的注解。如果發(fā)現(xiàn)成員變量加了注解,就可以為該成員變量注入實(shí)例化的對(duì)象了。
??問題1:怎么知道注入哪個(gè)對(duì)象?
??問題2:怎么注入?
??問題2很好解決,如果原來的類中帶有setter方法,那么可以使用method.invoke()方法來調(diào)用并注入?;蛘咄ㄟ^field直接注入都可以。那么主要是問題1,怎么找到合適的注入對(duì)象。
??Spring有多種注入的策略,比如按照裝配名稱,或者是默認(rèn)實(shí)現(xiàn)了接口或者抽象類的子類實(shí)例對(duì)象來注入。總之,不同的策略只是選擇的不同,我們可以假定使用找到的第一個(gè)合適子類的實(shí)例對(duì)象來注入。//找到某個(gè)類的子類【涉及到Spring的選擇策略】 private Class findSubClass(String fullClassName){ try { Class target = Class.forName(fullClassName); //不是抽象類,不是接口,那自身就好了。 if(!target.isInterface()){ boolean isAbs = Modifier.isAbstract(target.getModifiers()); if(!isAbs) return target; } int size = clazzList.size(); for(int i=0; i??findSubClass是用來找到某個(gè)類的合適子類,類似于Spring中根據(jù)某種策略來查找,這里使用了比較簡單的方法。找到第一個(gè)合適的子類即可。這個(gè)方法中,做了一些簡單的判斷,如果這個(gè)類本身就不是一個(gè)抽象類或者不是一個(gè)接口,那么這個(gè)類就是第一個(gè)合適的類。如果這個(gè)類是一個(gè)接口或者一個(gè)抽象類,那么就在全局掃描的classList中找到合適的類。找到合適的類之后,下一步就是一個(gè)注入了,筆者采用的是給setter方法注入,如果想直接給成員變量賦值也是非常簡單的。只要替換掉方法injectMethod,換成下面兩句代碼即可。
field[i].setAccessible(true); field[i].set(target, obj);??injectMethod實(shí)現(xiàn)也是比較簡單,通過比對(duì)Method中的方法,找到合適的setter方法(這里是通過field的名稱來判斷的),并將實(shí)例對(duì)象賦值進(jìn)去即可。以上就是一個(gè)簡單的注入過程的實(shí)現(xiàn)。筆者寫的比較匆忙,可能有些細(xì)節(jié)上經(jīng)不起推敲。但是如果能為迷惑的初學(xué)者提供一個(gè)思路也是不錯(cuò)的,這份代碼我都上傳到github上了,如果想下載進(jìn)行運(yùn)行的可以移步我的github。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/66788.html
摘要:使用的好處知乎的回答不用自己組裝,拿來就用。統(tǒng)一配置,便于修改。 前言 只有光頭才能變強(qiáng) 回顧前面: 給女朋友講解什么是代理模式 包裝模式就是這么簡單啦 單例模式你會(huì)幾種寫法? 工廠模式理解了沒有? 在刷Spring書籍的時(shí)候花了點(diǎn)時(shí)間去學(xué)習(xí)了單例模式和工廠模式,總的來說還是非常值得的! 本來想的是刷完《Spring 實(shí)戰(zhàn) (第4版)》和《精通Spring4.x 企業(yè)應(yīng)用開發(fā)實(shí)戰(zhàn)》...
摘要:它的構(gòu)造器上添加了注解,這表明當(dāng)創(chuàng)建的時(shí)候,會(huì)通過這個(gè)構(gòu)造器來進(jìn)行實(shí)例化并且會(huì)傳入一個(gè)可設(shè)置給類型的通過自動(dòng)裝配,將一個(gè)注入到之中注解不僅能夠用在構(gòu)造器上,還能用在屬性的方法上。 Spring配置的可選方案 Spring容器負(fù)責(zé)創(chuàng)建應(yīng)用程序中的bean并通過DI來協(xié)調(diào)這些對(duì)象之間的關(guān)系。當(dāng)描述bean如何進(jìn)行裝配時(shí),Spring具有非常大的靈活性,它提供了三種主要的裝配機(jī)制: 在XM...
摘要:關(guān)于依賴注入注入的注解提供的注解不僅僅是對(duì)象,還有在構(gòu)造器上,還能用在屬性的方法上。與之相反,的限定符能夠在所有可選的上進(jìn)行縮小范圍的操作,最終能夠達(dá)到只有一個(gè)滿足所規(guī)定的限制條件。注解是使用限定符的主要方式。 本文首發(fā)于泊浮目的專欄:https://segmentfault.com/blog... Spring致力于提供一種方法管理你的業(yè)務(wù)對(duì)象。在大量Java EE的應(yīng)用中,隨處可...
摘要:入門篇學(xué)習(xí)總結(jié)時(shí)間年月日星期三說明本文部分內(nèi)容均來自慕課網(wǎng)。主要的功能是日志記錄,性能統(tǒng)計(jì),安全控制,事務(wù)處理,異常處理等等。 《Spring入門篇》學(xué)習(xí)總結(jié) 時(shí)間:2017年1月18日星期三說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)示例源碼:https://github.com/zccodere/s...個(gè)人學(xué)習(xí)源碼:https://git...
摘要:先來看代碼吧,一會(huì)松哥再慢慢解釋關(guān)于這一段自動(dòng)配置,解釋如下首先注解表明這是一個(gè)配置類。本文的案例,松哥已經(jīng)上傳到上了,地址。我們使用 Spring Boot,基本上都是沉醉在它 Stater 的方便之中。Starter 為我們帶來了眾多的自動(dòng)化配置,有了這些自動(dòng)化配置,我們可以不費(fèi)吹灰之力就能搭建一個(gè)生產(chǎn)級(jí)開發(fā)環(huán)境,有的小伙伴會(huì)覺得這個(gè) Starter 好神奇呀!其實(shí) Starter 也都...
閱讀 3127·2023-04-25 15:02
閱讀 2835·2021-11-23 09:51
閱讀 2045·2021-09-27 13:47
閱讀 2003·2021-09-13 10:33
閱讀 987·2019-08-30 15:54
閱讀 2651·2019-08-30 15:53
閱讀 2868·2019-08-29 13:58
閱讀 901·2019-08-29 13:54