Spring简单模拟Spring容器

续Spring之HelloWorld:http://huangminwen.iteye.com/admin/blogs/1040405

Spring容器启动后,首先读取spring.xml配置文件中的bean信息,然后再实例化该bean,所以我们就可以直接获取bean来使用了,而无需实例化,下面我们模拟一下Spring容器的工作原理,首先我们需要先读取spring.xml配置文件,然后再初始化bean标签页中的类,SimulateClassPathXMLApplicationContext说明了该过程:

package org.spring.junit;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

public class SimulateClassPathXMLApplicationContext {
	private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
	private Map<String, Object> sigletons = new HashMap<String, Object>();

	public SimulateClassPathXMLApplicationContext(String filename) {
		this.readXML(filename);
		this.instanceBeans(); 
	}
	
	/**
	 * 读取xml配置文件
	 * 
	 * @param filename
	 */
	private void readXML(String filename) {
		SAXReader saxReader = new SAXReader();
		Document document = null;

		try {
			URL xmlpath = this.getClass().getClassLoader()
					.getResource(filename);
			document = saxReader.read(xmlpath);

			Map<String, String> nsMap = new HashMap<String, String>();
			nsMap.put("ns", "http://www.springframework.org/schema/beans");// 加入命名空间

			XPath xsub = document.createXPath("//ns:beans/ns:bean");// 创建beans/bean查询路径
			xsub.setNamespaceURIs(nsMap);// 设置命名空间

			List<Element> beans = xsub.selectNodes(document);// 获取文档下所有bean节点

			// 将读取到的bean信息存入beanDefines中
			for (Element element : beans) {
				String id = element.attributeValue("id");// 获取id属性值
				String clazz = element.attributeValue("class"); // 获取class属性值
				BeanDefinition beanDefine = new BeanDefinition(id, clazz);
				beanDefines.add(beanDefine);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 完成bean的实例化
	 */
	private void instanceBeans() {
		for (BeanDefinition beanDefinition : beanDefines) {
			try {
				if (beanDefinition.getClassName() != null
						&& !"".equals(beanDefinition.getClassName().trim()))
					sigletons.put(beanDefinition.getId(),
							Class.forName(beanDefinition.getClassName())
									.newInstance());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 获取bean实例
	 * 
	 * @param beanName
	 * @return
	 */
	public Object getBean(String beanName) {
		return this.sigletons.get(beanName);
	}
}

其中BeanDefinition类如下:

package org.spring.junit;

/**
 * 用于存放spring.xml中bean标签的信息
 */
public class BeanDefinition {
	private String id; // spring.xml配置文件中bean节点的id属性
	private String className; // spring.xml配置文件中的bean节点的name属性

	public BeanDefinition(String id, String className) {
		this.id = id;
		this.className = className;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

}

控制台打印结果:Hello Spring World!

工程目录结构图

猜你喜欢

转载自huangminwen.iteye.com/blog/1874200