先大體說一下思路:以流的形式讀取一個配置文件,並將流中的信息解析並封裝到一個map1<String,BeanDefinition>中,BeanDefinition包含了配置文件的屬性信息,構建一個工廠,利用反射將構建的bean對象存入另外一個map2<String,Object>中,方便從工廠直接獲取對象. 其中map1做爲工廠的原料(須要從配置文件中獲取),map2做爲工廠產品(有工廠爲咱們建立的bean對象).java
先定義實體類 User.classnode
package com.spring; /** * 實體類 * @author wan_ys * */ public class User { private Integer id; private String name; }
Order.classspring
package com.spring; /** * 實體類 * @author wan_ys * */ public class Order { private Integer id; private String item; }
這裏寫一個簡單的配置文件 spring-config.xmldom
<?xml version="1.0" encoding="UTF-8"?> <beans> <bean id="user" class="com.spring.User"></bean> <bean id="order" class="com.spring.Order"></bean> </beans>
定義一個存放配置文件信息的類(屬性與配置文件中的屬性對應)ide
package com.spring; /** * 包裝配置文件中bean的配置信息 * @author wan_ys * */ public class BeanDefinition { private String id; private String claString;//對應配置文件中的class屬性 public String getId() { return id; } public void setId(String id) { this.id = id; } public String getClaString() { return claString; } public void setClaString(String claString) { this.claString = claString; } @Override public String toString() { return "BeanDefinition [id=" + id + ", claString=" + claString + "]"; } }
模仿Spring寫一個DefaultBeanFactory工廠測試
package com.spring; /** * Bean工廠 * @author wan_ys * */ import java.io.InputStream; import java.lang.reflect.Constructor; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class DefaultBeanFactory { // 存儲bean的信息(原料) Map<String, BeanDefinition> beanMap = new ConcurrentHashMap<String, BeanDefinition>(); // 存儲示例對象(產品) Map<String, Object> instanceMap = new ConcurrentHashMap<String, Object>(); public DefaultBeanFactory(String configFilePath) { // 獲取文件對應的流對象 InputStream inputStream = ClassLoader.getSystemResourceAsStream(configFilePath); // 處理流對象 handleStream(inputStream); // 處理Document對象 // 處理Node對象,將數據封裝到BeanDefinition對象中 } /* * 處理讀取的配置文件流 */ private void handleStream(InputStream inputStream) { try { //構建解析器對象 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); //將流解析爲Document對象 Document document = builder.parse(inputStream); //處理Document對象 handleDocument(document); } catch (Exception e) { e.printStackTrace(); } } /* * 處理Document對象 */ private void handleDocument(Document document) { // 獲取全部bean元素 NodeList nodeList = document.getElementsByTagName("bean"); // 迭代全部的bean元素,先獲取一個Node節點,將節點轉成BeanDefinition對象以後存入beanMap(原料) for (int i = 0; i < nodeList.getLength(); i++) { // 獲取第i個元素 Node node = nodeList.item(i); // 處理Node對象,並將返回的BeanDefinition對象存入beanMap BeanDefinition beanDefinition = handleNode(node); beanMap.put(beanDefinition.getId(), beanDefinition); } } /* * 處理Node,轉成BeanDefinition */ private BeanDefinition handleNode(Node node) { //構建BeanDefinition對象,存儲Node信息 BeanDefinition beanDefinition=new BeanDefinition(); //獲取節點相關屬性值 NamedNodeMap nodeMap = node.getAttributes(); String id = nodeMap.getNamedItem("id").getNodeValue(); String claString = nodeMap.getNamedItem("class").getNodeValue(); //將節點值存入BeanDefinition對象 beanDefinition.setId(id); beanDefinition.setClaString(claString); return beanDefinition; } /* * 建立對象 */ private Object createInstance(Class<?> class1) { try { Constructor<?> constructor = class1.getDeclaredConstructor(); return constructor.newInstance(); } catch (Exception e) { e.printStackTrace(); return null; } } public <T>T getBean(String id,Class<T> class1){ //對傳入的id和class1進行校驗 if (!beanMap.containsKey(id)) { throw new RuntimeException("沒有該id的bean對象"); } BeanDefinition definition = beanMap.get(id); if (!class1.getName().equals(definition.getClaString())) {//User.class的getName與definition對象中獲取的class屬性是否相同 throw new RuntimeException("沒有對應類的bean對象"); } //從instanceMap中獲取對象 Object object = instanceMap.get(id); if (object==null) { object=createInstance(class1); instanceMap.put(id, object); } return (T) object; } }
下面作一個測試ui
package com.spring; public class Test { public static void main(String[] args) { DefaultBeanFactory defaultBeanFactory=new DefaultBeanFactory("spring-config.xml"); User bean = defaultBeanFactory.getBean("user", User.class); User bean2 = defaultBeanFactory.getBean("user", User.class); System.out.println(bean); //com.spring.User@4e25154f System.out.println(bean==bean2); //true } }