Handwritten springioc (read configuration information of bean)

Keywords: Spring xml Java Attribute

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

	}

}

Posted by vaaaska on Fri, 22 Nov 2019 08:45:57 -0800