Spring Ioc容器的设计java
在Spring Ioc容器的设计中,有两个主要的容器系列,一个是实现BeanFactory接口的简单容器系列,只实现了容器的最基本的功能;另外一个是ApplicationContext应用上下文,进行了不少扩展,它做为容器的高级形态存在。编程
Spring Ioc容器的设计:。。。。函数
BeanFactory容器的设计原理(以 实现类XmlBeanFactory为例):this
public class XmlBeanFactory extends DefaultListableBeanFactory { public XmlBeanFactory(Resource resource) throws BeansException { this(resource, null); } public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); reader = new XmlBeanDefinitionReader(this); reader.loadBeanDefinitions(resource); } private final XmlBeanDefinitionReader reader; }
在Spring中,其实是把DefaultListableBeanFactory做为一个默认的功能完整的Ioc容器来使用。XmlBeanFactory容器继承了DefaultListableBeanFactory又增长了一些新的功能。XmlBeanFactory是一个与XML相关的BeanFactory,是一个能够读取以XML文件方式定义的BeanDefinition(XML定义的信息)的Ioc容器。设计
BeanDefinition分为FileSystemResource(文件系统中的Bean定义的信息可使用FileSystemResource来进行抽象)、ClassPathResource(在类路径中的Bean定义信息可使用ClassPathResource来使用)等code
实现XML读取的功能实现:对这些XML形式的信息处理并非直接经过XmlBeanFactory直接完成。从上面XmlBeanFactory的代码中能够看出初始化了一个XmlBeanDefinitionReader对象,对XML形式的信息处理其实是由XmlBeanDefinitionReader(Reader对象)来完成的。xml
构造XmlBeanFactory这个Ioc容器时,须要指定BeanDefinition的信息来源,须要被封装成Spring中的Resource类给出。Resource是Spring用来封装I/O操做的类。BeanDefinition信息是以XML文件形式存在的,可使用像ClassPathResource res = new ClassPathResource("beans.xml");这样具体的ClassPathResource来构造须要的Resource,而后将Resource做为构造参数传递给XmlBeanFactory构造函数。这样,Ioc容器就能够方便地定位到须要的BeanDefinition信息来对Bean完成容器的初始化和依赖注入过程。对象
ApplicationContext容器的设计原理(FileSystemXmlApplicationContext为例):继承
ApplicationContext与FileSystemXmlApplicationContext关系图:接口
public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext { public FileSystemXmlApplicationContext() { } public FileSystemXmlApplicationContext(ApplicationContext parent) { super(parent); } public FileSystemXmlApplicationContext(String configLocation) throws BeansException { this(new String[] { configLocation }, true, null); } public transient FileSystemXmlApplicationContext(String configLocations[]) throws BeansException { this(configLocations, true, null); } public FileSystemXmlApplicationContext(String configLocations[], ApplicationContext parent) throws BeansException { this(configLocations, true, parent); } public FileSystemXmlApplicationContext(String configLocations[], boolean refresh) throws BeansException { this(configLocations, refresh, null); } //下文所说自身须要实现的第一个功能 public FileSystemXmlApplicationContext(String configLocations[], boolean refresh, ApplicationContext parent) throws BeansException { super(parent); setConfigLocations(configLocations); if(refresh) refresh(); } //下文所说自身须要实现的第二个功能 protected Resource getResourceByPath(String path) { if(path != null && path.startsWith("/")) path = path.substring(1); return new FileSystemResource(path); } }
在FileSystemXmlApplicationContext设计中,ApplicationContext应用上下文的功能已经在FileSystemXmlApplicationContext的基类AbstractXmlApplicationContext中实现了,在FileSystemXmlApplicationContext中,做为一个具体的应用上下文,只需实现和它自身相关的两个功能。
一个是:若是应用直接使用FileSystemXmlApplicationContext,须要实例化这个应用的上下文支持,同时启动IoC容器的refresh()过程。这个refresh()过程会牵涉IoC容器启动的一系列复杂操做,同时,对于不一样容器的实现这些操做相似,所以在基类中将它封装好,须要时调用。
另外一个:是与FileSystemXmlApplicationContext设计具体相关的功能,与怎样从文件系统中加载XML的Bean定义资源有关。不一样的应用上下文实现对应着不一样的读取BeanDefinition的方式,而FileSystemXmlApplicationContext经过这个过程,能够为在文件系统中读取以XML形式存在的BeanDefinition作准备。
IoC容器的初始化过程
Spring Ioc容器的初始化是由前面介绍的refresh()方法来启动的,这个方法标志着Ioc容器的正式启动。
包括三个步骤:BeanDefinition的Resource定位、载入、注册
编程的方式使用DefaultListableBeanFactory(XmlBeanFactory的基类)(IoC容器初始化的过程和以编程的方式相似,能够作参考):
//定义一个Resource来定位容器使用的BeanDefinition,这里使用的是ClassPathResource(类路径中找) ClassPathResource res = new ClassPathResource("beans.xml"); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); //这里的Resource不能由DefaultListableBeanFactory直接使用,Spring经过使用BeanDefinitionReader对这些信息进行处理 XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); reader.loadBeanDefinitions(res);
图2-1
在这里,咱们能够看到使用ApplicationContext相对直接使用DefaultListableBeanFactory的好处,由于在ApplicationContext中,Spring已经为咱们提供了一系列加载不一样Resource的读取器的实现,而DefaultListableBeanFactory只是一个纯粹的IoC容器,须要为它配置特定的读取器才能完成这些功能。可是使用DefaultListableBeanFactory这种更底层的容器,能提升定制IoC容器的灵活性
BeanDefinition的Resource定位(这个定位过程相似容器寻找数据的过程):
回到ApplicationContext上来,例如FileSystemXmlApplicationContext、ClassPathXmlApplicationContext以及XmlApplicationContext等。
FileSystemXmlApplicationContext的继承体系如上图2-2
FileSystemXmlApplicationContext经过继承AbstractApplicationContext具有了ResourceLoader读入以Resource定义的BeanDefinition的能力,由于AbstractApplicationContext的基类是DefaultResourceLoader,而DefaultResourceLoader实现了ResourceLoader接口
参照FileSystemXmlApplicationContext的代码清单,BeanDefinition资源定位(调用getResourceByPath)的过程,最初是由refresh来触发的,而这个refresh的调用是在FileSystemXmlApplicationContext构造函数中启动的。