看到這個標題大家可能又想:哎,又一個重新發明輪子的人。在這裏很想先聲明一下,寫這篇文章只是想讓大家瞭解一下Spring到底是怎麼運行的,並不是想重造輪子噢,希望大家看完這篇文章後能對Spring運作機制有更深入的瞭解,希望這篇文章對你有所幫助喔!好,言歸正傳,讓我們來一起探索吧!
我們先從最常見的例子開始吧
Java的代碼
- 公共靜態無效的主要(字串[] args){
- ApplicationContext的 背景 = 新 FileSystemXmlApplicationContext來(
- “的applicationContext.xml”);
- 動物 動物 =(動物)context.getBean(“動物”);
- animal.say();
- }
這段代碼你一定很熟悉吧,不過還是讓我們分析一下它吧,首先是applicationContext.xml
Java的代碼
- < bean的 ID = “動物” 類= “phz.springframework.test.Cat” >
- < 屬性 名= “姓名” >
- < 值>的小貓</ 值>
- </ 屬性>
- </ 豆>
他有一個類phz.springframework.test.Cat =
Java的代碼
- 公共類Cat實現動物{
- 私人字符串名稱;
- 公共無效的發言權(){
- 的System.out.println(“我”+姓名+“!”);
- }
- 公共無效setname可以(字符串名稱){
- this.name =名稱;
- }
- }
實現了phz.springframework.test.Animal接口
Java的代碼
- 公共接口動物{
- 公共無效說();
- }
很明顯上面的代碼輸出,我的小貓!
那麼到底春天是如何做到的呢?
接下來就讓我們自己寫個春天來看看春天運作機制吧!
首先,我們定義一個Bean的類,這個類用來存放一個豆擁有的屬性
Java的代碼
- / *豆ID * /
- 私人字符串ID;
- / * Bean類* /
- 私人字符串類型;
- / * Bean屬性* /
- 私人地圖< 字符串,對象> 屬性 = 新 的HashMap < 字符串,對象>();
一個豆包括編號,類型,和屬性。
接下來春天 的標識,HasMap
地圖配置可以像下面的
Java的代碼
- < bean的 ID = “測試” 級= “測試” >
- < 屬性 名= “testMap” >
- < 圖>
- < 進入 關鍵= “A” >
- < 值> 1 </ 值>
- </ 入門>
- < 進入 關鍵= “B” >
- < 值> 2 </ 值>
- </ 入門>
- </ 圖>
- </ 屬性>
- </ 豆>
春天的運作機制中是怎樣保存上面的配置呢,代碼如下?
Java的代碼
- 如果(beanProperty.element(“映射”)!= NULL){
- 地圖< 字符串,對象> propertiesMap = 新 的HashMap < 字符串,對象>();
- 元素 propertiesListMap =(元素)的BeanProperty
- .elements()得到(0)。
- 迭代器<?> propertiesIterator = propertiesListMap
- 。.elements()迭代器();
- 而(propertiesIterator.hasNext()){
- 元素 獸醫 =(元)propertiesIterator.next();
- 如果(vet.getName()。等於(“入口”)){
- 字符串 鍵 = 獸醫.attributeValue(“鑰匙”);
- 迭代器<?> valuesIterator = 獸醫.elements()
- .iterator();
- 而(valuesIterator.hasNext()){
- 元素 值 =(元素)valuesIterator.next();
- 如果(value.getName()。等於(“價值”)){
- propertiesMap.put(鍵,value.getText());
- }
- 如果(value.getName()。等於(“參考”)){
- propertiesMap.put(鍵,新的String [] {值
- .attributeValue(“豆”)});
- }
- }
- }
- }
- 。bean.getProperties()擺(姓名,propertiesMap);
- }
接下來就進入最核心部分了,讓我們看看春天到底是怎麼依賴注入的吧,其實依賴注入的思想也很簡單,它是通過反射機制實現的,在實例化一個類時,它通過反射調用類中set方法將事先保存在HashMap中的類屬性注入到類中。讓我們看看具體它是怎麼做的吧。
首先實例化一個類,像這樣
Java的代碼
- 公共靜態對象的newInstance(絃樂的className){
- 類<?> CLS = 空;
- 對象 的obj = 空;
- 嘗試{
- CLS = 類.forName(類名);
- OBJ = CLS .newInstance();
- }趕上(ClassNotFoundException異常E){
- 拋出新的RuntimeException(五);
- }趕上(InstantiationException五){
- 拋出新的RuntimeException(五);
- }趕上(IllegalAccessException五){
- 拋出新的RuntimeException(五);
- }
- 返回的obj;
- }
接着它將這個類的依賴注入進去,像這樣
Java的代碼
- 公共靜態無效的SetProperty(obj對象,字符串名稱,字符串值){
- 類<? 擴展 對象> clazz所 = OBJ .getClass();
- 嘗試{
- 字符串 方法名 = returnSetMthodName (名稱);
- 方法[] 毫秒 = clazz所.getMethods();
- 對於(方法M:毫秒){
- 如果(m.getName()。等於(方法名)){
- 如果(m.getParameterTypes().length == 1){
- 類<?> clazzParameterType = m.getParameterTypes()[0];
- setFieldValue(clazzParameterType.getName(),價值,男,
- OBJ);
- 打破;
- }
- }
- }
- }趕上(SecurityException異常E){
- 拋出新的RuntimeException(五);
- }趕上(拋出:IllegalArgumentException五){
- 拋出新的RuntimeException(五);
- }趕上(IllegalAccessException五){
- 拋出新的RuntimeException(五);
- }趕上(的InvocationTargetException五){
- 拋出新的RuntimeException(五);
- }
- }
最後它將這個類的實例返回給我們,我們就可以用了。我們還是以Map爲例看看它是怎麼做的,我寫的代碼裏面是創建一個HashMap並把該HashMap注入到需要注入的類中,像這樣,
Java的代碼
- 如果(值的instanceof地圖){
- 迭代器<?> entryIterator =((地圖<? , ?>)值).entrySet()
- .iterator();
- 地圖< 字符串,對象> 圖 = 新 的HashMap < 字符串,對象>();
- 而(entryIterator.hasNext()){
- 進入<? , ?> entryMap =(進入<? , ?>)entryIterator.next();
- 如果(entryMap.getValue()的instanceof的String []){
- map.put((絃樂)entryMap.getKey()
- 的getBean(((字符串[])entryMap.getValue())[0]));
- }
- }
- BeanProcesser.setProperty(OBJ,財產,地圖);
- }
好了,這樣我們就可以用春給我們創建的類了,是不是也不是很難啊?當然Spring能做到的遠不止這些,這個示例程序僅僅提供了Spring最核心的依賴注入功能中的一部分。這也是Spring運作機制中的一部分。
本文參考了大量文章無法一一感謝,在這一起感謝,如果侵犯了你的版權深表歉意,很希望對大家有幫助!
附件中包含該山寨Spring的源碼,核心只有五個類,還有一個測試程序,phz.springframework.test.AnimalSayApp,可以直接運行。