Java—實現 IOC 功能的簡單 Spring 框架

編寫一個實現 IOC 功能的簡單 Spring 框架,包含對象注冊、對象管理、及暴 露給外部獲取對象的功能,并編寫測試程序。擴展注冊器的方式,要求采用 XML 和 txt 文件。

源代碼

package myspring;import java.lang.reflect.Method;
import java.util.Map;/*** 最頂層的IOC實現* 該類負責從注冊器中取出注冊對象* 實現從對象描述信息轉換為對象實例的過程、* 實現根據名稱獲取對象的方法*/
public abstract class AbstractBeanFactory implements BeanFactory {private String filePath;   //注冊文件路徑private Map<String,BeanInfo> container; //注冊對象信息Mapprotected SourceReader reader; //對象注冊讀取器public AbstractBeanFactory(String filePath){this.filePath = filePath;}/*** 該方法為抽象方法,需有子類類實現,用于指定使用什么樣的注冊讀取器* @param reader 指定的注冊讀取器*/protected abstract void setSourceReader(SourceReader reader);// 從注冊讀取器中讀取,注冊對象的信息MAPpublic void registerBeans(){this.container = this.reader.loadBeans(filePath);}//  實現BeanFactory定義的根據名稱獲取指定對象的方法@Overridepublic Object getBean(String name) {BeanInfo beaninfo = this.container.get(name); //根據對象名獲取該對象的描述信息if(beaninfo == null){ //如果容器中不存在該對象的描述信息,則返回null,此處可以拋開一個異常return null;}else{ //根據對象信息,解析并生成指定對象實例,返回給用戶return this.parseBean(beaninfo);}}  /*** 解析并生成對象實例* 該方法主要通過反射完成,步驟如下:* 1.根據類名,加載指定類,并獲取該類的貌似Class對象clazz* 2.使用Class對象clazz實例化該類,獲取一個對象,注意,這兒實例化對象時,采用的無參構造方法,因此要求注冊的對象必須含有無參構造方法* 3.逐個設置對象字段的值,這兒采用setter Method方式,而不是直接使用Field對象的原因是,用戶有可能在setter對象中,對注入的值進行額外處理,如格式化等* 4.返回對象實例* @param beaninfo 指定對象的描述信息* @return*/protected Object parseBean(BeanInfo beaninfo){Class clazz; try {clazz = Class.forName(beaninfo.getType()); //根據對象的全類名,指定類Object bean = clazz.newInstance(); //使用注冊對象的無參構造函數,實例化對象實例Method[] methods = clazz.getMethods(); //獲取該類聲明的所有公共方法,其實Spring獲取的是所有方法,包括非公有的for(String property : beaninfo.getProperties().keySet()){ //遍歷對象的所有屬性,進行賦值String setter = "set" + StringUtil.firstCharToUp(property); //獲取屬性的setter方法名稱for(Method method : methods){ //遍歷該類的所有公有方法String methodName = method.getName(); //獲取方法名稱if(methodName.equals(setter)){ //比較方法名與屬性的setter方法名是否相同,如果相同則進行賦值Object value = beaninfo.getProperties().get(property); //從對象描述信息中獲取該屬性的值method.invoke(bean,value); //通過反射對屬性進行賦值continue; //對下一屬性賦值}}}return bean; //返回指定的對象} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();} return null;}}package myspring;/*** IOC容器的頂層接口*/
public interface BeanFactory {/*** 根據對象的名稱標識來獲取對象實例* @param name 對象名稱,即對象描述信息中的對象標識* @return 指定名稱的對象實例*/Object getBean(String name);
}package myspring;import java.util.HashMap;
import java.util.Map;//該類用于描述注冊在容器中的對象
public class BeanInfo {private String id; //對象的標識private String type; //對象的類型,即全類名private Map<String,Object> properties = new HashMap<String,Object>(); //對象的屬性及值得集合 public String getId() {return id;}public void setId(String id) {this.id = id;}public String getType() {return type;}public void setType(String type) {this.type = type;}public Map<String,Object> getProperties() {return properties;}public void setProperties(Map<String, Object> properties) {this.properties = properties;}public void addProperty(String name, Object value){this.properties.put(name, value);}
}
package myspring;public class Bootstrap {public static void main(String[] args) {BeanFactory factory = new TXTContext("bean.txt");Speakable s = (Speakable)factory.getBean("Person");s.speak("Lesson one!");}
}
package myspring;public class Person implements Speakable {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic void speak(String message) {System.out.println( this.name + " say: " + message);}
}
package myspring;import java.util.Map;/*** 注冊讀取器接口* 負責從讀取用戶注冊的對象* 繼承該接口的類可以實現多種讀取方式,如從配置文件中讀取,根據標注讀取,從網絡中讀取等*/
public interface SourceReader {/*** 讀取用戶注冊的對象信息* @param filePath 讀取錄取* @return 注冊對象信息Map*/Map<String,BeanInfo> loadBeans(String filePath);
}
package myspring;public interface Speakable {public void speak(String message);
}
package myspring;public class StringUtil {/*public static void main(String[] args) {System.out.println(StringUtil.firstCharToUp(str)); }*/public static String firstCharToUp(String str){char ch[]=str.toCharArray();char ch1=Character.toUpperCase(ch[0]);ch[0]=ch1;String s=new String(ch);return s;}public static String firstCharToLower(String str){char ch[]=str.toCharArray();char ch1=Character.toLowerCase(ch[0]);ch[0]=ch1;String s=new String(ch);return s;}
}
package myspring;public class TXTContext extends AbstractBeanFactory {/*** 上下文的構造方法* 該方法中指明注冊讀取器* 并在構造該方法時一次性的加載注冊的對象* @param filePath*/public TXTContext(String filePath) {super(filePath);this.setSourceReader(new TXTSourceReader()); //添加注冊讀取器,此處的注冊讀取器為XMLSourceReaderthis.registerBeans(); //加載注冊的對象信息}//  設置注冊讀取器@Overrideprotected void setSourceReader(SourceReader reader) {this.reader = reader;}
}package myspring;import org.w3c.dom.*;
import org.xml.sax.SAXException;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.util.HashMap;
import java.util.Map;public class TXTSourceReader implements SourceReader{/*** 實現讀取注冊對象信息方法* 此處只是模擬測試使用,感興趣的同學可以自己書寫通過配置文件讀取的實現*/@Overridepublic Map<String, BeanInfo> loadBeans(String filePath) {//初始化一個對象信息Map<String,BeanInfo> beans = new HashMap<String,BeanInfo>(); //初始化一個對象信息MapBeanInfo beanInfo=new BeanInfo();File filename = new File("bean.txt"); // 要讀取以上路徑的input。txt文件InputStreamReader reader = null; // 建立一個輸入流對象readertry {reader = new InputStreamReader(new FileInputStream(filename));BufferedReader br = new BufferedReader(reader); // 建立一個對象,它把文件內容轉成計算機能讀懂的語言String line = "";line = br.readLine();while (line != null) {String[] t=line.split("=");System.out.println(t[0]+t[1]);if(t[0].equals("id")){beanInfo.setId(t[1]);}else if(t[0].equals("class")){beanInfo.setType(t[1]);}else beanInfo.addProperty(t[0],t[1]);line = br.readLine();}} catch (FileNotFoundException fileNotFoundException) {fileNotFoundException.printStackTrace();} catch (IOException ioException){ioException.printStackTrace();}beans.put(beanInfo.getId(),beanInfo);return beans; //返回對象信息MAP}package myspring;public class XMLContext extends AbstractBeanFactory{/*** 上下文的構造方法* 該方法中指明注冊讀取器* 并在構造該方法時一次性的加載注冊的對象* @param filePath*/public XMLContext(String filePath) {super(filePath);this.setSourceReader(new XMLSourceReader()); //添加注冊讀取器,此處的注冊讀取器為XMLSourceReaderthis.registerBeans(); //加載注冊的對象信息}  //  設置注冊讀取器@Overrideprotected void setSourceReader(SourceReader reader) {this.reader = reader;}
}package myspring;import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.xpath.XPath;import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;/*** XML注冊讀取器* 該類繼承了注冊讀取器接口,并模擬實現了讀取注冊對象信息的方法*/
public class XMLSourceReader implements SourceReader {/*** 實現讀取注冊對象信息方法* 此處只是模擬測試使用,感興趣的同學可以自己書寫通過配置文件讀取的實現*/@Overridepublic Map<String, BeanInfo> loadBeans(String filePath) {//初始化一個對象信息Map<String,BeanInfo> res = new HashMap<String,BeanInfo>(); //初始化一個對象信息Maptry {SAXBuilder builder = new SAXBuilder();Document doc = null;doc = (Document) builder.build(new File("book.xml"));  XPath xpath = null;    xpath = XPath.newInstance("//bean");List beans = null;beans = xpath.selectNodes(doc);  Iterator i = beans.iterator();while (i.hasNext()) {BeanInfo beaninfo = new BeanInfo();Element bean = (Element) i.next();String id = bean.getAttributeValue("id");String cls = bean.getAttributeValue("class");beaninfo.setId(id);beaninfo.setType(cls);List<Element> list = bean.getChildren("property");for (Element el : list) {if (el.getAttribute("name") != null) {beaninfo.addProperty(el.getAttributeValue("name"),el.getAttributeValue("value"));}}res.put(beaninfo.getId(),beaninfo);}} catch (JDOMException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return res;}
}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/392067.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/392067.shtml
英文地址,請注明出處:http://en.pswp.cn/news/392067.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

讀zepto核心源碼學習JS筆記(3)--zepto.init()

上篇已經講解了zepto.init()的幾種情況,這篇就繼續記錄這幾種情況下的具體分析. 1. 首先是第一種情況,selector為空 既然是反向分析,那我們先看看這句話的代碼; if (!selector) return zepto.Z() 這里的返回值為zepto.Z();那我們繼續往上找zepto.Z()函數 zepto.Z function(dom…

css flexbox模型_Flexbox和CSS Grid之間的主要區別

css flexbox模型by Shaira Williams由莎拉威廉姆斯(Shaira Williams) Flexbox和CSS Grid之間的主要區別 (The main differences between Flexbox and CSS Grid) Dimensions define the primary demarcation between Flexbox and CSS Grid. Flexbox was designed specifically …

置信區間估計 預測區間估計_估計,預測和預測

置信區間估計 預測區間估計Estimation implies finding the optimal parameter using historical data whereas prediction uses the data to compute the random value of the unseen data.估計意味著使用歷史數據找到最佳參數&#xff0c;而預測則使用該數據來計算未見數據的…

鴻蒙系統還會推出嗎,華為明年所有自研設備都升級鴻蒙系統,還會推出基于鴻蒙系統的新機...

不負期許&#xff0c;華為鴻蒙OS手機版如期而至。今日(12月15日)&#xff0c;鴻蒙OS 2.0手機開發者Beta版本正式上線&#xff0c;支持運行安卓應用&#xff0c;P40、Mate 30系列可申請公測。國內媒體報道稱&#xff0c;華為消費者業務軟件部副總裁楊海松表示&#xff0c;按照目…

C#中將DLL文件打包到EXE文件

1&#xff1a;在工程目錄增加dll目錄&#xff0c;然后將dll文件復制到此目錄&#xff0c;例如&#xff1a; 2&#xff1a;增加引用&#xff0c;定位到工程的dll目錄&#xff0c;選中要增加的dll文件 3&#xff1a;修改dll文件夾下面的dll文件屬性 選中嵌入式資源&#xff0c;不…

PopupMenu控件的使用

1、用PopupMenu控件能進行右鍵菜單的實現&#xff0c;它的實現還需要綁定到barManager控件上&#xff0c;在barManager的Customize中添加右鍵所需要顯示的功能。 2、PopupMenu屬性欄中綁定Manager為barManager&#xff1b; 3、窗體加載事件中創建 this.popupMenu1.AddItems(new…

Java—動態代理

動態代理利用了JDK API&#xff0c;動態地在內存中構建代理對象&#xff0c;從而實現對目標對象的代理功能。動態代理又被稱為JDK代理或接口代理。 靜態代理與動態代理的區別主要在&#xff1a; 靜態代理在編譯時就已經實現&#xff0c;編譯完成后代理類是一個實際的class文件…

Oracle VM Virtual Box的安裝

安裝Oracle VM Virtual Box安裝擴展插件 選擇"管理"?"全局設定" 在設置對話框中&#xff0c;選擇"擴展" 選擇"添加包" 找到"Oracle_VM_VirtualBox_Extension_Pack-4.1.18-78361"&#xff0c;點擊"打開" 5&#x…

python 移動平均線_Python中的SMA(短期移動平均線)

python 移動平均線With the evolution of technology rapidly evolving, so do strategies in the stock market. In this post, I’ll go over how I created a SMA(Short Moving Average) strategy.隨著技術的飛速發展&#xff0c;股票市場的策略也在不斷發展。 在本文中&…

angular中的href=unsafe:我該怎么擺脫你的溺愛!!

解決方法&#xff1a;angular.module加入下面這行&#xff1a;&#xff08;依據Angular changes urls to “unsafe:” in extension page&#xff09; .config(function($compileProvider){//注:有些版本的angularjs為$compileProvider.urlSanitizationWhitelist(/^\s*(https?…

android view gesturedetector,如何在Android中利用 GestureDetector進行手勢檢測

如何在Android中利用 GestureDetector進行手勢檢測發布時間&#xff1a;2020-11-26 16:15:21來源&#xff1a;億速云閱讀&#xff1a;92作者&#xff1a;Leah今天就跟大家聊聊有關如何在Android中利用 GestureDetector進行手勢檢測&#xff0c;可能很多人都不太了解&#xff0c…

Ubuntu2204配置samba

0.前情說明 samba服務器主要是用來局域網共享文件的&#xff0c;如果想公網共享可能行不通&#xff0c;我已經踩坑一天了 所以說如果你想滿足公網samba共享你就可以不要看下去了 1.參考連接 Ubuntu 安裝 Samba 服務器_ubuntu安裝samba服務器-CSDN博客 2.安裝samba服務 sud…

Java—BIO模型

利用 BIO 模型&#xff08;傳統阻塞 IO 模型&#xff09;實現多用戶訪問 源代碼 Server類 public class server {public static void main(String[] args) {ExecutorService executorService Executors.newFixedThreadPool(6);try {ServerSocket serverSocketnew ServerSocke…

c++學編程如何鍛煉耐力_我如何學習編程:這是一項耐力運動

c學編程如何鍛煉耐力by Amy M Haddad通過艾米M哈達德(Amy M Haddad) 我如何學習編程&#xff1a;這是一項耐力運動 (How I’m learning to program: it’s an endurance sport) 為什么我的編程學習軌跡反映了我作為跑步者的訓練方式 (Why my learning trajectory for programm…

python處理文本數據

處理文本數據&#xff0c;主要是通過Seris的str訪問。遇到NaN時不做任何處理&#xff0c;保留結果為NaN&#xff0c;遇到數字全部處理為NaN。 str是Seris的方法&#xff0c;DataFrame不能直接使用&#xff0c;但是通過索引選擇DataFrame中的某一行或者某一列&#xff0c;結果為…

Java系列筆記(4) - JVM監控與調優【轉】

Java系列筆記(4) - JVM監控與調優【轉】 目錄 參數設置收集器搭配啟動內存分配監控工具和方法調優方法調優實例 光說不練假把式&#xff0c;學習Java GC機制的目的是為了實用&#xff0c;也就是為了在JVM出現問題時分析原因并解決之。通過學習&#xff0c;我覺得JVM監控與調…

Maven打包排除某個資源或者目錄

最近在spark streaming本地調試的時候&#xff0c;引入了一些資源文件&#xff0c;打包的時候需要給排除掉。所以就考慮使用maven的方式 詳細參考官方文檔&#xff1a;https://maven.apache.org/plugins/maven-jar-plugin/examples/include-exclude.html 排除某個資源文件 <…

android發送網絡請求沒反應,Android無法使用HttpURLConnection發送GET請求

我正在嘗試在我的應用程序中使用HttpURLConnection.我將我的請求方法設置為’GET’,但是當我嘗試檢索輸出流時,該方法將更改為’POST’&#xff01;我不確定是什么原因,但是當我使用’POST’發送請求時,我的JSON服務器(我使用JAX-RS)會返回一個空白頁面.這是我的代碼片段&#…

地圖 c-suite_C-Suite的模型

地圖 c-suiteWe’ve all seen a great picture capture an audience of stakeholders.我們所有人都看到了吸引利益相關者聽眾的美好畫面。 Let’s just all notice that the lady in the front right is not captivated by the image on the board (Photo by Christina wocin…

框架和庫的區別_框架和庫之間的區別

框架和庫的區別Developers often use the terms “library” and “framework” interchangeably. But there is a difference.開發人員經常互換使用術語“庫”和“框架”。 但是有區別。 Both frameworks and libraries are code written by someone else that is used to he…