Let's start with the idea: read a configuration file in the form of a stream, parse and encapsulate the information in the stream into a MAP1 < string, BeanDefinition >. BeanDefinition contains the attribute information of the configuration file, build a factory, store the built bean object into another MAP2 < string, Object > by reflection, so as to obtain the object directly from the factory map1 is the raw material of the factory (it needs to be obtained from the configuration file), and map2 is the factory product (there are bean objects created for us by the factory)
Define entity class first User.class
package com.spring; /** * Entity class * @author wan_ys * */ public class User { private Integer id; private String name; }
Order.class
package com.spring; /** * Entity class * @author wan_ys * */ public class Order { private Integer id; private String item; }
Write a simple configuration file here spring-config.xml
<?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>
Define a class to hold profile information (properties correspond to properties in the profile)
package com.spring; /** * Packaging configuration information of bean in configuration file * @author wan_ys * */ public class BeanDefinition { private String id; private String claString;//Corresponding to the class attribute in the configuration file 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 + "]"; } }
Imitating Spring to write a DefaultBeanFactory factory
package com.spring; /** * Bean factory * @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 { // Store bean information (raw material) Map<String, BeanDefinition> beanMap = new ConcurrentHashMap<String, BeanDefinition>(); // Store sample objects (products) Map<String, Object> instanceMap = new ConcurrentHashMap<String, Object>(); public DefaultBeanFactory(String configFilePath) { // Get the stream object corresponding to the file InputStream inputStream = ClassLoader.getSystemResourceAsStream(configFilePath); // Processing flow objects handleStream(inputStream); // Working with Document objects // Handle Node object and encapsulate data into BeanDefinition object } /* * Process read profile stream */ private void handleStream(InputStream inputStream) { try { //Building parser objects DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); //Resolve flow to Document object Document document = builder.parse(inputStream); //Working with Document objects handleDocument(document); } catch (Exception e) { e.printStackTrace(); } } /* * Working with Document objects */ private void handleDocument(Document document) { // Get all bean elements NodeList nodeList = document.getElementsByTagName("bean"); // Iterate over all bean elements, first obtain a Node node, convert the Node to a BeanDefinition object, and then store it in beanmap (raw material) for (int i = 0; i < nodeList.getLength(); i++) { // Get the i-th element Node node = nodeList.item(i); // Process the Node object and store the returned BeanDefinition object in beanMap BeanDefinition beanDefinition = handleNode(node); beanMap.put(beanDefinition.getId(), beanDefinition); } } /* * Handle Node, convert to BeanDefinition */ private BeanDefinition handleNode(Node node) { //Build BeanDefinition object to store Node information BeanDefinition beanDefinition=new BeanDefinition(); //Get node related property values NamedNodeMap nodeMap = node.getAttributes(); String id = nodeMap.getNamedItem("id").getNodeValue(); String claString = nodeMap.getNamedItem("class").getNodeValue(); //Store node values in the BeanDefinition object beanDefinition.setId(id); beanDefinition.setClaString(claString); return beanDefinition; } /* * create object */ 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){ //Verify the id and class1 passed in if (!beanMap.containsKey(id)) { throw new RuntimeException("No such thing. id Of bean object"); } BeanDefinition definition = beanMap.get(id); if (!class1.getName().equals(definition.getClaString())) {//Whether the getName of User.class is the same as the class attribute obtained in the definition object throw new RuntimeException("Without corresponding class bean object"); } //Get objects from instanceMap Object object = instanceMap.get(id); if (object==null) { object=createInstance(class1); instanceMap.put(id, object); } return (T) object; } }
Here's a test
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 } }