先大体说一下思路:以流的形式读取一个配置文件,并将流中的信息解析并封装到一个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 } }