Spring IoC 源码系列(二)IoC 容器启动流程分析

Spring IoC 容器启动流程详解
本文详细解析了Spring IoC容器的启动过程,从构造函数到bean实例化,涵盖XML配置解析、BeanDefinition初始化、BeanPostProcessor注册及单例bean创建等关键步骤。

    private static final String configLocation = "applicationContext.xml";

    @Test
    public void beanTest() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(configLocation);
        System.out.println("user -> " + applicationContext.getBean("user"));
    }

在没有看源码之前,对于上面的例子一直以为是在执行 applicationContext.getBean("user") 时创建的 bean 实例,带着这种想法去看了 getBean 方法的内部实现,发现有很多地方串不起来,比如 beanDefinition 是什么时候初始化的,beanPostProcessor 是什么时候设置的,看的过程中一头雾水。

IoC 的源码也跟踪了一段时间,后来在 ClassPathXmlApplicationContext 的构造函数中找到了答案,在执行 new ClassPathXmlApplicationContext(configLocation) 时 IoC 容器其实已经创建完成了,并会初始化所有的非懒加载配置的单例 bean。下面是看源码过程中的一些记录,如果有不对的地方还望大家指正。由于启动过程中完整的代码非常多,这里只总结一些重要的流程,相关的细节有兴趣的可以自己 debug 查看。

1.入口

ClassPathXmlApplicationContext 入口:

    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
    }

    public ClassPathXmlApplicationContext(
            String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
            throws BeansException {

        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }

ClassPathXmlApplicationContext 的构造函数主要做了 3 件事:

  1. 设置父容器,这里为 null
  2. 设置 XML 配置文件的位置
  3. 调用 resresh 方法,启动容器

2.解析并设置 XML 配置文件

setConfigLocations 方法用于将解析过的文件路径添加到 configLocations 数组中,用于后面 beanDefitnion 初始化。

    public void setConfigLocations(@Nullable String... locations) {
        if (locations != null) {
            Assert.noNullElements(locations, "Config locations must not be null");
            this.configLocations = new String[locations.length];
            for (int i = 0; i < locations.length; i++) {
                this.configLocations[i] = resolvePath(locations[i]).trim();
            }
        }
        else {
            this.configLocations = null;
        }
    }

3.启动流程一览

下面简化了一些无用的代码,IoC 容器启动的流程主要是通过 refresh 方法实现的,流程比较复杂,后面分步来总结。从 refresh() 方法中我们可以看出 IoC 启动流程是线程安全的,startupShutdownMonitor 是一个 Object 对象,当容器启动或者销毁时使用。

@Override
    public void refresh() throws BeansException, IllegalStateException {
        // 线程安全,startupShutdownMonitor 是一个 Object 对象,当容器启动或者销毁时使用
        synchronized (this.startupShutdownMonitor) {
            prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            prepareBeanFactory(beanFactory);
            try {
                postProcessBeanFactory(beanFactory);
                invokeBeanFactoryPostProcessors(beanFactory);
                registerBeanPostProcessors(beanFactory);
                initMessageSource();
                initApplicationEventMulticaster();
                onRefresh();
                registerListeners();
                finishBeanFactoryInitialization(beanFactory);
                finishRefresh();
            }
            catch (BeansException ex) {
            }

            finally {
                resetCommonCaches();
            }
        }
    }

简要的看完了启动流程代码,下面简单的梳理一下每个方法的作用,具体细节会在方法实现中解释。

  • prepareRefresh:设置启动信息、属性信息、初始化监听器存储集合等
  • obtainFreshBeanFactory:创建 BeanFactory,初始化 BeanDefinition
  • prepareBeanFactory:设置 bean 类加载器、解析器、注册环境信息等
  • postProcessBeanFactory:空实现,用于子类重写
  • invokeBeanFactoryPostProcessors:发现并执行 BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor
  • registerBeanPostProcessors:发现并注册 BeanPostProcessor,并不会执行
  • initMessageSource:初始化国际化信息
  • initApplicationEventMulticaster:初始化事件广播器
  • onRefresh:模板方法空实现,子类重写
  • registerListeners:注册监听器,监听器的发现基于 ApplicationListenerDetector 实现,// TODO 待验证
  • finishBeanFactoryInitialization:冻结配置文件、初始化所有非懒加载切是单例配置的 bean 等
  • finishRefresh:发布事件(清除缓存等)
  • resetCommonCaches:清除相关反射缓存数据

4.启动前准备

容器启动前会做一些准备工作,当准备工作完成后才会创建 BeanFactory

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

        // 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<>();
    }
  1. 设置启动信息:启动时间,活跃状态
  2. 初始化属性信息,是一个空方法,具体交给子类去实现,用来设置环境属性信息
  3. 验证必要的属性信息
  4. 初始化存储监听器的集合,此时并没有监听器注册

5.创建 BeanFactory 并初始化 BeanDefinition

这个流程中最值得一提的是 loadBeanDefinitions 方法,该方法用于将 Spring 的配置文件转成 Document 对象,然后解析 Document 将 XML 文件中的配置转化成 BeanDefinition,保存在 beanDefinitionMap 中用于创建 bean 对象。loadBeanDefinitions 方法之前已经总结过,大家可以在以前的文章中找到。


    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        // 返回 beanFactory
        return getBeanFactory();
    }

    @Override
    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

    @Override
    public final ConfigurableListableBeanFactory getBeanFactory() {
        synchronized (this.beanFactoryMonitor) {
            if (this.beanFactory == null) {
                throw new IllegalStateException("BeanFactory not initialized or already closed - " +
                        "call 'refresh' before accessing beans via the ApplicationContext");
            }
            return this.beanFactory;
        }
    }
  1. 如果存在 beanFactory 则销毁,并销毁创建的 bean,就是清空各种缓存 map
  2. 创建 BeanFactory(DefaultListableBeanFactory)
  3. 设置序列 ID,根据当前对象生成
  4. 设置是否允许循环依赖与覆盖 beanDefinition,默认都是不允许的,set 方法没有调用
  5. 加载 beanDefinition

6.完善 BeanFactory

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        // 设置类加载器
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // Configure the bean factory with context callbacks.
        // 设置与取消对应 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);

        // BeanFactory interface not registered as resolvable type in a plain factory.
        // MessageSource registered (and found for autowiring) as a bean.
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        // Register early post-processor for detecting inner beans as ApplicationListeners.
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        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()));
        }

        // Register default environment beans.
        // 注册默认的环境 bean 信息,比如:environment、systemProperties、systemEnvironment
        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());
        }
    }
  1. 设置 bean 的类加载器,解析器
  2. 设置与排除对应 beanPostProcessor,这里设置了 ApplicationContextAwareProcessorApplicationListenerDetectorApplicationContextAwareProcessor 会处理对应的 …Aware 接口,可以联想项目中经常使用类继承 ApplicationAware,然后获取到 ApplicationContext,这个 ApplicationContext 就是通过 BeanPostProcessor 实现的
  3. 设置依赖信息,TODO 没看懂
  4. 注册默认的环境 bean 信息,比如:environmentsystemPropertiessystemEnvironment

在项目里我们经常通过继承 ApplicationContextAware 来获取到 applicationContext,从而创建一些辅助 bean 来帮助我们实现一些架构设计,这个 applicationContext 就是通过 BeanPostProcessor 完成配置的,BeanPostProcessor 相关内容我会在后续的文章里讲到。

ApplicationContextAwareProcessor 继承自 BeanPostProcessor,会在每个 bean 创建前后执行对应的方法。下面我们一起来简单的看一下 ApplicationContextAwareProcessor 中的 postProcessBeforeInitialization 方法,看完后你就知道原因了。

    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;

        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                        bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                        bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareInterfaces(bean);
                return null;
            }, acc);
        }
        else {
            invokeAwareInterfaces(bean);
        }

        return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            // 设置 applicationContext
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

7.postProcessBeanFactory

    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    }

这个方法没有任何操作,当代码执行到这里的时候 beanDefinition 已经初始化完成,而 bean 实例还没有创建,在这个方法中你可以设置 BeanPostProcessors 来达到某种效果。比如在 StaticWebApplicationContext 实现类中会设置 ServletContextAwareProcessor 来完成 web 相关的一些配置。

8.执行 BeanFactoryPostProcessor

在 Spring 中有多种类型的 processor,不同的类型可以获取到不同资源,我们可以根据对应的资源进行一些自定义处理。

  • BeanDefinitionRegistryPostProcessor: 继承自 BeanFactoryPostProcessor,在 beanDefinition 注册之后执行,可以获取到所有已注册的 beanDefinition进行额外处理
  • BeanFactoryPostProcessor:在 BeanDefinitionRegistryPostProcessor 执行完成之后执行,可以获取到 beanFactory 进行额外处理
  • BeanPostProcessor:在 bean 实例创建前后执行
    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {

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

该方法会执行所有实现了 BeanFactoryPostProcessor 类型的 processor。下面是一个 BeanDefinitionRegistryPostProcessor 的例子

public class BeanDefinitionRegistryPostProcessorTest implements BeanDefinitionRegistryPostProcessor {

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // 获取所有 beanDefinitionNames
        String[] beanDefinitionNames = registry.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            // 根据 beanDefinitionName 获取到 beanDefinition
            BeanDefinition beanDefinition = registry.getBeanDefinition(beanDefinitionName);
            System.out.println(beanDefinitionName + " is singleton:" + beanDefinition.isSingleton());
        }
        System.out.println("------------BeanDefinitionRegistryPostProcessor start-------------");
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("------------BeanDefinitionRegistryPostProcessor end-------------");
    }
}

在这里插入图片描述
postProcessBeanDefinitionRegistry 方法有一个 BeanDefinitionRegistry 参数,通过该参数,我们可以获取到所有已经注册过的 beanDefinition,有了 beanDefinition 我们就可以在 bean 创建前动态的修改一些配置,其他类型的 processor 同理。

通过上面的截图可以看出 BeanDefinitionRegistryPostProcessorTest 本身也是一个 bean,在执行前会先从 beanFactory 中获取已注册的 processor,如果该 processor 没有创建会先在 getBean 方法中创建。因此 IoC 容器中的 bean 并不全是在 finishBeanFactoryInitialization 中实例化的。

9.发现并注册 BeanPostProcessor

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

通过方法名就能看出来这个方法用来发现并注册所有的 BeanPostProcessorBeanPostProcessor 中有两个方法,分别在 bean 创建前后执行。

10.初始化国际化配置

initMessageSource 方法用于给容器初始化一个 messageSource 用来支持一些国际化的操作。

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

11.初始化事件多播器

Spring 支持事件通知机制,主要组件包括:

  • ApplicationEvent:事件
  • ApplicationListener:事件监听器
  • ApplicationEventPublisher:事件发布
  • ApplicationEventMulticaster:事件广播

关于事件发布机制,后面会单独写一篇文章介绍原理,有兴趣的可以也参考 Spring Event事件通知机制 这篇文章进行详细了解。

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

这个方法主要用来给容器初始化一个事件多播器,后面会通过多播器将事件广播给所有的监听者。

12.onRefresh

    protected void onRefresh() throws BeansException {
        // For subclasses: do nothing by default.
    }

onRefresh 是一个模板方法,用来自定义一些实现。

13.注册监听器并发布事件

    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);
            }
        }
    }

registerListeners 方法会注册所有监听器,然后判断是否有早期要发布的事件,如果有则进行事件发布。

14.实例化单例 bean

到这里准备工作基本上都完成了,也就到了最重要的一步,实例化所有单例 bean(非懒加载),实例化的流程比较复杂,后面会通过几篇文章进行详细的梳理,这里就不展开了。

    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));
        }

        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }

        // TODO 这个是干嘛用的
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        beanFactory.setTempClassLoader(null);

        beanFactory.freezeConfiguration();

        beanFactory.preInstantiateSingletons();
    }
  1. 初始化 property 转换服务 bean
  2. 设置注解 value 解析器
  3. LoadTimeWeaverAware 目前还没有搞懂是干啥的
  4. 禁用临时类加载器,并冻结配置文件
  5. 初始化单例 bean

15.收尾工作

    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. 初始化容器生命周期处理器,这里是初始化的是一个 LifecycleProcessor 对象,这个对象主要用来管理容器的生命周期
  3. 设置处理器生命周期开始
  4. 发布容器刷新完成(ContextRefreshedEvent)事件
  5. LiveBeansView.registerApplicationContext(this) 没有看懂什么意思 // TODO

//TODO

16.resetCommonCaches

    protected void resetCommonCaches() {
        ReflectionUtils.clearCache();
        AnnotationUtils.clearCache();
        ResolvableType.clearCache();
        CachedIntrospectionResults.clearClassLoader(getClassLoader());
    }

当所有步骤完成时清除相关缓存信息。

总结

整个启动流程非常长,有的步骤会涉及到很多细节,如果要让我说该从哪里着手源码,说真的我也说不清楚,因为很多流程是环环相扣的,基本上最近一有空闲时间我就看一部分,有的部分会重复的看,每次都会有收获,慢慢的才对一些组件熟悉起来,好事多磨。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值