以前說過,依賴注入就是爲了解決依賴的問題的,在Spring中,原本應該本身入new的對象本身不來new了,交給bean去new。其實使用反射能夠實現依賴注入。java
下面就是簡單實現的方式:設計模式
使用反射能夠new出新的實例,咱們能夠這麼作:spa
1 public Object getInstance(String ClassName){ 2 private Object result=null; 3 try { 4 result=Class.forName(ClassName).newInstance(); 5 } catch (ClassNotFoundException e) { 6 e.printStackTrace(); 7 } catch (InstantiationException e) { 8 e.printStackTrace(); 9 } catch (IllegalAccessException e) { 10 e.printStackTrace(); 11 } 12 return result; 13 }
爲了保證通用性,這裏使用了返回Object類型。以後能夠直接在代碼中調用這個方法,在反射中實現依賴注入(假設有一個User接口和他的實現類):設計
1 TestIOC testIOC=new TestIOC(); 2 User user=(User)testIOC.getInstance("com.smile.UserImpl"); 3 user.sayHey();
第一行爲剛剛封裝反射方法的類。好像仍是沒有達到預知的效果,這裏開始修改:code
將實現類放到外面的配置文件中,到使用的時候載注入到其中。xml
那麼咱們加入瞭如下配置文件:對象
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> 3 <properties> 4 <entry key="className">com.smile.User</entry> 5 </properties>
而後在讀取配置文件:blog
1 InputStream inputStream=ClassLoader.getSystemResourceAsStream("testxml.xml"); 2 Properties properties=new Properties(); 3 properties.loadFromXML(inputStream); 4 String ClassName=properties.getProperty("className"); 5 System.out.println(ClassName);
這裏好像有點似曾相識了,以前使用Spring的時候,就有相似的代碼:接口
1 public void UseTest(){ 2 ApplicationContext context=new ClassPathXmlApplicationContext("SpringConfig.xml"); 3 Hello hello=(Hello)context.getBean("hello"); 4 hello.sayHello(); 5 }
讀取玩配置文件還會進行下一步的操做,也會有相似的代碼:utf-8
1 TestIOC testIOC=new TestIOC(); 2 User user=(User)testIOC.getInstance(ClassName); 3 user.sayHey();
是否是和Spring的代碼中驚人的類似了,咱們在程序中沒有本身去new對象,而是交給了咱們本身寫出來的方法去new,咱們的代碼會根據咱們本身寫的配置文件獲得配置文件的信息,而後去new配置文件中寫好的對象,將依賴注入到這裏,若是咱們要使用的實現類出現了變化,那麼只須要修改xml配置文件中的信息就行了,大大減小了修改代碼的成本。經過以上就簡單的實現了依賴注入。
這種實現方式實際上使用了一種設計模式——抽象工廠。
那麼抽象工廠是一種什麼樣的設計模式呢?提供一個建立一系列相關或相互依賴的接口對象。而無需指定具體的類。
在剛剛的代碼中User就是抽象,之因此是抽象,是由於User可能會有不一樣的實現,而咱們利用反射而獲得的對象的方法——getInstance()就是工廠。之因此沒有看到抽象工廠的影子是由於使用反射的時候不須要再代碼中顯示的new出對象,而類名是字符串,能夠隨意修改,反射取代了抽象工廠,完成了依賴注入。
若是這裏使用純粹的抽象工廠的話會出現大量的類來new咱們須要的實例,反射只須要一個方法能夠new出來不少咱們須要的實例。
固然由於類過多的時候咱們也可使用簡單工廠來改進抽象工廠,就是講new的過程放到switch中new,在new的時候根據輸入的字符來判斷使用哪種方式,可是這裏若是咱們增長一個實現類的時候,就要再次修改代碼,在switch中加入case,這樣仍是會很麻煩,而利用反射也改進了這裏的缺點。