容器工廠(原型&單例)
阿新 • • 發佈:2017-11-29
col ima hash ssl init image 判斷 catch sax解析
上一篇講的是容器工廠的原型。
我們可以不必通過new關鍵之創建實例,可以直接取容器裏面的實例。
我們可以發現,在對比他們的地址值的時候,他們是相同的為true。
如果我們需要的是不一樣的呢。也就是有一些特殊的操作需要到的是單例地址。
下面讓我們看看如何創建一個可以隨意切換原型&單例的容器工廠吧。
我們在上一篇原型的容器工廠上稍微做一下改造就OK了!
添加一個描述bean的類,封裝了配置文件bean的類
public class Definition { //bean的唯一標識 private String id; //bean的完整類名 private String className;//bean的創建方式 private String scope = "singleton"; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; }public String getScope() { return scope; } public void setScope(String scope) { this.scope = scope; } }
第二,我們需要在容器工廠的類裏面做出稍稍的改動。
如下:
public class ContainerFactoryTwo { //單例的容器(Singleton) private static Map<String,Object> singleton = new HashMap<String,Object>();//原型的容器(prototype) private static Map<String,Definition> prototype = new HashMap<String,Definition>(); //初始化 public ContainerFactoryTwo(String resourcePath){ initPrototype(resourcePath); initSingleton(); } public void initPrototype(String resourcePath){ //創建SAX解析器 SAXReader reader = new SAXReader(); try { Document document = reader.read(Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath)); Element root = document.getRootElement(); List<Element> list = root.elements(); for (Element e:list){ String id = e.attributeValue("id"); String className = e.attributeValue("class"); String scope = e.attributeValue("scope"); //構建bean的定義 Definition def = new Definition(); def.setId(id); def.setClassName(className); if(scope!=null){ def.setScope(scope); } prototype.put(id,def); } } catch (Exception e) { throw new RuntimeException(e); } } /** * 初始化單利容器 */ private void initSingleton(){ //遍歷prototype裏面的值做出判斷 for (String key : prototype.keySet()) { Definition def = prototype.get(key); //如果是判斷是否是singleton if("singleton".equals(def.getScope())){ try { //將實例化對象保存到singleton的map裏 singleton.put(key, Class.forName(def.getClassName()).newInstance()); } catch (Exception e) { throw new RuntimeException(e); } } } } public Object getBean(String name){ return getContainerBean(name); } public <T> T getBean(String name, Class<T> clazz){ return (T)getContainerBean(name); } private Object getContainerBean(String name){ //獲取作用域屬性 String scope = prototype.get(name).getScope(); try { //三目運算,singleton在scope裏面?是的話就之前前者(K對應的已經是一個Object對象)否則執行後者,通過類加載返回一個對象 return ("singleton".equals(scope))?singleton.get(name): Class.forName(prototype.get(name).getClassName()).newInstance(); } catch (Exception e) { throw new RuntimeException(e); } } }
測試:
public class Main { public static void main(String[] args) { //創建工廠 ContainerFactoryTwo factory = new ContainerFactoryTwo("beans.xml"); Phone phone1 = factory.getBean("OppoPhone", Phone.class);//singleton Phone phone2 = factory.getBean("OppoPhone", Phone.class);//singleton Pad pad1 = (Pad) factory.getBean("OppoPad", Pad.class);//prototype Pad pad2 = (Pad) factory.getBean("OppoPad", Pad.class);//prototype System.out.println(phone1==phone2); System.out.println(pad1==pad2); //phone1.call(); } }
結果為:
true
false
註意:在XML文件裏面的scope
決定單例或者是原型容器在於Map
容器工廠(原型&單例)