Spring context的refresh函数执行过程分析

今天看了一下Spring Boot的run函数运行过程,发现它调用了Context中的refresh函数。所以先分析一下Spring context的refresh过程,然后再分析Spring boot中run的流程。

首先我们找到spring-context组件的AbstractApplicationContext类下的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) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

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

                // Propagate exception to caller.
                throw ex;
            }

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

prepareRefresh()

    protected void prepareRefresh() {
        // Switch to active.
        this.startupDate = System.currentTimeMillis();
        this.closed.set(false);
        this.active.set(true);

......

        // Initialize any placeholder property sources in the context environment.
        initPropertySources();

        // Validate that all properties marked as required are resolvable:
        // see ConfigurablePropertyResolver#setRequiredProperties
        getEnvironment().validateRequiredProperties();

        // Store pre-refresh ApplicationListeners...
        if (this.earlyApplicationListeners == null) {
            this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
        }
        else {
            // Reset local application listeners to pre-refresh state.
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }

        // Allow for the collection of early ApplicationEvents,
        // to be published once the multicaster is available...
        this.earlyApplicationEvents = new LinkedHashSet<>();
    }

可以看到,这个函数做了一些准备工作,记录了refresh的开始时间,调用了留给子类重写的initPropertySources()函数。

验证了环境中必要的参数,并且将earlyListeners加入到应用程序的监听器列表中。

obtainFreshBeanFactory()

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        return getBeanFactory();
    }

可以看见,refreshBeanFactory()和getBeanFactory()都是abstract函数,这两个函数设计出来就是为了让子类重写,根据子类实现具体功能,从函数名可以推断出这两个函数一个是用来初始化beanFactory,另外一个则是拿到beanFactory的实例,我们以AbstractRefreshableApplicationContext类的代码为例:

refreshBeanFactory:

    @Override
    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {//如果beanFactory已经被初始化过,则在此销毁
            destroyBeans();
            closeBeanFactory();
        }
        try {//这里其实就是new了一个DefaultListableBeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            //客制化beanFactory,例如设置能否循环引用,能否重写bean等
            customizeBeanFactory(beanFactory);
            //将xml中的bean定义加载到spring-core的注册中心中
            loadBeanDefinitions(beanFactory);
            //设置beanFactory,供getBeanFactory取得
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

getBeanFactory:不难想象,这个函数从this类中拿到beanFactory实例并返回。

prepareBeanFactory(beanFactory)

篇幅原因就不贴这部分代码,实在太长,这个函数主要做了如下几件事:

1. 设置了beanFactory的classloader

2. 设置了SpEL的解析器

3. 设置了PropertyEditor,这个是用来将xml里面的占位符解析成具体值的,例如xml里面写<... value="${predefined-var}"/>,在PropertyEditor可以将${predefined-var}解析为某个具体值,并且到时候生成的beanDefinition对应的field就是这个具体的值。这一步会发生在xml被转换为beanDefinition之前

4. 增加ApplicationContextAwareProcessor的BeanPostProcessor,这个是为了让实现了ApplicationContextAware接口的bean在初始化后自身被注入当前的ApplicationContext,实现对自己所在的Context的感知

5. 忽略下述接口的依赖注入:

EnvironmentAware.class
EmbeddedValueResolverAware.class
ResourceLoaderAware.class
ApplicationEventPublisherAware.class
MessageSourceAware.class
ApplicationContextAware.class

观察上述接口的特征,发现这些都是Aware系列接口,用于使Bean感知环境中的参数(例如当前Context)。自动装配不会对这些接口进行处理,实际上实现了这些接口的类会在Spring中有专门的函数进行处理。

6. 对于一些特定的接口实现,定义默认的注入值:

BeanFactory.class
ResourceLoader.class
ApplicationEventPublisher.class
ApplicationContext.class

这些接口是用来获取关于Spring本身相关的信息的,例如Spring本身的BeanFactory等。

7. 注册一些环境相关的bean,例如systemProperties、systemEnvironment和environment

postProcessBeanFactory(beanFactory)

这个函数实际上是空的:

    /**
     * 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) {
    }

通过上面的注释,我们可以知道,当所有的xml已经被载入并且产生了对应的beanDefinition时,这个函数将会被调用,此时bean的实例都没有产生,在此处可以对beanDefinition的属性进行修改、抑或是注册特别的beanPostProcessor用于对实例化的bean做最终处理。

这里函数留空是为了让用户能够子类化,然后在里面写入自己需要的修改,典型的模板设计模式

invokeBeanFactoryPostProcessors(beanFactory)

调用所有在容器中注册的BeanFactoryPostProcessor

registerBeanPostProcessors(beanFactory)

注册BeanPostProcessors,将所有在xml中定义的beanPostProcessors加入到当前BeanFactory的列表,以便在getBean的时候调用。

initMessageSource()

初始化消息源

initApplicationEventMulticaster()

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() + "]");
            }
        }
    }

通过Spring容器得到一个applicationEventMulticaster,如果Spring容器没有定义,则创建SimpleApplicationEventMulticaster作为applicationEventMulticaster。

通过SimpleApplicationEventMulticaster的代码我们也能推断出这个类的作用,就是向Context里面的EventListener发布消息:

    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        Executor executor = getTaskExecutor();
        //将当前的事件event发送给当前Context的每一个Listener
        for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            //如果有executor则使用executor执行
            if (executor != null) {
                executor.execute(() -> invokeListener(listener, event));
            }
            else {
                //否则直接在当前线程执行
                invokeListener(listener, event);
            }
        }
    }

onRefresh()

这是模板方法,留给子类实现并执行想要的操作

registerListeners()

这一步将注册Listener,供前面initApplicationEventMulticaster注册的EventMulticaster进行广播,代码如下:

    protected void registerListeners() {
        // Register statically specified listeners first.
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let post-processors apply to them!
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }

        // Publish early application events now that we finally have a multicaster...
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }

这段代码将静态注册的Listener和Spring中注册的Listener bean都添加到EventMulticaster中,这样从EventMulticaster中发布的消息,每个Listener都能监听到,典型的观察者模式。

值得注意的是,Context中包含earlyApplicationEvents,所有的Listener就绪后,会先接收到这个事件。

finishBeanFactoryInitialization(beanFactory)

通过上面的注释:Instantiate all remaining (non-lazy-init) singletons.

我们可以知道,这个方法初始化所有的非懒加载单例实例,代码很复杂,后面会开一个专题分析这段代码的。

finishRefresh()

从函数名可以知道这个是完成刷新,代码如下:

    protected void finishRefresh() {
        // Clear context-level resource caches (such as ASM metadata from scanning).
        clearResourceCaches();

        // Initialize lifecycle processor for this context.
        initLifecycleProcessor();

        // Propagate refresh to lifecycle processor first.
        getLifecycleProcessor().onRefresh();

        // Publish the final event.
        publishEvent(new ContextRefreshedEvent(this));

        // Participate in LiveBeansView MBean, if active.
        LiveBeansView.registerApplicationContext(this);
    }

实际上它:

1. 清空了资源缓存

2. 初始化了生命周期处理器,用于处理Bean生命周期

3. 使用生命周期处理器传播刷新事件

4. 在Context内发布刷新事件

5. 将本Context注册到ListBeansView中

至此,Context的refresh分析完毕,下一部该分析Spring Boot的run进行了什么操作了。

原文地址:https://www.cnblogs.com/nullifier/p/11438608.html

时间: 2024-10-09 04:54:16

Spring context的refresh函数执行过程分析的相关文章

Task的执行过程分析

Task的执行过程分析 Task的执行通过Worker启动时生成的Executor实例进行, caseRegisteredExecutor(sparkProperties)=> logInfo("Successfullyregistered with driver") //Make this host instead of hostPort ? executor= newExecutor(executorId, Utils.parseHostPort(hostPort)._1,s

Mapreduce执行过程分析(基于Hadoop2.4)——(三)

4.4 Reduce类 4.4.1 Reduce介绍 整完了Map,接下来就是Reduce了.YarnChild.main()—>ReduceTask.run().ReduceTask.run方法开始和MapTask类似,包括initialize()初始化,根据情况看是否调用runJobCleanupTask(),runTaskCleanupTask()等.之后进入正式的工作,主要有这么三个步骤:Copy.Sort.Reduce. 4.4.2 Copy Copy就是从执行各个Map任务的节点获取

当spring 容器初始化完成后执行某个方法

在做web项目开发中,尤其是企业级应用开发的时候,往往会在工程启动的时候做许多的前置检查. 比如检查是否使用了我们组禁止使用的Mysql的group_concat函数,如果使用了项目就不能启动,并指出哪个文件的xml文件使用了这个函数. 而在Spring的web项目中,我们可以介入Spring的启动过程.我们希望在Spring容器将所有的Bean都初始化完成之后,做一些操作,这个时候我们就可以实现一个接口: package com.yk.test.executor.processor publi

Mapreduce执行过程分析(基于Hadoop2.4)——(一)

1 概述 该瞅瞅MapReduce的内部运行原理了,以前只知道个皮毛,再不搞搞,不然怎么死的都不晓得.下文会以2.4版本中的WordCount这个经典例子作为分析的切入点,一步步来看里面到底是个什么情况. 2 为什么要使用MapReduce Map/Reduce,是一种模式,适合解决并行计算的问题,比如TopN.贝叶斯分类等.注意,是并行计算,而非迭代计算,像涉及到层次聚类的问题就不太适合了. 从名字可以看出,这种模式有两个步骤,Map和Reduce.Map即数据的映射,用于把一组键值对映射成另

Mapreduce执行过程分析(基于Hadoop2.4)——(二)

4.3 Map类 创建Map类和map函数,map函数是org.apache.hadoop.mapreduce.Mapper类中的定义的,当处理每一个键值对的时候,都要调用一次map方法,用户需要覆写此方法.此外还有setup方法和cleanup方法.map方法是当map任务开始运行的时候调用一次,cleanup方法是整个map任务结束的时候运行一次. 4.3.1 Map介绍 Mapper类是一个泛型类,带有4个参数(输入的键,输入的值,输出的键,输出的值).在这里输入的键为Object(默认是

图库Gallery3D(Gallery2)分析(四) 菜单命令执行过程分析

该分析基于 Android4.2的Gallery2 1 菜单创建过程分析. Gallery的父类是AbstractGalleryActivity类,AbstractGalleryActivity的父类是Activity类.所以菜单创建是调用的AbstractGalleryActivity的菜单创建函数. public class AbstractGalleryActivity extends Activity implements GalleryContext { private static

ART运行时Semi-Space(SS)和Generational Semi-Space(GSS)GC执行过程分析

Semi-Space(SS)GC和Generational Semi-Space(GSS)GC是ART运行时引进的两个Compacting GC.它们的共同特点是都具有一个From Space和一个To Space.在GC执行期间,在From Space分配的还存活的对象会被依次拷贝到To Space中,这样就可以达到消除内存碎片的目的.本文就将SS GC和GSS GC的执行过程分析进行详细分析. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 与SS G

MFC的执行过程分析

MFC程序的执行细节剖析 MFC程序也是Windows程序,所以它应该也有一个WinMain.可是在程序中看不到它的踪影.事实上在程序进入点之前.另一个(并且仅有一个)全局对象(theApp).这就是所谓的Application object,当操作系统将程序载入并激活时,这个全局对象获得配置,其构造函数会先运行.比WinMain更早. 一 CWinApp代替WinMain CWinApp的派生对象被称为application object,能够想见,CWinApp本身就代表一个程序本体.所谓程

ART运行时Mark-Compact( MC)GC执行过程分析

除了Semi-Space(SS)GC和Generational Semi-Space(GSS)GC,ART运行时还引入了第三种Compacting GC:Mark-Compact(MC)GC.这三种GC虽然都是Compacting GC,不过它们的实现方式却有很大不同.SS GC和GSS GC需两个Space来压缩内存,而MC GC只需一个Space来压缩内存.本文就详细分析MC GC的执行过程. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 从前面AR