美文网首页
【Spring源码】2.Spring容器启动核心方法refres

【Spring源码】2.Spring容器启动核心方法refres

作者: 天还下着毛毛雨 | 来源:发表于2021-12-24 16:43 被阅读0次

    AbstractApplicationContext

    AbstractApplicationContext 是所有 Spring上下文类的抽象父类。

    常见的上下文类型 :

    1. ClassPathXmlApplicationContext : xml配置的上下文类。

    2. AnnotationConfigApplicationContext : 支持注解的上下文类。构造方法里会直接传入要扫描的包路径,用于扫描该路径下,带有@Component及其派生注解的类,构造出BeanDefination注册进容器中, 后续进行实例化。

    3. AnnotationConfigEmbeddedWebApplicationContext :Springboot 1.5.x 用的,会重写refresh()方法中的onRefresh(),启动内嵌tomcat。

    4. AnnotationConfigServletWebServerApplicationContext : Springboot 2.x 用的,同样会重写refresh()方法中的onRefresh(),启动内嵌tomcat。

    image

    不管选用的上下文类 是哪个,都是拓展至AbstractApplicationContext类。

    容器启动的核心流程都是调用的父类继承而来的refresh()。refresh()定义了一系列用来容器启动的方法, 不同的上下文类 在 核心步骤不变的情况下, 可能重写 某些个方法,来完成不同的事情,比如springboot使用的上下文类就会重写里面的onRefresh(),启动内嵌tomcat。这是一种典型的模板设计模式。

    refresh()源码解析

    @Override
    public void refresh() throws BeansException, IllegalStateException {
       synchronized (this.startupShutdownMonitor) {
          //为容器初始化做准备
          // Prepare this context for refreshing.
          prepareRefresh();
    
          /*
          * 1、创建BeanFactory对象
          * 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设置一些属性值,可以不看
           * */
          // Prepare the bean factory for use in this context.
          prepareBeanFactory(beanFactory);
    
          try {
             // Allows post-processing of the bean factory in context subclasses.
             // 空方法
             postProcessBeanFactory(beanFactory);
    
             /*
              * BeanDefinitionRegistryPostProcessor
              * BeanFactoryPostProcessor
              * 完成对这两个接口的调用
              * */
             // Invoke factory processors registered as beans in the context.
             invokeBeanFactoryPostProcessors(beanFactory);
    
             /*
              * 把实现了BeanPostProcessor接口的类实例化,并且加入到BeanFactory中
              * */
             // Register bean processors that intercept bean creation.
             registerBeanPostProcessors(beanFactory);
    
             /*
              * 国际化的支持
              * */
             // Initialize message source for this context.
             initMessageSource();
    
             //初始化事件管理类
             // Initialize event multicaster for this context.
             initApplicationEventMulticaster();
    
             //这个方法着重理解模板设计模式,因为在springboot中,这个方法是用来做内嵌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();
          }
       }
    }
    

    相关文章

      网友评论

          本文标题:【Spring源码】2.Spring容器启动核心方法refres

          本文链接:https://www.haomeiwen.com/subject/aralqrtx.html