码农翻身

Spring Context初始化流程(源码分析)

- by MRyan, 2020-08-11


不管是XML配置的Context,还是Spring Boot的Context,还是Web服务中的Context,创建后都会调用AbstractApplicationContext类的refresh()方法。

定位到AbstractApplicationContext下的refresh()方法,开始分析。
整体流程如下:


    @Override
    public void refresh() throws BeansException, IllegalStateException {
        //1
        synchronized (this.startupShutdownMonitor) {
            //2
            prepareRefresh();
            //3
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            //4
            prepareBeanFactory(beanFactory);

            try {
                //5
                postProcessBeanFactory(beanFactory);

                //6
                invokeBeanFactoryPostProcessors(beanFactory);

                //7
                registerBeanPostProcessors(beanFactory);

                //8
                initMessageSource();

                //9
                initApplicationEventMulticaster();

                //10
                onRefresh();

                //11
                registerListeners();

                // 12
                finishBeanFactoryInitialization(beanFactory);

                // 13
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }


                destroyBeans();

                cancelRefresh(ex);

                throw ex;
            }

            finally {
                //14
                resetCommonCaches();
            }
        }
    }

分为14步,接下来我们一步一步来进行分析。

1.
synchronized (this.startupShutdownMonitor) 加锁,确保了同一时间startupShutdownMonitor的状态不发生改变。
2.
prepareRefresh() 为刷新做准备,进入方法查看:

/**
     *准备此上下文以进行刷新,设置其启动日期和活动标记以及执行属性源的任何初始化
     */
    protected void prepareRefresh() {
        // 设置开始时间
        this.startupDate = System.currentTimeMillis();
        //设置激活状态
        this.closed.set(false);
        this.active.set(true);

        if (logger.isDebugEnabled()) {
            if (logger.isTraceEnabled()) {
                logger.trace("Refreshing " + this);
            }
            else {
                logger.debug("Refreshing " + getDisplayName());
            }
        }
        //初始化Context环境占位符
        initPropertySources();

        // 动作根据子类的自求由子类执行,然后验证是否缺失必要的properties
        getEnvironment().validateRequiredProperties();

        // 存储预刷新的ApplicationListeners
        if (this.earlyApplicationListeners == null) {
            this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
        }
        else {
            // 将本地应用程序侦听器重置为预刷新状态。
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }

        //允许收集早期的ApplicationEvent 一旦多播器可用时就发布
        this.earlyApplicationEvents = new LinkedHashSet<>();
    }

3.
刷新并获得内部的 Bean Factory

4.
进入方法prepareBeanFactory()

/**
     * 配置工厂的标准上下文特征,例如上下文的ClassLoader和后处理器
     * @param beanFactory the BeanFactory to configure
     */
    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 告诉内部bean工厂使用上下文的类加载器等
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // 使用上下文回调配置Bean工厂
        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接口未在普通工厂中注册为可解析类型
        //MessageSource注册为Bean(并发现用于自动装配)
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        //注册早期的后处理器以将内部bean检测为ApplicationListeners。
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        //检测LoadTimeWeaver并准备编织(如果找到)
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            //设置一个临时的ClassLoader以进行类型匹配。
            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 进行准备工作,比如设置类加载器和后置处理器、配置不进行自动装配的类型、注册默认的环境 Bean。

5.
postProcessBeanFactory方法源码如下

/**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for registering special
     * BeanPostProcessors etc in certain ApplicationContext implementations.
     * @param beanFactory the bean factory used by the application context
     */
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    }

为 Context 的子类提供后置处理 BeanFactory 的扩展能力。如果子类想在 Bean 定义加载完成后,开始初始化上下文之前做一些特殊逻辑,可以复写这个方法。

6.
invokeBeanFactoryPostProcessors()方法源码如下:

    /**
     * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
     * respecting explicit order if given.
     * <p>Must be called before singleton instantiation.
     */
    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    //传入Bean工厂并获取容器中的Bean工厂后置处理器(注意这里Bean工厂后置处理器还没有初始化)
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

        // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
        // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

执行 Context 中注册的 Bean Factory 后缀处理器。这里有两种后置处理器,一种是可以注册 Bean 的后缀处理器,另一种是针对 BeanFactory 进行处理的后置处理器。执行的顺序是,先按优先级执行可注册 Bean 的处理器,在按优先级执行针对 BeanFactory的处理器。由 ConfigurationClassPostProcessor 触发、由ClassPathBeanDefinitionScanner 解析并注册到 BeanFactory。

7.
registerBeanPostProcessors方法源码如下

    /**
     * Instantiate and register all BeanPostProcessor beans,
     * respecting explicit order if given.
     * <p>Must be called before any instantiation of application beans.
     */
    protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    }

按优先级指定顺序在 BeanFactory 中注册 Bean的后缀处理器,Bean 后置处理器可以在 Bean 初始化前、后执行处理。

8.
initMessageSource方法源码如下:

    /**
     * 实例化消息源
     * 如果在此上下文中未定义父项,则使用父项
     */
    protected void initMessageSource() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
            this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
            // Make MessageSource aware of parent MessageSource.
            if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
                HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
                if (hms.getParentMessageSource() == null) {
                    // Only set parent context as parent MessageSource if no parent MessageSource
                    // registered already.
                    hms.setParentMessageSource(getInternalParentMessageSource());
                }
            }
            if (logger.isTraceEnabled()) {
                logger.trace("Using MessageSource [" + this.messageSource + "]");
            }
        }
        else {
            // Use empty MessageSource to be able to accept getMessage calls.
            DelegatingMessageSource dms = new DelegatingMessageSource();
            dms.setParentMessageSource(getInternalParentMessageSource());
            this.messageSource = dms;
            beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
            if (logger.isTraceEnabled()) {
                logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
            }
        }
    }

初始化消息源,消息源用来支持消息的国际化

9.

    /**
     *初始化应用事件广播器
     *如果上下文中未定义则用简单的应用事件广播器
     * @see org.springframework.context.event.SimpleApplicationEventMulticaster
     */
    protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
            this.applicationEventMulticaster =
                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
            if (logger.isTraceEnabled()) {
                logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        }
        else {
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
            if (logger.isTraceEnabled()) {
                logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
                        "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
            }
        }
    }

初始化应用事件广播器。事件广播器用来向 ApplicationListener 通知各种应用产生的事件,是一个标准的观察者模式。

10.
onRefresh方法源码如下

    /**
     * Template method which can be overridden to add context-specific refresh work.
     * Called on initialization of special beans, before instantiation of singletons.
     * <p>This implementation is empty.
     * @throws BeansException in case of errors
     * @see #refresh()
     */
    protected void onRefresh() throws BeansException {
        //对于子类:默认情况下不执行任何操作。
    }

是留给子类的扩展步骤,用来让特定的 Context 子类初始化其他的 Bean。

11.
registerListeners方法源码如下:

/**
     * 添加将ApplicationListener实现为侦听器的bean
     * 不会影响其他侦听器,可以将它们添加为非bean.
     */
    protected void registerListeners() {
        //首先注册静态指定的侦听器
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        //不要在这里初始化FactoryBeans:我们需要保留所有常规bean
        //未初始化,以使后处理器适用于它们!
        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);
            }
        }
    }

把实现了 ApplicationListener 的 Bean 注册到事件广播器,并对广播器中的早期未广播事件进行通知。

12.
finishBeanFactoryInitialization方法源码如下:

/**
     *完成此上下文的Bean工厂的初始化
     *初始化所有剩余的单例beans.
     */
    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        //为此上下文初始化转换服务
        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));
        }

        //如果之前没有任何bean后处理器(例如PropertyPlaceholderConfigurer bean)注册过以下任何一个,则注册一个默认的嵌入式值解析器:
        //此时,主要是为了注释属性值中的解析。
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }

        //尽早初始化LoadTimeWeaverAware Bean,以便尽早注册其转换器。
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        //停止使用临时ClassLoader进行类型匹配。
        beanFactory.setTempClassLoader(null);

        //允许缓存所有bean定义元数据,而不期望进一步的更改。
        beanFactory.freezeConfiguration();

        //实例化所有剩余的(非延迟初始化)单例。
        beanFactory.preInstantiateSingletons();
    }

冻结所有 Bean 描述信息的修改,实例化非延迟加载的单例 Bean。

13.
finishRefresh方法源码如下:

/**
     *完成此上下文的刷新,调用LifecycleProcessor的 onRefresh()方法并发布
     * {@link org.springframework.context.event.ContextRefreshedEvent}.
     */
    protected void finishRefresh() {
        //清除上下文级别的资源缓存(例如来自扫描的ASM元数据)。
        clearResourceCaches();

        // 为此上下文初始化生命周期处理器。
        initLifecycleProcessor();

        //首先将刷新传播到生命周期处理器。
        getLifecycleProcessor().onRefresh();

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

        // 如果活动,请参加LiveBeansView MBean。
        LiveBeansView.registerApplicationContext(this);
    }

完成上下文的刷新工作,调用 LifecycleProcessor 的 onFresh() 方法以及发布 ContextRefreshedEvent 事件。

14.

/**
     * Reset Spring's common reflection metadata caches, in particular the
     * {@link ReflectionUtils}, {@link AnnotationUtils}, {@link ResolvableType}
     * and {@link CachedIntrospectionResults} caches.
     * @since 4.2
     * @see ReflectionUtils#clearCache()
     * @see AnnotationUtils#clearCache()
     * @see ResolvableType#clearCache()
     * @see CachedIntrospectionResults#clearClassLoader(ClassLoader)
     */
    protected void resetCommonCaches() {
        ReflectionUtils.clearCache();
        AnnotationUtils.clearCache();
        ResolvableType.clearCache();
        CachedIntrospectionResults.clearClassLoader(getClassLoader());
    }

重置公共的缓存,比如 ReflectionUtils 中的缓存、 AnnotationUtils ,ResolvableType中的缓存等等;

到此文章就结束了。

作者:MRyan


本文采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
转载时请注明本文出处及文章链接。本文链接:https://www.wormholestack.com/archives/504/
2025 © MRyan 50 ms