再談依賴注入(依賴注入的簡單實現)
下面就是簡單實現的方式:
使用反射可以new出新的例項,我們可以這麼做:
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();
第一行為剛剛封裝反射方法的類。好像還是沒有達到預知的效果,這裡開始修改:
將實現類放到外面的配置檔案中,到使用的時候載注入到其中。
那麼我們加入了以下配置檔案:
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>
然後在讀取配置檔案:
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 }
讀取玩配置檔案還會進行下一步的操作,也會有類似的程式碼:
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,這樣還是會很麻煩,而利用反射也改進了這裡的缺點。