• SpringBoot启动关键点解析 及启动日志追溯


    <!doctype html>Spring Boot 源码阅读2

    目录

    1 SpringBoot启动关键点解析

    启动核心分为两部分new SpringApplication(primarySources)和执行run(args)方法,

    1.1 new SpringApplication(primarySources)部分

    部分的核心是从META/spring.facteries中读取ApplicationContextInitializer和ApplicationListener配置,然后直接通过反射实例化,实例化+排序完毕后,把应用初始化器ApplicationContextInitializer和应用监听放到SpringApplication对象上

    1.2 run(args)部分

    run部分最核心的构建ConfigurableApplicationContext这个上下文对象对象,构建完毕后当前线程是会返回的。

    run方法实现为:

     
     
     
    x
     
     
     
     
    /**
     * Run the Spring application, creating and refreshing a new
     * {@link ApplicationContext}.
     * @param args the application arguments (usually passed from a Java main method)
     * @return a running {@link ApplicationContext}
     */
    public ConfigurableApplicationContext run(String... args) {
       StopWatch stopWatch = new StopWatch();
       stopWatch.start();
       ConfigurableApplicationContext context = null;
       Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
       configureHeadlessProperty();
       SpringApplicationRunListeners listeners = getRunListeners(args);//获取SpringApplicationRunListener的监听,当前只有org.springframework.boot.context.event.EventPublishingRunListener一个
       listeners.starting(); //调度监听的start方法,这里事件发布监听的start方法是发布了一个ApplicationStartingEvent事件
       try {
          ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
           //创建一个ConfigurableEnvironment(理解参见1.2.1),初始化
           //让configurationProperties的属性源始终位于第一(应该是保证最高优先级)
           //调度应用监听执行environmentPrepared, EventPublishingRunListener一个也就是发布一个ApplicationEnvironmentPreparedEvent事件
           //将获取到的environment中的spring.main配置绑定到SpringApplication的source中(这部分用到了一个Binder语法,没有看懂)
          ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
    // 从环境中读取spring.beaninfo.ignore并设置为系统属性
          configureIgnoreBeanInfo(environment);
            //Banner打印
          Banner printedBanner = printBanner(environment);
            //创建ConfigurableApplicationContext对象,这个上下文对象关注的信息有点多,参见(1.2.2)
          context = createApplicationContext();
           //从META_DATA/spring.facteries中读取SpringBootExceptionReporter的配置并进行实例化,默认读取出来是org.springframework.boot.diagnostics.FailureAnalyzers
          exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                new Class[] { ConfigurableApplicationContext.class }, context);
           //准备环境,参见(1.2.3),主要为设置上下文对象的容器属性
           //调度一开始读取的initializer的执行initialize方法,之后调度监听器的contextPrepared,发布ApplicationContextInitializedEvent
           //打印开始和profile的日志
           //把拿到的标签类进行beanDefinition注册,之后调度监听器的contextLoaded,发布ApplicationPreparedEvent
          prepareContext(context, environment, listeners, applicationArguments, printedBanner);
           //刷新上下文,参见(1.2.4),
          refreshContext(context);
          afterRefresh(context, applicationArguments);
          stopWatch.stop();
          if (this.logStartupInfo) {
              //打印已启动信息以及耗时情况
             new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
          }
           //调度监听器的started的方法,此处默认为发布一个ApplicationStartedEvent事件
          listeners.started(context);
           //找注册的ApplicationRunner、CommandLineRunner,排序后分别调度对应的ApplicationRunner和CommandLineRunner (spring-boot的启动后自动执行建表语句好像就是通过这个机制实现。这里可以做一些启动后就需要立马执行的事)。注意,此时刚发布ApplicationStartedEvent而尚未发布ApplicationReadyEvent
          callRunners(context, applicationArguments);
       }
       catch (Throwable ex) {
          handleRunFailure(context, ex, exceptionReporters, listeners);
          throw new IllegalStateException(ex);
       }
       try {
           //调度监听器的running方法,此处默认为发布一个ApplicationReadyEvent事件。
           //执行完次应该代表服务正式可用
          listeners.running(context);
       }
       catch (Throwable ex) {
          handleRunFailure(context, ex, exceptionReporters, null);
          throw new IllegalStateException(ex);
       }
       return context;
    }
     

    1.2.1 ConfigurableEnvironment提供的服务(关注的信息)

    从环境接口的方法来看,它主要关注与当前应用的profile、propertySource、systemEnvironment、systemProperties、getConversionService;环境本身重要的信息有webApplicationType(ConversionService是干啥的??)

    1.2.2 ConfigurableApplicationContext

    从名字解读是可配置的应用容器对象。关注的内容非常多,包括应用监听器(ApplicationListener)、应用的后置处理器(PosProcessor)、应用的协议解析器(ProtocolResolver)、bean管理、类加载器、环境对象管理(Environment)、消息对象管理(Message)、资源对象管理(Resouce)等.

    容器对象是根据应用类型有所不同的,SERVLET创建的是org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext的容器对象,该对象在构造时会构造一个AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner对象。

    AnnotatedBeanDefinitionReader对象同时设置了beanFactory的dependencyComparator、autowireCandidateResolver实例,进行了ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、EventListenerMethodProcessor、DefaultEventListenerFactory的bean声明。

    ClassPathBeanDefinitionScanner对象创建时同时TypeFilter的实例(包含AnnotationTypeFilter(Component.class))

     

     

    1.2.3 SpringApplication.prepareContext

    代码如下:

     
     
     
    xxxxxxxxxx
     
     
     
     
    private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
          SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
       context.setEnvironment(environment);
        //把SpringApplication上的部分信息绑定到context上
       postProcessApplicationContext(context);
        //拿到之前从配置中读取并实例化的initializer,执行initialize(context)方法 !!它们大部分都是给容器设置一些值
       applyInitializers(context);
        //调度监听器的contextPrepared,此处为发布一个ApplicationContextInitializedEvent事件
       listeners.contextPrepared(context);
       if (this.logStartupInfo) {
           //打印应用启动的日志
          logStartupInfo(context.getParent() == null);
           //打印profile加载情况
          logStartupProfileInfo(context);
       }
       // Add boot specific singleton beans
       ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
       //把ApplicationArguments注册成单例bean
       beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
       if (printedBanner != null) {
           //如果Banner非空,也注册成单例bean
          beanFactory.registerSingleton("springBootBanner", printedBanner);
       }
       if (beanFactory instanceof DefaultListableBeanFactory) {
           //设置bean工程的allowBeanDefinitionOverriding属性
          ((DefaultListableBeanFactory) beanFactory)
                .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
       }
       if (this.lazyInitialization) {
           //如果是lazyInitialization模式(默认为false),给上下文追加一个LazyInitializationBeanFactoryPostProcessor的后置处理器实例
          context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
       }
       // Load the sources -》注册的入口类被识别为私有源,需要加入更多的标签类看看是否是在这里就已经被全部识别
       Set<Object> sources = getAllSources();
       Assert.notEmpty(sources, "Sources must not be empty");
       //把识别出来的源都进行beanDefinition注册
       load(context, sources.toArray(new Object[0]));
       //调度监听器的contextLoaded方法,这里表现为发布一个ApplicationPreparedEvent事件
       listeners.contextLoaded(context);
    }
     

    默认读取并实例化的初始化器有:

    0 = {DelegatingApplicationContextInitializer@3271} 1 = {SharedMetadataReaderFactoryContextInitializer@3272} 2 = {ContextIdApplicationContextInitializer@3273} 3 = {ConfigurationWarningsApplicationContextInitializer@3274} 4 = {RSocketPortInfoApplicationContextInitializer@3275} 5 = {ServerPortInfoApplicationContextInitializer@3276} 6 = {ConditionEvaluationReportLoggingListener@3277}

    1.2.4 SpringApplication.refreshContext

     
     
     
     
     
     
     
     
    private void refreshContext(ConfigurableApplicationContext context) {
       refresh(context);
       if (this.registerShutdownHook) {
          try {
              //注册关闭虚拟机的钩子
             context.registerShutdownHook(); 
          }
          catch (AccessControlException ex) {
             // Not allowed in some environments.
          }
       }
    }
    protected void refresh(ApplicationContext applicationContext) {
    Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
    ((AbstractApplicationContext) applicationContext).refresh();
    }
    //AbstractApplicationContext.refresh
        
    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing. //初始化当前容器的一些属性
            prepareRefresh();
            // Tell the subclass to refresh the internal bean factory. //设置工厂的序列化id
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            // Prepare the bean factory for use in this context. 
            //初始化beanFactory的一些属性,创建一些实例类,也注册了几个beanDefinition
            //设置内容包括 beanClassLoader、StandardBeanExpressionResolver、ResourceEditorRegistrar、ApplicationContextAwareProcessor
            //设置忽略的依赖接口EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware
            //注册BeanFactory(SpringApplication)、ResourceLoader(ConfigurableApplicationContext)、ApplicationEventPublisher(ConfigurableApplicationContext)、ApplicationContext(ConfigurableApplicationContext)
            //追加beanPostProcessors:ApplicationListenerDetector
            //管控environment、systemProperties、systemEnvironment单例
            prepareBeanFactory(beanFactory);
            try {
                // Allows post-processing of the bean factory in context subclasses.
                //设置一个WebApplicationContextServletContextAwareProcessor后置处理器
                //设置忽略接口依赖ServletContextAware
                
                //注册并实例化register和session的Scope,在注册过程中通过WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory());跳转到sprig-web中
                //注册ServletRequest、ServletResponse、HttpSession、WebRequest的解析以来
                //!!!注意,也就这里引入了对于spring-web的支持 (spring-boot通过spring-boot-starter..等是引入了spring-web的...)
                //这里总结就是注册了spring-web相关的信息
                postProcessBeanFactory(beanFactory);
                // Invoke factory processors registered as beans in the context.
                //先是收集beanFactory中直接已经注册好的BeanDefinitionRegistryPostProcessor,按registryProcessors、regularPostProcessors两种类别收集,在所有BeanDefinitionRegistryPostProcessor类后置执行方法最后执行,最后先执行按registryProcessors再执行regularPostProcessors
                //然后从bean定义集合中找是BeanDefinitionRegistryPostProcessor类别,同时带PriorityOrdered标签的,实例化后执行后置方法
                //再从bean定义集合中找是BeanDefinitionRegistryPostProcessor类别,同时带Ordered标签的,实例化后执行后置方法
                //最后执行其余没有被实例化的BeanDefinitionRegistryPostProcessor,实例化并执行
                
                
                //然后处理BeanFactoryPostProcessor类别
                //按PriorityOrdered、Ordered、其他来收集并实例化BeanFactoryPostProcessor
                //之后是分别排序和执行PriorityOrdered、Ordered、其他 类别的BeanFactoryPostProcessor
                invokeBeanFactoryPostProcessors(beanFactory);
                // Register bean processors that intercept bean creation.
                //处理BeanPostProcessor,按PriorityOrdered、Ordered、其他来收集并实例化和执行
                registerBeanPostProcessors(beanFactory);
                // Initialize message source for this context.
                //如果有名为messageSource的bean以它作为上下文里的messageSource,否则新建一个DelegatingMessageSource注册单例,并以它作为messageSource
                initMessageSource();
                // Initialize event multicaster for this context.
                //如果有名为applicationEventMulticaster的bean以它作为上下文的applicationEventMulticaster,否则新建一个SimpleApplicationEventMulticaster注册单例,并以它作为applicationEventMulticaster
                initApplicationEventMulticaster();
                // Initialize other special beans in specific context subclasses.
                //如果有名为themeSource的bean以它作为web抽象层级的themeSource,否则新建一个
                //找容器里的ServletWebServerFactory(这里找到的是tomcatServletWebServerFactory),把它实例化并通过这个工厂创建webServer(这部分还是用spring-boot里的TomcatServletWebServerFactory)
                //(!!!后续可以深入一下这里,看一下如何创建一个内嵌的tomcat,以及如何以代码的角度来理解这个tomcat容器)
                //创建完毕后,更新对应PropertySource
                onRefresh();
                // Check for listener beans and register them.
                //拿到applicationEventMulticaster,把之前收录的applicationListeners注册上(注册实例)
                //并且从bean容器中找ApplicationListener类别的bean定义,也注册上(注册beanName)
                //拿到earlyApplicationEvents,广播事件
                registerListeners();
                // Instantiate all remaining (non-lazy-init) singletons.
                //看(1.2.4.1)的源码解读,bean实例化部分并没有深入
                finishBeanFactoryInitialization(beanFactory);
                // Last step: publish corresponding event.
                //清理临时缓存
                //如果有名为lifecycleProcessor的bean以它作为上下文的lifecycleProcessor,否则创建一个DefaultLifecycleProcessor,并执行startBeans方法;标记其running=true
                //发布一个ContextRefreshedEvent事件
                //处理了一个spring.liveBeansView.mbeanDomain相关服务(这里没理解)
                //启动webServer
                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();
            }
        }
    }
     

    1.2.4.1 AbstractApplicationContext.finishBeanFactoryInitialization

    源码如下:

     
     
     
    xxxxxxxxxx
     
     
     
     
    /**
     * Finish the initialization of this context's bean factory,
     * initializing all remaining singleton beans.
     */
    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.
        //如果有对应bean定义,【先】创建一个LoadTimeWeaverAware的bean
       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.
        //这里的意思是冻结beanDefinition,不预期后面还有beanDefinition相关改动
       beanFactory.freezeConfiguration();
       // Instantiate all remaining (non-lazy-init) singletons.
        //实例化所有有beanDefinition定义但是尚未实例化的bean(具体参见1.2.4.2)
       beanFactory.preInstantiateSingletons();
    }
     

    1.2.4.2 DefaultListableBeanFactory.preInstantiateSingletons

    大部分的bean实例化就是在这个环节,细节非常复杂,这里并没有深入

     
     
     
    xxxxxxxxxx
     
     
    @Override
    public void preInstantiateSingletons() throws BeansException {
       if (logger.isTraceEnabled()) {
          logger.trace("Pre-instantiating singletons in " + this);
       }
       // Iterate over a copy to allow for init methods which in turn register new bean definitions.
       // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
       List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
       // Trigger initialization of all non-lazy singleton beans...
       for (String beanName : beanNames) {
          RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
          if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
             if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof FactoryBean) {
                   final FactoryBean<?> factory = (FactoryBean<?>) bean;
                   boolean isEagerInit;
                   if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                      isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                  ((SmartFactoryBean<?>) factory)::isEagerInit,
                            getAccessControlContext());
                   }
                   else {
                      isEagerInit = (factory instanceof SmartFactoryBean &&
                            ((SmartFactoryBean<?>) factory).isEagerInit());
                   }
                   if (isEagerInit) {
                      getBean(beanName);
                   }
                }
             }
             else {
                 //这里的实现非常复杂
                 //创建bean的实际过程(后续专门开章节再深入吧)
                 //比如bean依赖(dependsOn)、bean实例化时的后置处理(InstantiationAwareBeanPostProcessor)等都是在这里面完成
                getBean(beanName);
             }
          }
     
     
       }
     

    1.2.5 默认的关闭钩子

    钩子注册是通过

     
     
     
    x
     
     
     
     
    private void refreshContext(ConfigurableApplicationContext context) {
       refresh(context);
       if (this.registerShutdownHook) {
          try {
             context.registerShutdownHook(); //注册钩子
          }
          catch (AccessControlException ex) {
             // Not allowed in some environments.
          }
       }
    }
     

    具体代码为:(只是定义了一个独立线程,在执行结束时才进行调度)

     
     
     
    xxxxxxxxxx
     
     
     
     
    @Override
    public void registerShutdownHook() {
       if (this.shutdownHook == null) {
          // No shutdown hook registered yet.
          this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
             @Override
             public void run() {
                synchronized (startupShutdownMonitor) {
                   doClose();
                }
             }
          };
          Runtime.getRuntime().addShutdownHook(this.shutdownHook);
       }
    }
     

    具体代码如下,注意注释里说的 “Called by both {@code close()} and a JVM shutdown hook, if any.”

     
     
     
    x
     
     
     
     
    /**
     * Actually performs context closing: publishes a ContextClosedEvent and
     * destroys the singletons in the bean factory of this application context.
     * <p>Called by both {@code close()} and a JVM shutdown hook, if any.
     * @see org.springframework.context.event.ContextClosedEvent
     * @see #destroyBeans()
     * @see #close()
     * @see #registerShutdownHook()
     */
    protected void doClose() {
       // Check whether an actual close attempt is necessary...
       if (this.active.get() && this.closed.compareAndSet(false, true)) { //断点是走不到这里的..
          if (logger.isDebugEnabled()) {
             logger.debug("Closing " + this);
          }
          LiveBeansView.unregisterApplicationContext(this);
          try {
             // Publish shutdown event.
         //发布一个ContextClosedEvent事件
             publishEvent(new ContextClosedEvent(this));
          }
          catch (Throwable ex) {
             logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
          }
          // Stop all Lifecycle beans, to avoid delays during individual destruction.
          if (this.lifecycleProcessor != null) {
             try {
             //这里貌似是通过生命周期管理停掉所有在执行的bean (TODO 生命周期管理机制是啥?),并设置lifecycleProcessor.running=false
                this.lifecycleProcessor.onClose();
             }
             catch (Throwable ex) {
                logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
             }
          }
          // Destroy all cached singletons in the context's BeanFactory.
          //销毁所有beanFactory中缓存的单例bean
          destroyBeans();
      //销毁beanFactory工厂
          // Close the state of this context itself.
          closeBeanFactory();
          // Let subclasses do some final clean-up if they wish...
          onClose();
          // Reset local application listeners to pre-refresh state.
          if (this.earlyApplicationListeners != null) {
             this.applicationListeners.clear();
             this.applicationListeners.addAll(this.earlyApplicationListeners);
          }
          // Switch to inactive.
          this.active.set(false);
       }
    }
     

    1.3 启动日志分析

    1.3.1 虚拟机启动日志打印

    日志显示:

     
     
     
    xxxxxxxxxx
     
     
     
     
    Connected to the target VM, address: '127.0.0.1:59163', transport: 'socket'
     

    1.3.2 Banner打印

    日志显示:

     
     
     
    xxxxxxxxxx
     
     
     
     
      .   ____          _            __ _ _
     /\ / ___'_ __ _ _(_)_ __  __ _    
    ( ( )\___ | '_ | '_| | '_ / _` |    
     \/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::        (v2.2.5.RELEASE)
     

    打印相关代码:

     
     
     
     
     
     
     
     
    Banner printedBanner = printBanner(environment);
     

    堆栈:

     
     
     
     
     
     
     
     
    run:310, SpringApplication (org.springframework.boot)
    run:1226, SpringApplication (org.springframework.boot)
    run:1215, SpringApplication (org.springframework.boot)
    main:11, DemoApplication (com.example.demo)
     

    1.3.3 环境信息打印

    日志显示:

     
     
     
    xxxxxxxxxx
     
     
     
     
    2020-03-20 11:26:35.800  INFO 22748 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication on WIN-89EHFNGT2HI with PID 22748 (D:workspace_gwcodedemo-simple-web	argetclasses started by Administrator in D:workspace_gwcodedemo-simple-web)
    2020-03-20 11:26:35.803  INFO 22748 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
     

    打印相关代码:

     
     
     
    xxxxxxxxxx
     
     
     
     
    if (this.logStartupInfo) {
       logStartupInfo(context.getParent() == null);
       logStartupProfileInfo(context);
    }
     

    堆栈

     
     
     
    xxxxxxxxxx
     
     
     
     
    prepareContext:373, SpringApplication (org.springframework.boot)
    run:314, SpringApplication (org.springframework.boot)
    run:1226, SpringApplication (org.springframework.boot)
    run:1215, SpringApplication (org.springframework.boot)
    main:11, DemoApplication (com.example.demo)
     

    1.3.4 web服务启动日志

     
     
     
    xxxxxxxxxx
     
     
     
     
    2020-03-20 11:33:27.604  INFO 8740 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
    2020-03-20 11:33:27.661  INFO 8740 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    2020-03-20 11:33:27.663  INFO 8740 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.31]
    2020-03-20 11:33:28.328  INFO 8740 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
    2020-03-20 11:33:28.329  INFO 8740 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 15341 ms
     

    打印相关方法:

     
     
     
     
     
     
     
     
    createWebServer();
     

    堆栈:

     
     
     
     
     
     
     
     
    onRefresh:153, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
    refresh:544, AbstractApplicationContext (org.springframework.context.support)
    refresh:141, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
    refresh:747, SpringApplication (org.springframework.boot)
    refreshContext:397, SpringApplication (org.springframework.boot)
    run:315, SpringApplication (org.springframework.boot)
    run:1226, SpringApplication (org.springframework.boot)
    run:1215, SpringApplication (org.springframework.boot)
    main:11, DemoApplication (com.example.demo)
     

    1.3.5 实例化相关信息打印

    这里只是默认spring-boot-web的一个实例的打印

    日志显示:

     
     
     
    xxxxxxxxxx
     
     
     
     
    2020-03-20 11:36:29.536  INFO 21876 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
     

    打印相关方法:

     
     
     
    x
     
     
    if (logger.isInfoEnabled()) {
       logger.info("Initializing ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));
     
     
    }
     

    堆栈:

     
     
     
    xxxxxxxxxx
     
     
     
     
    initialize:181, ExecutorConfigurationSupport (org.springframework.scheduling.concurrent)
    afterPropertiesSet:173, ExecutorConfigurationSupport (org.springframework.scheduling.concurrent)
    invokeInitMethods:1855, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    initializeBean:1792, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    doCreateBean:595, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    createBean:517, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    lambda$doGetBean$0:323, AbstractBeanFactory (org.springframework.beans.factory.support)
    getObject:-1, 124734309 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$143)
    getSingleton:222, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
    doGetBean:321, AbstractBeanFactory (org.springframework.beans.factory.support)
    getBean:202, AbstractBeanFactory (org.springframework.beans.factory.support)
    configureAsyncSupport:211, WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter (org.springframework.boot.autoconfigure.web.servlet)
    configureAsyncSupport:67, WebMvcConfigurerComposite (org.springframework.web.servlet.config.annotation)
    configureAsyncSupport:68, DelegatingWebMvcConfiguration (org.springframework.web.servlet.config.annotation)
    requestMappingHandlerAdapter:626, WebMvcConfigurationSupport (org.springframework.web.servlet.config.annotation)
    requestMappingHandlerAdapter:369, WebMvcAutoConfiguration$EnableWebMvcConfiguration (org.springframework.boot.autoconfigure.web.servlet)
    invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
    invoke:62, NativeMethodAccessorImpl (sun.reflect)
    invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
    invoke:498, Method (java.lang.reflect)
    instantiate:154, SimpleInstantiationStrategy (org.springframework.beans.factory.support)
    instantiate:651, ConstructorResolver (org.springframework.beans.factory.support)
    instantiateUsingFactoryMethod:636, ConstructorResolver (org.springframework.beans.factory.support)
    instantiateUsingFactoryMethod:1338, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    createBeanInstance:1177, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    doCreateBean:557, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    createBean:517, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    lambda$doGetBean$0:323, AbstractBeanFactory (org.springframework.beans.factory.support)
    getObject:-1, 124734309 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$143)
    getSingleton:222, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
    doGetBean:321, AbstractBeanFactory (org.springframework.beans.factory.support)
    getBean:202, AbstractBeanFactory (org.springframework.beans.factory.support)
    preInstantiateSingletons:879, DefaultListableBeanFactory (org.springframework.beans.factory.support)
    finishBeanFactoryInitialization:878, AbstractApplicationContext (org.springframework.context.support)
    refresh:550, AbstractApplicationContext (org.springframework.context.support)
    refresh:141, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
    refresh:747, SpringApplication (org.springframework.boot)
    refreshContext:397, SpringApplication (org.springframework.boot)
    run:315, SpringApplication (org.springframework.boot)
    run:1226, SpringApplication (org.springframework.boot)
    run:1215, SpringApplication (org.springframework.boot)
    main:11, DemoApplication (com.example.demo)
     

    1.3.6 web启动打印

    日志显示:

     
     
     
    xxxxxxxxxx
     
     
     
     
    2020-03-20 11:37:38.186  INFO 21876 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
     

    相关方法:

     
     
     
    xxxxxxxxxx
     
     
     
     
    if (webServer != null) {
       webServer.start();
    }
     

    堆栈:

     
     
     
    xxxxxxxxxx
     
     
     
     
    startWebServer:297, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
    finishRefresh:163, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
    refresh:553, AbstractApplicationContext (org.springframework.context.support)
    refresh:141, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
    refresh:747, SpringApplication (org.springframework.boot)
    refreshContext:397, SpringApplication (org.springframework.boot)
    run:315, SpringApplication (org.springframework.boot)
    run:1226, SpringApplication (org.springframework.boot)
    run:1215, SpringApplication (org.springframework.boot)
    main:11, DemoApplication (com.example.demo)
     

    1.3.7 启动成功日志

    日志显示:

     
     
     
    xxxxxxxxxx
     
     
     
     
    2020-03-20 11:38:06.446  INFO 21876 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 168.106 seconds (JVM running for 178.556)
     

    相关代码:

     
     
     
    xxxxxxxxxx
     
     
     
     
    if (this.logStartupInfo) {
       new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
    }
     

    堆栈:

     
     
     
    xxxxxxxxxx
     
     
     
     
    run:321, SpringApplication (org.springframework.boot)
    run:1226, SpringApplication (org.springframework.boot)
    run:1215, SpringApplication (org.springframework.boot)
    main:11, DemoApplication (com.example.demo)
     
  • 相关阅读:
    hdu 3047 Zjnu Stadium(加权并查集)2009 Multi-University Training Contest 14
    hdu 5407 CRB and Candies(组合数+最小公倍数+素数表+逆元)2015 Multi-University Training Contest 10
    hdu 3635 Dragon Balls(加权并查集)2010 ACM-ICPC Multi-University Training Contest(19)
    hdu 3038 How Many Answers Are Wrong(种类并查集)2009 Multi-University Training Contest 13
    【进阶——种类并查集】hdu 1829 A Bug's Life (基础种类并查集)TUD Programming Contest 2005, Darmstadt, Germany
    hdu 1026 Ignatius and the Princess I(优先队列+bfs+记录路径)
    hdu2368Alfredo's Pizza Restaurant
    C#结课报告
    C#三个平台上的文件选择方法
    C#线程
  • 原文地址:https://www.cnblogs.com/ybk2018af/p/12530845.html
Copyright © 2020-2023  润新知