Skip to content

Spring 核心流程

├─main()
│ ├─SpringApplication.run()     此处下面省略了中间重载的 run() 方法。
│   ├─refreshContext(context);
│     ├─refresh(context);       此处下面省略了中间重载的 refresh() 方法。
│       └─AbstractApplicationContext.refresh();     一直到这个方法,详情参考下面代码块。

该方法是 spring 容器初始化的核心方法。是 spring 容器初始化的核心流程,是一个典型的父类模板设计模式的运用

根据不同的上下文对象,会掉到不同的上下文对象子类方法中

核心上下文子类有:

  • ClassPathXmlApplicationContext
  • FileSystemXmlApplicationContext
  • AnnotationConfigApplicationContext
  • EmbeddedWebApplicationContext(springboot)
java
/**
 * 方法重要程度:
 *  0:不重要,可以不看
 *  1:一般重要,可看可不看
 *  5:非常重要,一定要看
 *  必须读的 :重要程度 5
 */
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        //为容器初始化做准备,重要程度:0
        // Prepare this context for refreshing.
        prepareRefresh();

        /**
          重要程度:5
          1、创建BeanFactory对象。
          对应 SpringBoot 工程,就没有下面的 xml 解析的过程了,
          只是创建了对象 new DefaultListableBeanFactory(); 并返回。
          扫描 bean 的过程通过 @ComponentScan 注解完成。
        * 2、xml解析
        * 	传统标签解析:bean、import等
        * 	自定义标签解析 如:<context:component-scan base-package="com.xiangxue.jack"/>
        * 	自定义标签解析流程:
        * 		a、根据当前解析标签的头信息找到对应的namespaceUri
        * 		b、加载spring所有jar中的spring.handlers文件。并建立映射关系
        * 		c、根据namespaceUri从映射关系中找到对应的实现了NamespaceHandler接口的类
        * 		d、调用类的init方法,init方法是注册了各种自定义标签的解析类
        * 		e、根据namespaceUri找到对应的解析类,然后调用paser方法完成标签解析
        *
        * 3、把解析出来的xml标签封装成BeanDefinition对象
        * */
        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        /*
         * 给beanFactory设置一些属性值,可以不看
         * 设置了一些接口类:
         * EnvironmentAware.class
         * EmbeddedValueResolverAware.class
         * ResourceLoaderAware.class
         * ApplicationEventPublisherAware.class
         * MessageSourceAware.class
         * ApplicationContextAware.class
         * ApplicationStartupAware.class
         */
        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            /*
             * 这里如果是 web 应用,则注册了 RequestScope 和 SessionScope
             */
            postProcessBeanFactory(beanFactory);

            /**
             * BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor
             * 实例化注册到 Spring 容器并完成对上面这两个接口的调用
             */
            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);

            /*
            * 把实现了BeanPostProcessor接口的类实例化,并且加入到BeanFactory中
            * */
            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);

            /*
                * 国际化,重要程度2
                * */
            // Initialize message source for this context.
            initMessageSource();

            //初始化事件管理类
            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            //这个方法着重理解模板设计模式,因为在springboot中,这个方法是用来做内嵌tomcat启动的
            // 启动 Tomcat 的入口
            // Initialize other special beans in specific context subclasses.
            onRefresh();

            /*
             * 往事件管理类中注册事件类
             */
            // Check for listener beans and register them.
            registerListeners();

            /*
            * 这个方法是spring中最重要的方法,没有之一
            * 所以这个方法一定要理解要具体看
            * 1、bean实例化过程
            * 2、ioc
            * 3、注解支持
            * 4、BeanPostProcessor的执行
            * 5、Aop的入口
            * */
            // 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();
        }
    }
}