手寫SpringIOC(讀取bean的配置信息)

先大體說一下思路:以流的形式讀取一個配置文件,並將流中的信息解析並封裝到一個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

	}

}
相關文章
相關標籤/搜索