文章目录
  1. 1. 前言
  2. 2. spring的两种容器
    1. 2.1. BeanFactory
      1. 2.1.1. AbstractBeanFactory
      2. 2.1.2. AbstractAutowireCapableBeanFactory
      3. 2.1.3. DefaultListableBeanFactory
    2. 2.2. ApplicationContext
      1. 2.2.1. AbstractApplicationContext
  3. 3. 参考文献

前言

有时候去面试总会碰到问IoC原理的,但是很少看到问IoC分为哪几类,IoC与DI有什么区别,其实比较反感这种概念性的问题。04年的时候MartinFowler已经把这些东西解释了一遍,感兴趣的就到这里,在这篇博客的参考文献发现80年代国外的叫兽就在论文里面提到了这些东西了,只是MartinFowler归纳总结出了个概念。既然写出来了,还是说说自己的理解。IoC翻译为控制反转,就是对bean的控制反转了,电影中有剧情反转、体育比赛有比赛反转等等,说得广泛点这些都可以看做是IoC,而java的实现就是跟bean相关的事情都不用自己去做了,都交给spring管理(有点像软件中的外包吧)。从下图也可以看出这几者的关系了:


此图出自spring的作者Rod Johnson的《Expert One-on-One J2EE Development without EJB》一书。在spring内部中还是有使用了Dependency Lookup(依赖查找)方式的,如BeanFactoryAware、ApplicationContextAware,这些只是针对比较特殊处理,spring大部分还是使用DI方式。由于此书2004年就出版了,当时的JDK版本还没有注解,所以后来spring的版本DI的方式还有通过注解注入(包含field inject)。

spring的两种容器

分析源码之前,把API转换成类图,这些容器之间的关系其实就比较清晰了。spring的IoC容器主要分为两类,一个是BeanFactory,一个是ApplicationContext,如下图所示(基于4.2.3分支):

BeanFactory

BeanFactory作为最顶层的工厂,只提供了获取bean最基本的操作,其他操作又抽象出了4个工厂:
HierarchicalBeanFactory:设置bean的一种层级关系,可以获取父类的BeanFactory(如果在当前容器中没有找到还可以到父类容器中去找bean)。
ListableBeanFactory:可以列举所有的bean的名字,在内部解析的时候,经常用到,但只会涉及到当前容器的bean,不会像HierarchicalBeanFactory去找父类BeanFactory的bean。
AutowireCapableBeanFactory:创建bean的工厂,bean的依赖实现也是由此工厂处理。
ConfigurableBeanFactory:一般与BeanFactory、ListableBeanFactory一起使用,设置一些初始化配置操作,包括bean是singleton还是prototype, setParentBeanFactory,setConversionService,addPropertyEditorRegistrar,registerCustomEditor,addBeanPostProcessor等等。

AbstractBeanFactory

BeanFactory的抽象实现类,实现了bean的判断以及获取bean的入口。

AbstractAutowireCapableBeanFactory

处理bean的实例化操作,也包括处理前、处理后一些操作,在后面分析代理bean初始化再详细介绍。

DefaultListableBeanFactory

DefaultListableBeanFactory作为BeanFactory的具体实现类,是整个IoC容器最核心的一个类,只要涉及到容器,就离不开DefaultListableBeanFactory,该类实现了注册bean、缓存bean names(解析bean的时候用到),具体的的依赖关系参考下图:

ApplicationContext

相比BeanFactory,ApplicationContext继承了更多的接口,功能更强大,

  1. bean具有层级关系(父子关系)
  2. 可以触发监听事件
  3. 实现了ResoureLoader可以加载配置文件
  4. 默认注册PropertyEditors,由BeanWrapperImpl实现属性类型转换
  5. 内部实现了对BeanPostProcessor内置对象的处理
    所以实际运用中,一般都使用的ApplicationContext类型的IoC容器

AbstractApplicationContext

与AbstractBeanFactory一样,只要继承了AbstractApplicationContext,这个容器获取bean的入口就在这个抽象类中,可以参考refresh方法:

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);

            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);

            // Initialize message source for this context.
            initMessageSource();

            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            onRefresh();

            // Check for listener beans and register them.
            registerListeners();

            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            finishRefresh();
        }

        catch (BeansException ex) {
            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        }
    }
}

这个方法包含了初始化bean、实例化bean之前的一些操作、初始化国际化资源文件、注册各种监听器等等, AbstractApplicationContext内部存储bean其实都是由DefaultListableBeanFactory完成,后面bean分析的时候详细说明。

如果说得再细一点还可以把WebApplicationContext归为一类容器,但作为ApplicationContext的子类,里面的实现几乎没什么区别,只是WebApplicationContext里面多了对servlet相关类的处理,所以分为两大类就可以了。

总结
spring的IoC容器是整个框架最核心的部分,只要把这部分弄明白了,其他模块也就迎刃而解了,参考下图(来自spring官方文档):

参考文献

《Expert One-on-One J2EE Design and Development》
《Expert One-on-One J2EE Development without EJB》
《Professional Java Development with the spring framework》

文章目录
  1. 1. 前言
  2. 2. spring的两种容器
    1. 2.1. BeanFactory
      1. 2.1.1. AbstractBeanFactory
      2. 2.1.2. AbstractAutowireCapableBeanFactory
      3. 2.1.3. DefaultListableBeanFactory
    2. 2.2. ApplicationContext
      1. 2.2.1. AbstractApplicationContext
  3. 3. 参考文献