1. 前言
在日常的开发过程,经常使用或碰到的设计模式有代理、工厂、单例、反射模式等等。下面就对工厂模式模拟spring的bean加载过程进行解析,如果对工厂模式不熟悉的,具体可以先去学习一下工厂模式的概念。在来阅读此篇博文,效果会比较好。
2. 知识储备
在介绍本文的之前,不了解或不知道如何解析XML的,请先去学习一下XML的解析。掌握目前主要的几种解析XML中的一种即可,以下博文说明了如何采用Dom4J解析XML文件的,接下去的例子也是常用Dom4J来解析XML。博文地址参考:http://www.cnblogs.com/hongwz/p/5514786.html;
3. 原理及目标
Spring
容器最基本的接口就是BeanFactory
。(ApplicationContext是BeanFactory的子接口,大部分javaEE用这个接口就够了,也称为Spring上下文)
BeanFactory接口包含如下方法:
- boolean containsBean(String name):判断Spring容器中是否有id为name的实例
- T getBean(…) :可有参可无参,获得Bean实例
- Class < ?> getType(String name)
本文的目标是模拟spring容器生产bean的全过程,因此工厂接口
、工厂实现类
都自己写。
3.1 工厂接口
public interface BeanFactory {
//我们只定义了一个方法,并没有像spring默认写的方法多
Object getBean(String id) throws ExecutionException;
}
3.2 工厂实现
/**
* BeanFactory实现类
*/
public class ClassPathXmlApplicationContext implements BeanFactory {
private Map<String, Object> map = new HashMap<String, Object>();
@SuppressWarnings("unchecked")
public ClassPathXmlApplicationContext(String fileName) throws DocumentException, InstantiationException, IllegalAccessException, ClassNotFoundException {
//加载配置文件
SAXReader reader = new SAXReader();
Document document = reader.read(ClassPathXmlApplicationContext.class.getClassLoader().getResourceAsStream(fileName));
//获取根节点
Element root = document.getRootElement();
//获取子节点
List<Element> childElements = root.elements();
for (Element element : childElements) {
map.put(element.attributeValue("id"), Class.forName(element.attributeValue("class")).newInstance());
}
}
@Override
public Object getBean(String id) throws ExecutionException {
return map.get(id);
}
}
3.3 模拟Spring中bean的配置
实例类
/**
* 汽车类.
*/
public class Car {
public void run() {
System.out.println("这是一辆汽车...");
}
}
/**
* 火车类.
*/
public class Train {
public void run() {
System.out.println("这是一辆火车....");
}
}
applicationContext.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="car" class="com.shine.spring.domain.Car">
</bean>
<bean id="train" class="com.shine.spring.domain.Train">
</bean>
</beans>
测试类
public class BeanFactoryTest {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, DocumentException, ExecutionException {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("com/shine/spring/applicationContext.xml");
Object obj = beanFactory.getBean("car");
Car car = (Car)obj;
car.run();
}
}
4. 小结
Spring容器就是一个工厂,通过自己实现Spring容器的工厂接口、实现类,能更深的理解Spring中的底层实现。(对工厂模式不熟的请参考上篇的工厂模式)。