Spring源码解析-ioc容器的设计

Spring源码解析-ioc容器的设计

1 IoC容器系列的设计:BeanFactory和ApplicatioContext

  在Spring容器中,主要分为两个主要的容器系列,一个是实现BeanFactory接口的简单容器系列,这系列容器只实现了容器的最基本的功能;

另一个是ApplicationContext应用上下文,它作为容器的高级形态而存在。

  应用上下文在简单容器的基础上,增加了许多面向框架的特性,同时对应用环境作了许多适配。这两个容器系列,就基本满足用户对IoC容器使用的大部分需求了。

1.1 Spring的IoC容器系列

  我们通常说的IoC容器,实际上代表着一系列功能各异的容器产品,是指容器的功能有大有小,有各自的特点。

  在IoC容器的接口定义和实现的基础之上,Spring通过BeanDefinition来管理基于Spring的应用中的各种对象以及它们之间的相互依赖关系。BeanDefinition抽象了我们对Bean的定义,是让容器起作用的主要数据类型。

1.2 Spring IoC容器的设计

  IoC容器的接口设计图:

 

 

 

 

  1.第一条接口设计主线

    从BeanFactory到HierarchicalBeanFactory,再到ConfigurableBeanFactory,是一条主要的BeanFactory的BeanFactory设计路径。在这条设计路径中,BeanFactory定义了基本IoC容器的规范。在这个接口定义中,包括了像getBean()这样的IoC容器的基本方法。而HierarchicalBeanFactory接口在继承了BeanFactory基本接口之后,增加了getParentBeanFactory()的接口功能,使BeanFactory具备了双亲IoC容器的配置功能。而在接下来的ConfigurableBeanFactory接口中,定义了一些对BeanFactory的配置功能,比如通过setParentBeanFactory()设置双亲IoC容器,通过addBeanPostProcessor()配置Bena后置处理器等等。通过这些接口设计的叠加,定义了BeanFactory就是简单IoC容器 的基本功能。

  2.第二条接口设计主线

    以ApplicationContext应用上下文接口为核心的接口设计,这里涉及到设计到的接口主要有,从BeanFactory到ListableBeanFactory,再到ApplicationContext,再到我们常见的WebApplicationContext或者ConfigurableApplicationContext接口。在这个接口体系中,ListableBeanFactory和HierarchicalBeanFactory两个接口,连接BeanFactory接口定义和ApplicationContext应用上下文的接口定义。在ListableBeanFactory接口中,细化了许多BeanFactory的接口功能,比如定义了getBeanDefinitionNames()接口方法;对于ApplicationContext接口,它通过继承MessageSource、ResourceLoader、ApplicationEventPublisher接口,在BeanFactory简单容器中添加了许多对高级容器的特性支持。

 

  这里设计的是主要的接口关系,而具体的IoC容器都是在这个接口体系下实现的,比如DefaultListableBeanFactory,这个基本IoC容器就是实现了ConfigurableBeanFactory,从而成为一个精简的IoC容器的实现。像其他IoC容器,比如XmlBeanFactory,都是在DefaultListableBeanFactory的基础上做扩展,同样的,ApplicationContext的实现也是如此。

  这个接口系统是以BeanFactory和ApplicationContext为核心的。而BeanFactory又是IoC容器的最基本接口,在ApplicationContext的设计中,一方面可以看到它继承了BeanFactory接口体系中的ListableBeanFactory、AutowireCapableBeanFactory、HierarchicalBeanFactory等BeanFactory的接口,具备了BeanFactory IoC容器的基本功能;另一方面通过继承MseeageSource、ResourceLoader、ApplicationEventPublisher这些接口,具备了更高级的IoC容器特性。对于ApplicationContext而言,为了在Web环境下使用它,还设计了WebApplicationContext接口,这个接口通过继承ThemeSource接口来扩充。

 

2 BeanFactory容器的设计原理

 BeanFactory接口提供了使用IoC容器的规范。在这个基础上,Spring还提供了符合这个IoC容器接口的一系列的实现供开发人员使用。以XmlBeanFactory的实现为例来说明简单IoC容器的设计原理。如图:

  

 

 

  在Spring中,实际上是把DefaultListableBeanFactory作为一个默认的功能完整的IoC容器来使用的。XmlBeanFactory在继承了DefaultListableBeanFactory容器功能的同时,增加了新的功能,很容易从它的名字上猜到这是一个与XML相关的BeanFactory,也就是可以说它是一个可以读取以XML文件方式定义的BeanDefinition的IoC容器。

  对这些XML文件定义信息化的处理并不是由XmlBeanFactory直接完成的。在XmlBeanFactory中,初始化了一个XmlBeanDefinitionReader对象,有了这个Reader对象,那些以XML方式定义的BeanDefinition就有了处理的地方。

 

XmlBeanFactory的实现:

public class XmlBeanFactory extends DefaultListableBeanFactory {


  //拥有一个XmlBeanDefinitionReader对象解析BeanDefinition
  //将自己传给Reader对象,在Reader解析完BeanDefinition后通过一个回调配置给BeanFactory
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);   //传入一个Resource定位资源 public XmlBeanFactory(Resource resource) throws BeansException { this(resource, null); } public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader.loadBeanDefinitions(resource); } }

 

   参考XmlBeanFactory的实现,我们以编程的方式使用DefaultListableBeanFactory。从中我们可以看到IoC容器使用的一些基本过程。尽管我们在应用中使用IoC容器时很少用到这样的原始方式,但是了解这个基本过程对我们很有帮助。因为编程式使用容器的过程很清楚的揭示了在IoC容器实现中的那些关键的类,比如Resource、DefaultListableBeanFactory和BeanDefinitionReader之间的相互关系,例如是如何把IoC容器的功能解耦的,又是如何结合在一起为IoC容器工作的。

 

 编程式使用IoC容器:

    ClassPathResource res = new ClassPathResource("beans.xml");
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
    reader.loadBeanDefinitions(res);

 

   这样,我们就可以使用factory对象来使用DefaultListableBeanFactory这个IoC容器了。梳理一下,大概分为一下几个步骤:

  1.创建IoC配置文件的抽象资源。

  2.创建一个BeanFactory,这里使用的是DefaultListableBeanFactory。

  3.创建一个载入BeanDefinition的读取器,通过一个回调配置给BeanFactory。

  4.从定义好的资源位置读取配置信息,具体的解析成BeanDefinitions的过程由XmlBeanDefinitionReader来完成,然后配置给BeanFactory。完成整个载入和注册Bean定义后,需要的IoC容器就建立起来了。这时候就可以直接使用IoC容器了。

 

 

 

 

XmlBeanDefinitionReader
posted @ 2019-12-12 14:43  张天赐的博客  阅读(258)  评论(0编辑  收藏  举报