美文网首页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