歡迎關注頭條號:JAVA小野貓
首先我們要知道java獲得對象的方式有四種:
1.通過new語句實例化一個對象。
2.通過反射機制創建對象。
3.通過clone()方法創建對象
3.通過反序列化的方式創建對象
在spring框架中,為了減低耦合,可以使用xml,properties加載配置文件,然后通過反射來獲得對象,下面來講一講通過加載properties的配置文件來獲得代理對象
第一步
創建配置文件
accountService=com.itheima.service.impl.AccountServiceImpl accountDao=com.itheima.dao.impl.AccountDaoImpl
配置文件講解:
accountService是key,
com.itheima.service.impl.AccountServiceImpl是value,也就是全限定類名(為什么要全限定類名,因為要通過反射來獲得對象)
第二步
接下來就是實例化properties對象使用對象的方法load來讀取配置文件了
讀取完配置文件就會獲得全限定類名,有了全限定了類名創建對象就好辦了
package com.itheima.factory; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class BeanFactory { private static Properties props; static { InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"); //實例化對象 props = new Properties(); try { //讀取配置文件 props.load(in); } catch (IOException e) { e.printStackTrace(); } } public static Object getBean(String beanName){ Object bean = null; //getProperty方法 官方文檔解釋 /* 使用此屬性列表中指定的鍵搜索屬性。 */ String beanPath = props.getProperty(beanName); try { //獲得對象 bean = Class.forName(beanPath).newInstance(); } catch (Exception e) { e.printStackTrace(); } //返回對象,誰調用我我返回給誰 return bean; } }
第三步
改造問題
上述的代碼依然存在問題,問題如下所示
public static void main(String[] args) { //IAccountService as = new AccountServiceImpl(); for(int i=0;i<5;i++){ IAccountService as = (IAccountService)BeanFactory.getBean("accountService"); as.saveAccount(); System.out.println(as); } }
上述代碼中,我讓他循環了5次,他輸出的結果每一次都不一樣,如圖所示
沒調用一次,就會產生一個新的對象,這樣會造成效率低下的問題
所以我們就來到第四步,看看怎么樣來解決這個問題(第四步相當于引出spring容器的概念)
第四步
首先要知道為什么每次調用getBean方法都會創建一個新的對象,原因就是在于這里newInstance()
解決方案就是,創建完對象就把他用Map存起來,所以static代碼塊,不僅要獲得對象,還要實例化容器Map,還要添加對象到容器里面去。
package com.itheima.factory; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Properties; public class BeanFactory { private static Properties props; private static Map<String,Object> beans; static { InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"); //實例化對象 props = new Properties(); try { //讀取配置文件 props.load(in); //實例化容器 beans = new HashMap(); //查看API文檔發現 //keys()繼承自Hashtable<Object,Object> //使用keys()可以獲取配置文件的所有鍵 Enumeration keys = props.keys(); //遍歷枚舉 while(keys.hasMoreElements()){ String key = keys.nextElement().toString(); //根據Key獲取value String beanPath = props.getProperty(key); //反射創建對象 Object value = Class.forName(beanPath).newInstance(); //把key和value存入map集合 beans.put(key,value); } } catch (Exception e) { e.printStackTrace(); } } //對象已經在初始化時就創建了,所以獲取對象就沒有那么麻煩了 public static Object getBean(String beanName) { return beans.get(beanName); } }
最后一步
現在無論調用多少次getBean,對象都只有一個了,為什么只有一個,因為對象在static代碼塊初始化時就創建了,而且還添加到了容器中,你通過getBean方法獲取就從容器中獲取,而不是再次newInstance()獲得
歡迎做Java的朋友們私信我【資料】免費獲取免費的Java架構學習資料(里面有高可用、高并發、高性能及分布式、Jvm性能調優、Spring源碼,MyBatis,Netty,redis,Kafka,MySQL,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)
其中覆蓋了互聯網的方方面面,期間碰到各種產品各種場景下的各種問題,很值得大家借鑒和學習,擴展自己的技術廣度和知識面。