Spring IOC容器设计
(1)从接口BeanFactory到HierarchicalBeanFactory,再到ConfigurableBeanFactory,是一条主要的BeanFactory设计路径。在这条接口设计路径中,BeanFactory接口定义了基 本的IoC容器的规范。在这个接口定义中,包括了getBean()这样的IoC容器的基本方法 (通过这个方法可以从容器中取得Bean)。而HierarchicalBeanFactory接口在继承了 BeanFactory的基本接口之后,增加了getParentBeanFactory的接口功能,使 BeanFactory具备了双亲IoC容器的管理功能。在接下来的ConfigurableBeanFactory接 口中,主要定义了一些对BeanFactory的配置功能,比如通过setParentBeanFactoryO设 置双亲IoC容器,通过addBeanPostProcessorO配置Bean后置处理器,等等。通过这些 接口设计的叠加,定义了BeanFactory就是简单IoC容器的基本功能。关于BeanFactory 简单IoC容器的设计,我们会在后面的内容中详细介绍。
BeanFactory的方法如下:
ConfigurableBeanFactoy的方法如下:
configurableBeanfactory是HierarchicalBeanFactory的子类,提供了一些方法,用于配置和管理Bean的属性和行为。通过使用ConfigurableBeanFactory,开发人员可以对BeanFactory进行更细粒度的配置和管理。它提供了一些方法,用于设置ClassLoader(setBeanClassLoader)、属性解析器、类型转换器(setConversionService)等,以满足不同的应用需求。
HierrarchicaBeanFactory的方法如下:
HierarchicalBeanFactory是BeanFactory的子类,在此基础上增加了“双亲IOC管理”的功能,何为双亲管理?双亲IOC容器指的是在Spring框架中,存在多个层次的IOC容器,其中一个容器是另一个容器的父容器。在Spring中,当存在多个应用程序上下文时,可以通过将一个应用程序上下文设置为另一个应用程序上下文的父上下文来创建双亲IOC容器。
父子IOC容器之间的关系可以用来实现模块化和层次化的应用程序结构。子容器可以访问并继承父容器中定义的Bean,而父容器对子容器中的Bean一无所知。这种层次结构可以提供更好的隔离性和模块化,同时还允许容器之间共享一些公共的Bean定义。HierarchicalBeanFactory定义了一些方法,用于在层次结构中查找和获取Bean。如:getParentBeanFactory()用于获取父级BeanFactory。这允许在层次结构中向上查找Bean;containsLocalBean(String name)用于检查当前BeanFactory是否包含指定名称的Bean。它只在当前BeanFactory中查找,不会向上查找父级BeanFactory。
(2)第二条接口设计主线是,以ApplicationContext应用上下文接口为核心的接口设计,这里涉及的主要接口设计有,从BeanFactory到ListableBeanFactory,再到ApplicationContext,再到我们常用的WebApplicationContext或者ConfigurableApplicationContext接口。我们常用的应用上下文基本上都是 ConfigurableApplicationContext或者WebApplicationContext的实现。在这个接口体系中,ListableBeanFactory和HierarchicalBeanFactory两个接口,连接BeanFactory接口定义和ApplicationConext应用上下文的接口定义。在ListableBeanFactory接口中,细化了许多BeanFactory的接口功能,比如定义了getBeanDefinitionNames(接口方法,对于HierarchicalBeanFactory接口,我们在前文中已经提到过,对于ApplicationContext接口,它通过继承MessageSource、ResourceLoader、ApplicationEventPublisher接口,在BeanFactory简单IoC容器的基础上添加了许多对高级容器的特性的支持。
ListableBeanFactory的方法如下:
(3)这里涉及的是主要接口关系,而具体的loC容器都是在这个接口体系下实现的,比如DefaultListableBeanFactory,这个基本IoC容器的实现就是实现了ConfigurableBeanFactory,从而成为一个简单IoC容器的实现。像其他IoC 容器,比如XmlBeanFactory都是在DefaultListableBeanFactory的基础上做扩展,同样地,ApplicationContext的实现也是如此.
(4)这个接口系统是以BeanFactory和ApplicationContext为核心的。而BeanFactory又是IoC容器的最基本接口在ApplicationContext的设计中,一方面,可以看到它继承了BeanFactory接口体系中的ListableBeanFactory、AutowireCapableBeanFactory、HierarcbicalBeanFactory等BeanFactory的接口,具备了BeanFactoryIoC容器的基本功能,另一方面,通过继承MessageSource、ResourceLoader、ApplicationEventPublisher这些接门,BeanFactory为ApplicationContext赋予了更高级的IoC容器特性。对于ApplicationContext而言,为了在Web环境中使用它,还设计了WebApplicationContext接口。
WebApplicationContext的功能如下:
1. BeanFactory的应用场景
BeanFactory提供的是最基本的 loC容器的功能,关于这些功能定义,我们可以在接口BeanFactory中看到。BeanFactory接口定义了IoC容器最基本的形式,并且提供了IoC容器所应该遵守的最基本的服务契约,同时,这也是我们使用IoC容器所应遵守的最底层和最基本的编程规范,这些接口定义勾画出了loC的基本轮廓。
2. BeanFactory容器的设计原理
BeanFactory接口提供了使用IoC容器的规范。在这个基础上,Spring还提供了符合这个IoC容器接口的一系列容器的实现供开发人员使用。我们以DefaultListableBeanFactory的实现为例来说明简单loC容器的设计原理。
可以看到,作为一个简单loC容器系列最底层实现的DefaultListableBeanFactory,与我们在Spring应用中用到的那些上下文相比,有一个非常明显的特点:它只提供最基本的loC容器的功能。理解这一点有助于我们理解ApplicationContext与基本的BeanFactory之间的区别和联系。我们可以认为直接的BeanFactory实现是IoC容器的基本形式,而各种ApplicationContext的实现是IoC容器的高级表现形式。关于ApplicationContext的分析,以及t与BeanFactory相比的增强特性都会在下面进行详细的分析。
3. ApplicationContext的应用场景
ApplicationContext是一个高级别形态意义的IoC容器。
ApplicationContext的类继承关系如下:
ApplicationContext在BeanFactory的基础上添加的附加功能,这些功能为ApplicaionContext提供如下BeanFactory不具备的新特性。
(1)支持不同的信息源。我们看到ApplicationContext扩展了MessageSource接口,这些信息源的扩展功能可以支持国际化的实现,为开发多语言版本的应用提供服务。 (2)访问资源。这一特性体现在对ResourceLoader和Resource的支持上,这样我们可以从不同地方得到Bean定义资源。这种抽象使用户程序可以灵活地定义Bean定文信息,尤其是从不同的I/O途径得到Bean定义信息。这在接口关系上看不出来,不过一般来说,具体ApplicationContext都是继承了DefaultResourceLoader的子类。因为DefaultResourceLoader是AbstractApplicationContext的基类,关于Resource在IoC容器中的使用,后面会有详细的讲解。 (3)支持应用事件。继承了接口ApplicationEventPublisher,从而在上下文中引入了事件机制。这些事件和Bean的生命周期的结合为Bean的管理提供了便利。 (4)在ApplicationContext中提供的附加服务。这些服务使得基本IoC容器的功能更丰富。因为具备了这些丰富的附加功能,使得ApplicationContext与简单的BeanFactory相比,对它的使用是一种面向框架的使用风格,所以一般建议在开发应用时使用ApplicationContext作为IoC容器的基本形式。
ApplicationContext容器的设计原理
ApplicationContext容器的设计原理在ApplicationContext容器中,我们以常用的FileSystemXmlApplicationContext的实现为例来说明ApplicationContext容器的设计原理。
在FileSystemXmlApplicationContext的设计中,ApplicationContext的主要功能已经在FileSystemXmlApplicationContext的基类AbstractXmlApplicationContext中实现了。
FileSystemXmlApplicationContext作为具体的上下文,主要实现两个功能: (1)ApplicationContext的实例化 refresh()进行初始化的具体操作,后续进行详细分析。
public FileSystemXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
(2)如何从文件系统中加载XML的Bean定义资源
@Override
protected Resource getResourceByPath(String path) {
if (path.startsWith("/")) {
path = path.substring(1);
}
return new FileSystemResource(path);
}
用于读取BeanDefinition.