天天看点

理解 Spring 应用上下文生命周期

作者:阿里开发者
Spring 应用上下文(ApplicationContext),是 Spring 应用的核心接口,也是我们常说的 Spring 容器,除了扩展了基础容器 BeanFactory 还提供了更多企业级的特性,如资源管理、事件发布、国际化等。

前言

Spring 应用上下文(ApplicationContext),是 Spring 应用的核心接口,也是我们常说的 Spring 容器,除了扩展了基础容器 BeanFactory 还提供了更多企业级的特性,如资源管理、事件发布、国际化等。理解 Spring 应用上下文的生命周期也就理解了 Spring 内部的运行的核心逻辑,生命周期中同时提供了很多扩展点,跟随文章,我们一探究竟。

应用上下文的生命周期

Spring ApplicationContext 具有层次性的设计,生命周期的管理主要在 AbstractApplicationContext,类图如下。

理解 Spring 应用上下文生命周期

生命周期的相关方法均由实现的接口提供,各生命周期阶段并非完整地从上而下执行,部分阶段是可选的,具体如下。

刷新阶段:org.springframework.context.ConfigurableApplicationContext#refresh

启动阶段:org.springframework.context.Lifecycle#start

停止阶段:org.springframework.context.Lifecycle#stop

关闭阶段:org.springframework.context.ConfigurableApplicationContext#close

刷新阶段

刷新阶段是 Spring 应用上下文生命周期的主要阶段,刷新阶段完成后 Spring 中的非延迟单例 bean 即实例化完成,依赖注入也完成,可以正常调用 bean 的方法。有关 bean 的生命周期可参考我前面的文章《Java 面试必备的 Spring Bean 生命周期总结》。

刷新阶段对应的 AbstractApplicationContext#refresh 方法源码如下。

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 应用上下文刷新准备
            prepareRefresh();

            // BeanFactory 创建
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // BeanFactory 准备
            prepareBeanFactory(beanFactory);

            try {
                // BeanFactory 后处理,由子类扩展
                postProcessBeanFactory(beanFactory);

                // BeanFactory 后处理,调用 BeanFactoryPostProcessor 方法
                invokeBeanFactoryPostProcessors(beanFactory);

                // 注册 BeanPostProcessor
                registerBeanPostProcessors(beanFactory);

                // 初始化 MessageSource
                initMessageSource();

                // 初始化事件广播器
                initApplicationEventMulticaster();

                // 上下文刷新
                onRefresh();

                // 注册事件监听器
                registerListeners();

                // 初始化完成,实例化所有非延迟初始化的单例 bean
                finishBeanFactoryInitialization(beanFactory);

                // 刷新完成
                finishRefresh();
            } catch (BeansException ex) {
                destroyBeans();
                cancelRefresh(ex);
                throw ex;
            } finally {
                resetCommonCaches();
            }
        }
    }           

下面对应用上下文的刷新阶段进行细化分析。

上下文刷新准备阶段

上下文刷新准备阶段的工作如下:

设置启动时间及状态标识。

初始化 PropertySource。

由子类进行扩展,web 环境下将初始化名称为 servletContextInitParams 和 servletConfigInitParams 的 PropertySource 。

关于 PropertySource 可参见我前面的文章《Spring 中的 Environment 、Profile 与 PropertySource》。

校验 Environment 中必须的属性。

初始化事件监听器集合。

关于 Spring 事件可参见我前面的文章《Spring 事件处理机制详解,带你吃透 Spring 事件》 。

初始化早期事件集合。

对应的AbstractApplicationContext#prepareRefresh方法源码如下。

protected void prepareRefresh() {
        // 设置刷新事件及激活状态
        this.startupDate = System.currentTimeMillis();
        this.closed.set(false);
        this.active.set(true);
        
        ... 省略日志打印代码

        // 初始化 Environment 中的 PropertySource,该方法为空方法,由子类实现,如 web 环境下添加 ServletContext 初始化及 Servlet 配置的 PropertySource
        initPropertySources();

        // 校验 Environment 设置的必须的属性
        getEnvironment().validateRequiredProperties();

        if (this.earlyApplicationListeners == null) {
            // 首次 fresh,把刷新前添加的监听器添加到 earlyApplicationListeners
            this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
        } else {
            // 再次 fresh,把之前添加的监听器添加到 applicationListeners
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }

        // 初始化事件集合,事件广播器初始化完成后发布
        this.earlyApplicationEvents = new LinkedHashSet<>();
    }           

BeanFactory 创建阶段

BeanFactory 创建阶段的工作如下:

刷新 BeanFactory。

销毁并关闭 BeanFactory,如果已存在。

创建 BeanFactory。

设置 BeanFactory 的 ID。

设置 BeanFactory 是否允许 BeanDefinition 重复注册及循环引用。

关于循环引用,可参见我前面的文章《Spring 循环依赖处理》。

加载 BeanDefinition。

抽象方法,由子类进行实现。XML 和注解方式加载 BeanDefinition 的方式有所不同。

关于 BeanDefinition,可参见我前面的文章《掌握 Spring 必须知道的 BeanDefinition》 。

关联 BeanFactory 到应用上下文。

获取 BeanFactory。

相关的源码说明如下所示。

// AbstractApplicationContext#obtainFreshBeanFactory
  protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 先创建 BeanFactory,该方法为抽象方法,由子类进行实现
    refreshBeanFactory();
    // 再获取 BeanFactory
    return getBeanFactory();
  }

  // AbstractRefreshableApplicationContext#refreshBeanFactory
  @Override
  protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
      // 如果已经存在 BeanFactory,先销毁 bean ,然后关闭 BeanFactory
      destroyBeans();
      closeBeanFactory();
    }
    try {
      // 创建 BeanFactory
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      // 设置是否允许重复注册 BeanDefinition,是否允许循环引用
      customizeBeanFactory(beanFactory);
      // 加载 BeanDefinition,抽象方法,由子类进行实现
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
        this.beanFactory = beanFactory;
      }
    } catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
  }           

BeanFactory 准备阶段

BeanFactory 准备阶段的工作如下:

设置加载 bean class 的 ClassLoader。

设置解析 BeanDefinition 中字符串的表达式处理器。

添加 PropertyEditorRegistrar 的实现 ResourceEditorRegistrar。

添加 Aware 回调接口 BeanPostProcessor 的实现 ApplicationContextAwareProcessor。

支持的 Aware 回调接口包括 EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware。

忽略 Aware 回调接口作为依赖注入接口。

忽略的 Aware 回调接口和上面 ApplicationContextAwareProcessor 支持的 Aware 回调接口相对应,保持一致。

注册 ResolvableDependency 对象作为 bean。

包括 BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext。

添加 BeanPostProcessor 的实现 ApplicationListenerDetector。用于将 ApplicationListener 添加到 ApplicationContext。

如果 BeanFactory 中存在名称为 loadTimeWeaver 的 bean,

添加 BeanPostProcessor 的实现 LoadTimeWeaverAwareProcessor。

设置临时类加载器 ContextTypeMatchClassLoader。

注册单例 bean Environment、Java System Properties、OS 环境变量。

相关的源码说明如下所示:

// AbstractApplicationContext#prepareBeanFactory
    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 设置类加载器、表达式处理器;添加 ResourceEditorRegistrar
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // 配置 Aware 回调接口的处理器 ApplicationContextAwareProcessor,并且忽略依赖注入对应的 Aware 接口
        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);

        // 注册依赖注入时可解析的依赖
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        // 添加 ApplicationListenerDetector,用于添加事件监听器到应用上下文
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        // AOP 相关
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        // 注册默认的环境相关的单例 bean
        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());
        }
    }           

BeanFactory 后置处理阶段

BeanFactory 后置处理阶段的工作如下:

调用方法 postProcessBeanFactory。

该方法实现为空,由子类进行扩展。

如 web 环境下会设置 ServletContextAware、ServletConfigAware 回调处理,注册 web 环境下的 scope 及相关的 bean。

调用 BeanFactoryPostProcessor 中的后置处理方法。

如果临时 ClassLoader 不存在并且存在名称为 loadTimeWeaver 的 bean,

添加 BeanPostProcessor 的实现 LoadTimeWeaverAwareProcessor。

设置临时类加载器 ContextTypeMatchClassLoader。

相关的源码如下:

// AbstractRefreshableWebApplicationContext#postProcessBeanFactory
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 添加 web 环境下 aware 处理,忽略 aware 依赖注入接口
        beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
        beanFactory.ignoreDependencyInterface(ServletConfigAware.class);

        // 注册 web 环境下的 scope
        WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
        // 注册 web 环境下的 bean
        WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
    }
    
    // AbstractApplicationContext#invokeBeanFactoryPostProcessors
    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        // 调用 BeanFactoryPostProcessor 处理方法  
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

        // AOP 相关
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }           

BeanPostProcessor 注册阶段

BeanPostProcessor 注册阶段的工作主要是将 BeanPostProcessor 类型的 bean 添加到 BeanFactory 内部持有的 BeanPostProcessor 列表中。添加顺序如下:

实现 PriorityOrdered 接口的 BeanPostProcessor。

实现 Ordered 接口的 BeanPostProcessor。

普通的 BeanPostProcessor。

实现 MergedBeanDefinitionPostProcessor 接口的 BeanPostProcessor。

ApplicationListenerDetector 接口。

相关的源码如下:

// AbstractApplicationContext#registerBeanPostProcessors
    protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    }           

MessageSource 初始化阶段

MessageSource 初始化阶段用于保证 BeanFactory 中存在 MessageSource 类型的单例 bean。关于 MessageSource,可参见我前面的文章《Spring 国际化支持之 MessageSource》。

相关的源码如下:

protected void initMessageSource() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
            // 设置 messageSource 到当前应用上下文
            this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
            // 设置父 MessageSource
            if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
                HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
                if (hms.getParentMessageSource() == null) {
                    hms.setParentMessageSource(getInternalParentMessageSource());
                }
            }
        } else {
            // 设置 MessageSource 到当前应用上下文,通过调用父 MessageSource 实现其功能
            DelegatingMessageSource dms = new DelegatingMessageSource();
            dms.setParentMessageSource(getInternalParentMessageSource());
            this.messageSource = dms;
            beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
        }
    }           

事件广播器初始化阶段

事件广播器初始化阶段主要用来保证应用上下文中存在 ApplicationEventMulticaster。相关的源码如下:

protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
            // 存在名称为 applicationEventMulticaster 的 bean,设置到应用上下文
            this.applicationEventMulticaster =
                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
            }
        } else {
            // 不存在 bean,设置到当前应用上下文,并注册为 bean
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
            }
        }
    }           

上下文刷新阶段

上下文刷新阶段对应的方法为AbstractApplicationContext#onRefresh,该方法为空方法,由子类进行实现。

事件监听器注册阶段

事件监听器注册阶段的工作如下:

添加当前应用上下文关联的事件监听器到广播器。

添加 BeanFactory 中注册的事件监听器 bean 到广播器。

广播早期事件。

相关源代码如下:

protected void registerListeners() {
        // 添加应用上下文中的事件监听器到事件广播器中
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        // 添加 BeanFactory 中注册的事件监听器到事件广播器中
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }

        // 发布早期事件
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                // 广播当前应用上下文刷新前发布的事件
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }           

BeanFactory 初始化完成阶段

BeanFactory 初始化完成阶段的工作如下:

如果 BeanFactory 中存在注册的名称为 conversionService 的 ConversionService,将其设置到 BeanFactory 中。

如果 BeanFactory 中不存在 StringValueResolver,添加 StringValueResolver 到 BeanFactory。

点击查看原文,获取更多福利!

https://developer.aliyun.com/article/1086017?utm_content=g_1000365171

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。