spring入門(二)

qq_35383788發表於2020-11-18

上一節提到程式的解耦,但是出現了一個問題,就是在

Clinet

類中,如果列印得到的物件:

for(int i=0;i<6;i++){
    AccountService accountService = (AccountService) BeanFactory.getBean("accountService");
    System.out.println(accountService);
}

結果就是得到5個不同的accountService物件。原因是因為

BeanFactory

類中的這句話:

bean = Class.forName(beanPath).newInstance();//每次都會用預設的構造器建立新的物件

所以,這問題怎麼解決呢?

利用Map集合處理。

package com.springpractise.demo.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;

/**
 * 一個建立Bean物件的工廠
 * Bean:在計算機英語中有可重用元件的含義
 * javaBean:用java語言編寫的可重用元件
 * 建立javaBean:
 *  第一個:需要一個配置檔案來配置service和dao
 *       配置的內容:唯一標誌 = 全限定類名(key = value)
 *  第二個:通過讀取配置檔案中配置的內容,反射建立物件
 *
 *  配置檔案可以是xml也可以是properties
 *
 */
public class BeanFactory {
    //定義一個Properties物件
    private static Properties properties;
    //定義一個Map,用於存放我們要建立的物件。我們把它稱之為容器
    private static Map<String,Object> beans;
    //使用靜態程式碼塊為Properties物件賦值
    static {
        try {
        //例項化物件
        properties = new Properties();
        //獲取properties檔案的流物件(通過BeanFactory來獲取檔案)
        InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
        properties.load(in);
        beans = new HashMap<>();
            Enumeration<Object> keys = properties.keys();
            //遍歷列舉
            while (keys.hasMoreElements()){
                //取出每個key
                String key = keys.nextElement().toString();
                //根據key獲取value
                String beanPath = properties.getProperty(key);
                //反射建立物件
                Object value = Class.forName(beanPath).newInstance();
                beans.put(key,value);
            }
        } catch (IOException e) {
            throw new ExceptionInInitializerError("初始化properties失敗");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根據Bean名稱獲取物件
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
        return beans.get(beanName);
    }
}

 

可以看到,在靜態程式碼塊中,初次載入的時候,就把物件放進Map中,以後每次要用物件的時候,直接用key去獲取物件就可以了。

這樣一來,列印多次物件的時候,都是從同一個key獲取的物件,因此就避免了多次例項化。

相關文章