博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring源码(八)
阅读量:4210 次
发布时间:2019-05-26

本文共 8897 字,大约阅读时间需要 29 分钟。

通过之前的学习我们大致上已经知道了SpringBoot启动的流程。到目前剩下的就是如何将BeanDefineMap中的类转化为真实的bean,然后注册到beanFactory的beanMap中了。那么onRefresh方法是否就是做这件事情的?

protected void onRefresh() {    super.onRefresh();    try {        this.createWebServer();    } catch (Throwable var2) {        throw new ApplicationContextException("Unable to start web server", var2);    }}

我们看到在GenericWebApplicationContext中调用了

UiApplicationContextUtils.initThemeSource(this);方法。继续跟踪,我们进入initThemeSource这个方法。

public static ThemeSource initThemeSource(ApplicationContext context) {  if (context.containsLocalBean(THEME_SOURCE_BEAN_NAME)) {//themeSource是否存在,不存在的时候创建,这里的getBean方法是关键            ThemeSource themeSource = context.getBean(THEME_SOURCE_BEAN_NAME, ThemeSource.class);            // Make ThemeSource aware of parent ThemeSource.            if (context.getParent() instanceof ThemeSource && themeSource instanceof HierarchicalThemeSource) {                      HierarchicalThemeSource hts = (HierarchicalThemeSource) themeSource;                      if (hts.getParentThemeSource() == null) {                                // Only set parent context as parent ThemeSource if no parent ThemeSource                                // registered already.                                hts.setParentThemeSource((ThemeSource) context.getParent());                      }            }            if (logger.isDebugEnabled()) {                      logger.debug("Using ThemeSource [" + themeSource + "]");            }            return themeSource;  }  else {//创建themeSource对象并返回。            // Use default ThemeSource to be able to accept getTheme calls, either            // delegating to parent context's default or to local ResourceBundleThemeSource.            HierarchicalThemeSource themeSource = null;            if (context.getParent() instanceof ThemeSource) {                      themeSource = new DelegatingThemeSource();                      themeSource.setParentThemeSource((ThemeSource) context.getParent());            }            else {                      themeSource = new ResourceBundleThemeSource();            }            if (logger.isDebugEnabled()) {                      logger.debug("Unable to locate ThemeSource with name '" + THEME_SOURCE_BEAN_NAME +                                          "': using default [" + themeSource + "]");            }            return themeSource;  }}//创建web服务    private void createWebServer() {        WebServer webServer = this.webServer;        ServletContext servletContext = this.getServletContext();        if (webServer == null && servletContext == null) {            ServletWebServerFactory factory = this.getWebServerFactory();            this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer()});        } else if (servletContext != null) {            try {                this.getSelfInitializer().onStartup(servletContext);            } catch (ServletException var4) {                throw new ApplicationContextException("Cannot initialize servlet context", var4);            }        }        this.initPropertySources();    }

    这块是获取tomcat的,通过ServletWebServerFactory拿取servlet服务器

protected ServletWebServerFactory getWebServerFactory() {    String[] beanNames = this.getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);    if (beanNames.length == 0) {        throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.");    } else if (beanNames.length > 1) {        throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));    } else {        return (ServletWebServerFactory)this.getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);    }}

代码运行到这里的时候,tomcat已经加载好了。

protected void initPropertySources() {    ConfigurableEnvironment env = this.getEnvironment();    if (env instanceof ConfigurableWebEnvironment) {        ((ConfigurableWebEnvironment)env).initPropertySources(this.servletContext, (ServletConfig)null);    }}

又进行了一次配置修改

public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {    WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(), servletContext, servletConfig);}

  创建完servlet服务器之后,就开始注册registerListener。这块就是上篇文档我们说到的ApplicationListenner接口。

  执行完上述操作之后,我们看看finishBeanFactoryInitialization是做那些工作的。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {   // Initialize conversion service for this context.   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));   }   // Register a default embedded value resolver if no bean post-processor   // (such as a PropertyPlaceholderConfigurer bean) registered any before:   // at this point, primarily for resolution in annotation attribute values.   if (!beanFactory.hasEmbeddedValueResolver()) {      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));   }   // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.   String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);   for (String weaverAwareName : weaverAwareNames) {      getBean(weaverAwareName);   }   // Stop using the temporary ClassLoader for type matching.   beanFactory.setTempClassLoader(null);   // Allow for caching all bean definition metadata, not expecting further changes.   beanFactory.freezeConfiguration();   // Instantiate all remaining (non-lazy-init) singletons.   beanFactory.preInstantiateSingletons();}
 

   通过debug发现,这个方法对bean进行实例化。

   通过这个方法之后,singletonObjects被逐渐转化为bean实体。

在finishRefresh方法中

protected void finishRefresh() {   // Clear context-level resource caches (such as ASM metadata from scanning).   clearResourceCaches();   // 初始化一个处理器initLifecycleProcessor();   // 拿到处理器,并初始化lifecycle接口的类   getLifecycleProcessor().onRefresh();   // 发布容器已经刷新的消息   publishEvent(new ContextRefreshedEvent(this));   // Participate in LiveBeansView MBean, if active.   LiveBeansView.registerApplicationContext(this);}

   初始化有lifecycle接口的类

protected void initLifecycleProcessor() {   ConfigurableListableBeanFactory beanFactory = getBeanFactory();   if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {      this.lifecycleProcessor =            beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);      if (logger.isTraceEnabled()) {         logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");      }   }   else {      DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();      defaultProcessor.setBeanFactory(beanFactory);      this.lifecycleProcessor = defaultProcessor;      beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);      if (logger.isTraceEnabled()) {         logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +               "[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");      }   }}
  //  这里开始调用lifecycle接口bean的方法private void startBeans(boolean autoStartupOnly) {//获取实现了lifecycle接口的bean   Map, Lifecycle> lifecycleBeans = getLifecycleBeans();   Map, LifecycleGroup> phases = new HashMap<>();   lifecycleBeans.forEach((beanName, bean) -> {      if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {         int phase = getPhase(bean);         LifecycleGroup group = phases.get(phase);         if (group == null) {            group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);            phases.put(phase, group);         }         group.add(beanName, bean);      }   });   if (!phases.isEmpty()) {      Listkeys =new ArrayList<>(phases.keySet());      Collections.sort(keys);      for (Integer key : keys) {         phases.get(key).start();      }   }}

  但是分析到这里就比较奇特了,这里只是启动启动了tomcat,那么tomcat是在哪里创建的?

我跟踪代码.

   我们发现在OnRefresh方法中就创建了。我们看到OnRefresh方法有4个实现。

我们依次查看源代码,看看实现有什么差别。发现ServletWebServerApplicationContent和ReactiveWebServerApplicationContent都有Servlet容器服务的创建。

在这里突然想到,如果我们不做服务端也就是不想启动servlet容器,那么是不是就不用用剩余的两个content类?如果是这样的话,那么肯定在创建这里的content时候就决定了。我们知道当时创建content容器的时候得方法是createApplicationContent方法。

  那么是不是我们设置了webApplicationType就可以了?通过研究发现确实是这样的。其实我一直觉得控制是否启动servlet容器的控制在于OnRefresh中,现在发现spring调用前就决定了一切。

SpringApplicationBuilder builder = new SpringApplicationBuilder(MergeeServic.class);ApplicationContext applicationContext = builder.web(WebApplicationType.NONE).headless(false).run(args);

  通过上述分析,springboot的过程已经解析的基本明确了。

转载地址:http://uhkmi.baihongyu.com/

你可能感兴趣的文章
sd是否在位检查
查看>>
关于USB Gadget开发
查看>>
tofel词汇
查看>>
jellybean的suspend策略变动
查看>>
Android linux的休眠和唤醒
查看>>
高通msm8x60 boot(lk)的usb处理解析流程
查看>>
MSM8260 EHCI-MSM72k主控制器的状态机迁移分析
查看>>
MSM8x60 OTG之设备控制器流程分析
查看>>
MSM8X60 USB控制器流程分析
查看>>
sd卡驱动分析之card
查看>>
sd卡驱动分析之core
查看>>
sd卡驱动分析之host
查看>>
sd卡驱动分析之相关硬件操作和总结
查看>>
好的播文
查看>>
linux dd命令解析
查看>>
linux find命令详解
查看>>
S3C2440上touchscreen触摸屏驱动
查看>>
ARM-Linux驱动-触摸屏驱动分析
查看>>
GPIO的上拉电阻的作用
查看>>
kernel power off流程分析
查看>>