Spring IOC ApplicationContext 源码分析

作为Spring提供的较之 BeanFactory 更为先进的IoC容器实现, ApplicationContext 除了拥有BeanFactory 支持的所有功能之外,还进一步扩展了基本容器的功能,包括 BeanFactoryPostProcessor 、 BeanPostProcessor 以及其他特殊类型bean的自动识别、容器启动后bean实例的自动初始化、国际化的信息支持、容器内事件发布等。

ApplicationContext 继承结构

image

ApplicationContext 的继承机构可以看到, ApplicationContext 继承了BeanFactory,也就是说,ApplicationContext 拥有BeanFactory的全部功能,ApplicationContext 是通过将容器的功能委派给DefaultListableBeanFactory来实现。除了继承BeanFactory,还有ResourceLoaderEnvironmentCapableApplicationEventPublisherMessageSource等接口,也就说明ApplicationContext 除了容器的功能外,还囊括了资源的处理、环境、事件发布、国际化等。

ApplicationContext 源码

创建一个常用的ApplicationContext

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");

ApplicationContext 初始化

ClassPathXmlApplicationContext的构造函数在设置完配置文件的位置后,紧接着调用refresh()方法。refresh方法是加载或刷新配置的信息,同时加载容器的单例。

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 为刷新准备这个context。
        prepareRefresh();

        // 告诉子类刷新内部bean工厂。
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 准备好bean工厂,以便在此context中使用。
        prepareBeanFactory(beanFactory);

        try {
            // 允许在context子类中对BeanFactory进行post-processing。
            postProcessBeanFactory(beanFactory);

            // 调用在context中注册为bean的工厂处理器(BeanFactoryPostProcessor)。
            invokeBeanFactoryPostProcessors(beanFactory);

            // 注册拦截bean创建的BeanProcessor。
            registerBeanPostProcessors(beanFactory);

            // 为context初始化消息源。
            initMessageSource();

            // 为context初始化事件多播。
            initApplicationEventMulticaster();

            // 初始化子类context中的其他特殊bean。
            onRefresh();

            // 检查listener类型的bean并注册它们。
            registerListeners();

            // 实例化所有剩余的(non-lazy-init)单例。
            finishBeanFactoryInitialization(beanFactory);

            // 最后一步:发布相应的事件。
            finishRefresh();
        }

        catch (BeansException ex) {
            ...
        }

        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

obtainFreshBeanFactory

obtainFreshBeanFactory()方法核心是内部调用refreshBeanFactory()方法并将容器内部的ConfigurableListableBeanFactory返回,从这也看到了ApplicationContext和BeanFactory的关系:ApplicationContext内部包含一个BeanFactory,ApplicationContext所有关于BeanFactory的功能将委派给此BeanFactory处理。

AbstractRefreshableApplicationContext#refreshBeanFactory源码:

protected final void refreshBeanFactory() throws BeansException {
   // 清理之前的BeanFactory
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      // createBeanFactory方法直接新建一个DefaultListableBeanFactory,也就是说内部使用的是DefaultListableBeanFactory实例
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      // 自定义此上下文使用的内部bean工厂
      customizeBeanFactory(beanFactory);
      // 将BeanDefinition加载到给定的bean工厂中,通常通过委托给一个或多个BeanDefinitionReader来实现
      // 子类实现的方法,此处调用的是AbstractXmlApplicationContext的方法
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException(...);
   }
}

也就是说这一步是构建ApplicationContext内部的BeanFactory,以及根据配置将BeanDefinition加载到BeanFactory中。

prepareBeanFactory

配置工厂的标准上下文特征,比如上下文的类加载器和后处理器。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   // 告诉内部bean工厂使用上下文的ClassLoader等。
   beanFactory.setBeanClassLoader(getClassLoader());
   // 使用Spring的表达式模块解析和计算Spring EL表达式
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
   // 属性编辑器
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

   // 这个在BeanFactory源码提到过的,扩展的Aware类型通过BeanPostProcessor来装配
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

   // 注册为可装配的依赖,而不是bean
   // MessageSource注册为bean
   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
   beanFactory.registerResolvableDependency(ResourceLoader.class, this);
   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
   beanFactory.registerResolvableDependency(ApplicationContext.class, this);

   // 注册early post-processor检测bean是否为applicationlistener。
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

   // 检测LoadTimeWeaver并为织入做准备
   if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      // 为类型匹配设置一个临时类加载器。
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }

   // 注册默认的环境beans
   if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
   }
}

postProcessBeanFactory

对BeanFactory预处理,ClassPathXmlApplicationContext未重写,WebXmlApplicationContext有重写,这里不展开。

invokeBeanFactoryPostProcessors

在任何应用程序bean的实例化之前,实例化并调用所有已注册的BeanFactoryPostProcessor bean,如果实现了PriorityOrdered或者Ordered接口这按顺序调用。

invokeBeanFactoryPostProcessors方法主要有两个调用:

  1. invokeBeanFactoryPostProcessors,调用BeanFactoryPostProcessors
  2. 检测LoadTimeWeaver,选择添加LoadTimeWeaverAwareProcessor,这一步在prepareBeanFactory已经做了

invokeBeanFactoryPostProcessors方法逻辑很简单

  1. 如果beanFactory是BeanDefinitionRegistry,则先处理BeanDefinitionRegistryPostProcessor
  2. 处理完ApplicationContext的BeanDefinitionRegistryPostProcessor后,实例化beanFactory的BeanDefinitionRegistryPostProcessor,按照PriorityOrdered -> Ordered -> non,顺序处理
  3. 按照BeanFactoryPostProcessor的方法,处理以上所有的,包括BeanDefinitionRegistryPostProcessor
  4. 还没完,第二步是取出beanFactory的BeanDefinitionRegistryPostProcessor,还有部分它的超类BeanFactoryPostProcessor未处理。按照2、3步处理未执行的BeanFactoryPostProcessor

registerBeanPostProcessors

在任何应用程序bean的实例化之前,按照顺序,实例化并调用所有已注册的BeanPostProcessor bean。

注册BeanPostProcessor和注册BeanFactoryPostProcessor类似,主要步骤

  1. 注册BeanPostProcessorChecker,当bean在BeanPostProcessor实例化过程中创建时,它记录一个信息消息
  2. 从beanFactory中取出按照BeanPostProcessor类型取出postProcessorNames,然后实例化,按照PriorityOrdered -> Ordered -> non的顺序依次注册到beanFactory
  3. 注册一个ApplicationListenerDetector用于检测实例化的bean是否为一个ApplicationListeners,是则注册listener

initMessageSource

MessageSource用于处理I18n,获取多语言信息。这一步,初始化MessageSource,如果在此context中没有定义任何值,则使用DelegatingMessageSource,实际是委派给父类的。

initApplicationEventMulticaster

初始化ApplicationEventMulticaster。如果上下文中没有定义,则使用SimpleApplicationEventMulticaster。

onRefresh

子类实现用于刷新context特殊的初始化工作,在实例化单例之前调用特定bean的初始化。

registerListeners

添加实现ApplicationListener接口,作为Listener的bean。不会影响其他Listener监听事件,添加是BeanName,而不是实例化后的Bean。Listener注册到ApplicationEventMulticaster。主要步骤:

  1. 注册ApplicationContext特定的Listener
  2. BeanFactory取出ApplicationListener的BeanNames,这里不初始化bean,而是注册Listener BeanName
  3. 广播earlyApplicationEvents

finishBeanFactoryInitialization

完成此上下文bean工厂的初始化,初始化所有剩余的单例bean。 与BeanFactory不同的是,ApplicationContext是eager模式,这一步主要是直接调用BeanFactory的初始化方法,完成所有non-lazy-init的bean的初始化

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   // 初始化Context的类型转换服务。
   if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
         beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
      beanFactory.setConversionService(
            beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
   }

   // 注册一个默认的ValueResolver,主要是为了解决注解的属性值,默认用Environment的propertyResolver
   if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
   }

   // 先初始化LoadTimeWeaverAware,用于运行时织入
   String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
   for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
   }

   // Stop using the temporary ClassLoader for type matching.
   beanFactory.setTempClassLoader(null);

   // Allow for caching all bean definition metadata, not expecting further changes.
   beanFactory.freezeConfiguration();

   // 实例化所有剩余的(non-lazy-init)单例。
   beanFactory.preInstantiateSingletons();
}

实例化所有的bean就是遍历所有的beanNames,然后挨个调用getBean(beanName),bean的初始化在BeanFactory 源码分析已经分析过了。这里还有一步是检测SmartInitializingSingleton

if (singletonInstance instanceof SmartInitializingSingleton) {
    final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
    smartSingleton.afterSingletonsInstantiated();
}

也就是说bean还可以实现SmartInitializingSingleton完成最后的init工作。

finishRefresh

完成此上下文的刷新,调用LifecycleProcessor的onRefresh()方法并发布ContextRefreshedEvent。

protected void finishRefresh() {
   // 清除context级资源缓存
   clearResourceCaches();

   // 为这个context初始化生命周期处理器,默认为DefaultLifecycleProcessor
   initLifecycleProcessor();

   // 刷新LifecycleProcessor,调用所有Lifecycle的start方法
   getLifecycleProcessor().onRefresh();

   // 发布事件
   publishEvent(new ContextRefreshedEvent(this));

   // 。。。好像是对JMX支持
   LiveBeansView.registerApplicationContext(this);
}

这个方法主要是对于有生命周期的bean,按照分组,调用其start方法。

ApplicationContext 使用

那么到此ApplicationContext初始化也就完成了,ApplicationContext可以作为BeanFactory、时间通知、资源管理使用

// beanFactory
UserService userService = context.getBean("userService", UserService.class);

// 事件
context.addApplicationListener(new WalkListener());
context.publishEvent(new WalkEvent(new User("Jerry")));
context.publishEvent(new WalkEvent(new User("Peter")));

// locale
context.getMessage("menu.edit", null, "Edit", Locale.US);
// ...

ApplicationContext的使用部分只需要调用内部的相应的组件即可。

总结

ApplicationContext 是Spring 的完整上下文,通过将各个功能模块委派给各个组件,完成了一个完成的环境,在ApplicationContext的构造函数中,完成各个组件的初始化,以备后期使用。

推荐阅读更多精彩内容

  • 1.1 Spring IoC容器和bean简介 本章介绍了Spring Framework实现的控制反转(IoC)...
    起名真是难阅读 1,681评论 0 8
  • 1.1 spring IoC容器和beans的简介 Spring 框架的最核心基础的功能是IoC(控制反转)容器,...
    simoscode阅读 4,664评论 2 21
  • 本来是准备看一看Spring源码的。然后在知乎上看到来一个帖子,说有一群**自己连Spring官方文档都没有完全读...
    此鱼不得水阅读 4,681评论 4 16
  • Spring容器高层视图 Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相...
    Theriseof阅读 1,884评论 0 24
  • Spring容器高层视图 Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相...
    LeiLv阅读 14,672评论 5 44