一、概述
说到BeanFactory,就必然要提起IOC,IOC全名Inversion of Control,翻译为控制反转或者依赖注入,它是一种程序设计思想。
当我们依赖于某个类或者服务时,最简单而又有效地方式就是直接通过代码(即set方法或者通过构造方法)将其依赖在一起,这都是需要我们去主动地获取依赖对象。
相对于主动获取依赖对象,我们更希望能够被动地获取,IOC就可以达到这个目的。IOC容器会主动地将你需要的对象注入到对象中。在大型程序中,这样做的好处在于:以前对象与对象之间需要通过代码来产生耦合关系,现在只需要通过配置文件来进行调整,而通过调整配置文件又可以简单而又轻松地将对象与对象之间进行解耦。
Spring的BeanFactory就是一个IOC容器,它属于Spring框架中的Core(核心)部分 ,Spring AOP、Spring MVC等都是基于Spring Core之上的。
spring的IOC容器能够帮我们自动new对象,对象交给spring管之后我们不用自己手动去new对象了。那么它的原理是什么呢?是怎么实现的呢?下面我来简单的模拟一下spring的机制,相信看完之后就会对spring的原理有一定的了解。
二、BeanFactory实现
spring使用BeanFactory来实例化、配置和管理对象,但是它只是一个接口,里面有一个getBean()方法。我们一般都不直接用BeanFactory,而是用它的实现类ApplicationContext,这个类会自动解析我们配置的applicationContext.xml,然后根据我们配置的bean来new对象,将new好的对象放进一个Map中,键就是我们bean的id,值就是new的对象。
2.1、XML方式实现
实现思路
1.使用简单工厂模式来处理bean容器。
2.解析xml文件,获取配置中的元素信息。
3.利用反射获实例化配置信息中的对象。
4.如果有对象注入,使用invoke()方法。
5.实例化的对象放入bean容器中,并提供getBean方法。
核心代码
**
* bean工厂
* 实例化配置文件中的bean,并提供bean实例的获取方法
* @author tianyong
*/
public class MyBeanFacrotyImplimplements MyBeanFactory{
//beans中存放所有的bean实例,beans即为Ioc容器
private static Mapbeans =new HashMap();
/**
* 重写MyBeanFacrotyImpl的构造函数,实例化配置文件中的所有bean,并将其存到beans中
* @param configLocation
*/
public MyBeanFacrotyImpl(String configLocation){
try {
// 使用jdom的SAXBuilder读取xml文件
SAXBuilder sb =new SAXBuilder();
// 加载xml文档进内存
Document doc = sb.build(this.getClass().getClassLoader()
.getResourceAsStream(configLocation));
// 获取根节点--也就是beans
Element root = doc.getRootElement();
// 获取根节点的孩子节点--也就是bean
@SuppressWarnings("unchecked")
List childList = root.getChildren("bean");
// 循环取出每一个bean节点以及他们的id和class属性,利用反射创建一个对象
for (int i =0; i < childList.size(); i++) {
Element child = (Element) childList.get(i);
// 获取id属性
String id = child.getAttributeValue("id");
// 获取class属性
String clazz = child.getAttributeValue("class");
// 通过反射加载类,实例化bean对象
Object obj = Class.forName(clazz).newInstance();
// 将实例化的对象放入IOC容器(map)中
beans.put(id, obj);
}
}catch (Exception e) {
System.out.println("实例化bean出错");
e.printStackTrace();
}
}
/*
* 返回beans中的beanId的实例
* @see beanFactory.MyBeanFactory#getBean(java.lang.String)
*/
@Override
public Object getBean(String beanId){
return beans.get(beanId);
}
}
2.2、Java方式实现
1、定义bean对象,对应Spring中的< bean >标签;
2、创建BeanFactory,根据 BeanFactory 来获取实例对象;
bean定义对象:
public class BeanDefined {
private String beanId;
private String classPath;
//getter,setter方法
}
创建beanFactory:
public class BeanFactory {
private List<BeanDefined> beanDefinedList;
public List<BeanDefined> getBeanDefinedList() {
return beanDefinedList;
}
public void setBeanDefinedList(List<BeanDefined> beanDefinedList) {
this.beanDefinedList = beanDefinedList;
}
/**
* 通过反射实例化对象
* @param beanId
* @return
* @throws Exception
*/
public Object getBean(String beanId) throws Exception {
Object instance = null;
for (BeanDefined bean : beanDefinedList){
if (beanId.equals(bean.getBeanId())){
String classPath = bean.getClassPath();
instance = Class.forName(classPath).newInstance();
return instance;
}
}
return instance;
}
}
其中最主要的是getBean() 方法,利用反射机制,获取到对象,然后调用 newInstance() 默认的构造方法进行实例化,最后返回一个实例化好的对象,Spring 就是利用类似这样反射工厂的方式进行对象的实例化的。
这里主要分三步:
1、注册bean,相当于在 Spring 配置文件中添加 < bean > 标签;
2、将注册好的 bean 添加到 BeanFactory 中,使 bean 能够被 BeanFactory 管理,就如 Spring 中 bean 添加到 Spring 容器中一样;
3、通过 BeanFactory 来进行对象的实例化。
通过简单的三步,一个类的实例化就完成了,这只是一个最简单的BeanFactory。
后续待更新。。。。。
网友评论