美文网首页Spring Boot
springBoot启动过程容器刷新

springBoot启动过程容器刷新

作者: 小软_GCX | 来源:发表于2020-06-12 17:09 被阅读0次

    springBoot容器刷新

    上篇说了启动过程,现在说其中的刷新。上代码

    public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
          //刷新前准备
                prepareRefresh();
    
          //获取工厂
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
          //工厂预处理(给工厂设置一些必要参数 类加载器 后置处理等)
                prepareBeanFactory(beanFactory);
    
                try {
            //工厂后置处理
                    postProcessBeanFactory(beanFactory);
    
            //执行beanFactory后置处理器
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                //注册bean后置处理器
                    registerBeanPostProcessors(beanFactory);
    
            //初始化信息(国际化等)
                    initMessageSource();
    
                    //初始化应用事件派发器
                    initApplicationEventMulticaster();
    
                    //子类实现(web容器就是在这里加载的)
                    onRefresh();
    
                    //注册监听器
                    registerListeners();
    
                    // 实例化剩下的bean(单例)
                    finishBeanFactoryInitialization(beanFactory);
    
                    // 后续操作(初始化生命周期等)
                    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() {
      //记录时间,设置状态
       this.startupDate = System.currentTimeMillis();
       this.closed.set(false);
       this.active.set(true);
    
       if (logger.isInfoEnabled()) {
          logger.info("Refreshing " + this);
       }
       // 初始化属性源信息
       initPropertySources();
       //验证环境属性信息
       getEnvironment().validateRequiredProperties();
       this.earlyApplicationEvents = new LinkedHashSet<>();
    }
    

    invokeBeanFactoryPostProcessors

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
      //获取所有实现了BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor的类然后执行 postProcessBeanFactory方法
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    }
    

    点进去invokeBeanFactoryPostProcessors

    首先找到实现了BeanDefinitionRegistryPostProcessor接口和BeanFactoryPostProcessor接口的所有类,根据是否实现三种排序接口分类处理排序,放到一个集合中

    image.png

    然后执行方法,其中第二个实例是自定义实例

    image.png

    自定义实例如下 :实现BeanDefinitionRegistryPostProcessor

    @Component
    public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    
            System.out.println("postProcessBeanDefinitionRegistry数量。。。"+registry.getBeanDefinitionCount());
    //        System.out.println("postProcessBeanDefinitionRegistry数量。。。"+registry.getBeanDefinitionCount());
            RootBeanDefinition beanDefinition = new RootBeanDefinition(Row.class);
            registry.registerBeanDefinition("row",beanDefinition);
    
        }
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("postProcessBeanFactory数量"+beanFactory.getBeanDefinitionCount());
    
        }
    }
    

    此外其中一个重要的PostProcessor ConfigurationClassPostProcessor,它会对项目中的@Configuration注解修饰的类(@Component、@ComponentScan、@Import、@ImportResource修饰的类也会被处理)进行解析,解析完成之后把这些bean注册到BeanFactory中。需要注意的是这个时候注册进来的bean还没有实例化

    public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
          PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
    

    registerBeanPostProcessors

    和beanFactory的后置处理器一样,找到三种排序实现类进行注册实例化,这些BeanPostProcessor包括有AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入)、RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法)、CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等。如果是自定义的BeanPostProcessor,已经被ConfigurationClassPostProcessor注册到容器内。这些BeanPostProcessor会在这个方法内被实例化(通过调用BeanFactory的getBean方法,如果没有找到实例化的类,就会去实例化)。

    onRefresh

    servlet容器就是在这里加载的,点进去找到子类ServletWebServerApplicationContext

    @Override
    protected void onRefresh() {
       super.onRefresh();
       try {
          createWebServer();
       }
       catch (Throwable ex) {
          throw new ApplicationContextException("Unable to start web server", ex);
       }
    }
    
    private void createWebServer() {
            WebServer webServer = this.webServer;
            ServletContext servletContext = getServletContext();
            if (webServer == null && servletContext == null) {
                ServletWebServerFactory factory = getWebServerFactory();
          //创建一个server 
                this.webServer = factory.getWebServer(getSelfInitializer());
            }
            else if (servletContext != null) {
                try {
                    getSelfInitializer().onStartup(servletContext);
                }
                catch (ServletException ex) {
                    throw new ApplicationContextException("Cannot initialize servlet context",
                            ex);
                }
            }
            initPropertySources();
        }
    

    创建server有三个子类,也是springBoot支持的三种servlet容器

    image.png

    进到tomcat里,看到了tomcat熟悉的一些组件

    public WebServer getWebServer(ServletContextInitializer... initializers) {
       Tomcat tomcat = new Tomcat();
       File baseDir = (this.baseDirectory != null) ? this.baseDirectory
             : createTempDir("tomcat");
       tomcat.setBaseDir(baseDir.getAbsolutePath());
      //连接器
       Connector connector = new Connector(this.protocol);
      //service
       tomcat.getService().addConnector(connector);
       customizeConnector(connector);
       tomcat.setConnector(connector);
      //host
       tomcat.getHost().setAutoDeploy(false);
       configureEngine(tomcat.getEngine());
       for (Connector additionalConnector : this.additionalTomcatConnectors) {
          tomcat.getService().addConnector(additionalConnector);
       }
       prepareContext(tomcat.getHost(), initializers);
       return getTomcatWebServer(tomcat);
    }
    

    finishBeanFactoryInitialization

    开始实例化容器中的bean(后面详细说 bean的创建过程)

    相关文章

      网友评论

        本文标题:springBoot启动过程容器刷新

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