zno2

spring boot 原理:生命周期

https://docs.spring.io/spring-boot/docs/2.3.9.RELEASE/reference/html/spring-boot-features.html#boot-features-application-events-and-listeners

 

引子

Spring应用?
SpringApplication

启动为什么要传入主类?

启动前可以做什么?
可以继承SpringApplication 重写protected方法;
new SpringApplication 实例后,调用set方法修改默认配置,再run;
或者工厂模式SpringApplicationBuilder修改默认配置后run;
或者通过 META-INF/spring.factories文件自动化配置;
尽管平时调用的run是静态方法,但实际等同与上面,先要new SpringApplication ,再调用实例方法 org.springframework.boot.SpringApplication.run(String...)

慎用懒加载,这个只会提高启动速度,但是隐藏的风险很大,比如一些bean只有web请求时才会触发初始化


An application is considered live as soon as the context has been refreshed, see Spring Boot application lifecycle and related Application Events.
An application is considered ready as soon as application and command-line runners have been called, see Spring Boot application lifecycle and related Application Events.

 

 

整体流程

excel文件链接

 

Environment

new StandardServletEnvironment() 这个实例化都做了什么?

有什么骚操作?

什么是env?

 

 

AbstractEnvironment 提供了org.springframework.core.env.AbstractEnvironment.customizePropertySources(MutablePropertySources)
没有做操作,子类可以重写该方法
因为实例化子类必须按顺序实例化所有超类,骚操作是实例化最终超类AbstractEnvironment 时,它调用了customizePropertySources 方法,
这一步实际会调用子类的重写方法,即org.springframework.web.context.support.StandardServletEnvironment.customizePropertySources(MutablePropertySources),
而该方法中添加完毕资源后还会调用父类的该方法即 org.springframework.core.env.StandardEnvironment.customizePropertySources(MutablePropertySources)
一顿操作下来,StandardServletEnvironment 添加了 servletConfigInitParams、servletContextInitParams、jndiProperties
StandardEnvironment添加了 systemProperties、systemEnvironment

另个init 方法会在context 刷新时调用 对应

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

 

env 和 prop 区别是什么?env 不允许修改,prop允许修改,比如可以通过-D指定,以下实际测试输出:

    public static void main(String[] args) throws Exception {
        System.out.println(JSONObject.toJSONString(System.getenv(),SerializerFeature.PrettyFormat,SerializerFeature.MapSortField));
        System.out.println(JSONObject.toJSONString(System.getProperties(),SerializerFeature.PrettyFormat,SerializerFeature.MapSortField));
    }
{
	"=::":"::\\",
	"ALLUSERSPROFILE":"C:\\ProgramData",
	"APPDATA":"C:\\Users\\witas\\AppData\\Roaming",
	"COMPUTERNAME":"DESKTOP-5KL2IOV",
	"ComSpec":"C:\\WINDOWS\\system32\\cmd.exe",
	"CommonProgramFiles":"C:\\Program Files\\Common Files",
	"CommonProgramFiles(x86)":"C:\\Program Files (x86)\\Common Files",
	"CommonProgramW6432":"C:\\Program Files\\Common Files",
	"DriverData":"C:\\Windows\\System32\\Drivers\\DriverData",
	"FPS_BROWSER_APP_PROFILE_STRING":"Internet Explorer",
	"FPS_BROWSER_USER_PROFILE_STRING":"Default",
	"HOMEDRIVE":"C:",
	"HOMEPATH":"\\Users\\witas",
	"JAVA_HOME":"D:\\e\\Java\\openjdk1.8.0_181",
	"LOCALAPPDATA":"C:\\Users\\witas\\AppData\\Local",
	"LOGONSERVER":"\\\\DESKTOP-5KL2IOV",
	"MAVEN_HOME":"D:\\e\\maven\\apache-maven-3.6.0",
	"NLS_LANG":"SIMPLIFIED CHINESE_CHINA.ZHS16GBK",
	"NUMBER_OF_PROCESSORS":"8",
	"ORACLE_HOME":"D:\\e\\oracle\\instantclient_11_2",
	"OS":"Windows_NT",
	"OneDrive":"C:\\Users\\witas\\OneDrive",
	"OneDriveConsumer":"C:\\Users\\witas\\OneDrive",
	"PATHEXT":".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC",
	"PROCESSOR_ARCHITECTURE":"AMD64",
	"PROCESSOR_IDENTIFIER":"Intel64 Family 6 Model 142 Stepping 10, GenuineIntel",
	"PROCESSOR_LEVEL":"6",
	"PROCESSOR_REVISION":"8e0a",
	"PSModulePath":"C:\\Program Files\\WindowsPowerShell\\Modules;...",
	"PUBLIC":"C:\\Users\\Public",
	"Path":"C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath;...",
	"ProgramData":"C:\\ProgramData",
	"ProgramFiles":"C:\\Program Files",
	"ProgramFiles(x86)":"C:\\Program Files (x86)",
	"ProgramW6432":"C:\\Program Files",
	"SESSIONNAME":"Console",
	"SystemDrive":"C:",
	"SystemRoot":"C:\\WINDOWS",
	"TEMP":"C:\\Users\\witas\\AppData\\Local\\Temp",
	"TMP":"C:\\Users\\witas\\AppData\\Local\\Temp",
	"TNS_ADMIN":"D:\\e\\oracle\\tnsnames",
	"USERDOMAIN":"DESKTOP-5KL2IOV",
	"USERDOMAIN_ROAMINGPROFILE":"DESKTOP-5KL2IOV",
	"USERNAME":"witas",
	"USERPROFILE":"C:\\Users\\witas",
	"windir":"C:\\WINDOWS"
}
环境变量(操作系统层面)
{
	"awt.toolkit":"sun.awt.windows.WToolkit",
	"file.encoding":"UTF-8",
	"file.encoding.pkg":"sun.io",
	"file.separator":"\\",
	"java.awt.graphicsenv":"sun.awt.Win32GraphicsEnvironment",
	"java.awt.printerjob":"sun.awt.windows.WPrinterJob",
	"java.class.path":"...",
	"java.class.version":"52.0",
	"java.endorsed.dirs":"D:\\e\\Java\\openjdk1.8.0_181\\jre\\lib\\endorsed",
	"java.ext.dirs":"D:\\e\\Java\\openjdk1.8.0_181\\jre\\lib\\ext;C:\\WINDOWS\\Sun\\Java\\lib\\ext",
	"java.home":"D:\\e\\Java\\openjdk1.8.0_181\\jre",
	"java.io.tmpdir":"C:\\Users\\witas\\AppData\\Local\\Temp\\",
	"java.library.path":"D:\\e\\Java\\openjdk1.8.0_181\\bin;...",
	"java.runtime.name":"OpenJDK Runtime Environment",
	"java.runtime.version":"1.8.0_181-1-redhat-b13",
	"java.specification.name":"Java Platform API Specification",
	"java.specification.vendor":"Oracle Corporation",
	"java.specification.version":"1.8",
	"java.vendor":"Oracle Corporation",
	"java.vendor.url":"http://java.oracle.com/",
	"java.vendor.url.bug":"http://bugreport.sun.com/bugreport/",
	"java.version":"1.8.0_181-1-redhat",
	"java.vm.info":"mixed mode",
	"java.vm.name":"OpenJDK 64-Bit Server VM",
	"java.vm.specification.name":"Java Virtual Machine Specification",
	"java.vm.specification.vendor":"Oracle Corporation",
	"java.vm.specification.version":"1.8",
	"java.vm.vendor":"Oracle Corporation",
	"java.vm.version":"25.181-b13",
	"line.separator":"\r\n",
	"os.arch":"amd64",
	"os.name":"Windows 10",
	"os.version":"10.0",
	"path.separator":";",
	"sun.arch.data.model":"64",
	"sun.boot.class.path":"D:\\e\\Java\\openjdk1.8.0_181\\jre\\lib\\resources.jar;....",
	"sun.boot.library.path":"D:\\e\\Java\\openjdk1.8.0_181\\jre\\bin",
	"sun.cpu.endian":"little",
	"sun.cpu.isalist":"amd64",
	"sun.desktop":"windows",
	"sun.io.unicode.encoding":"UnicodeLittle",
	"sun.java.command":"cn.zno.springbootwebminimal.CC",
	"sun.java.launcher":"SUN_STANDARD",
	"sun.jnu.encoding":"GBK",
	"sun.management.compiler":"HotSpot 64-Bit Tiered Compilers",
	"sun.os.patch.level":"",
	"user.country":"CN",
	"user.dir":"D:\\e\\svn\\repo1\\原型\\springbootwebminimal",
	"user.home":"C:\\Users\\witas",
	"user.language":"zh",
	"user.name":"witas",
	"user.script":"",
	"user.timezone":"Asia/Shanghai",
	"user.variant":""
}
系统变量(jvm层面)

 

什么是evn,org.springframework.core.env.Environment 给出了解释:

Interface representing the environment in which the current application is running.
Models two key aspects of the application environment: profiles and properties. 
Methods related to property access are exposed via the PropertyResolver super interface. 

A profile is a named, logical group of bean definitions to be registered with the container only if the given profile is active. 
Beans may be assigned to a profile whether defined in XML or via annotations; 
see the spring-beans 3.1 schemaor the @Profile annotation for syntax details. 
The role of the Environment object with relation to profiles is in determining which profiles (if any) are currently active, 
and which profiles (if any) should be active by default. 

Properties play an important role in almost all applications, and may originate from a variety of sources: 
properties files, JVM system properties, system environment variables, JNDI, servlet context parameters, ad-hoc Properties objects,Maps, and so on. 
The role of the environment object with relation to properties is to provide the user with a convenient service interface for configuring property sources 
and resolving properties from them. Beans managed within an ApplicationContext may register to be EnvironmentAware or @Inject the Environment in order to query profile state or resolve properties directly. In most cases, however, application-level beans should not need to interact with the Environment directly but instead may have to have ${...}} property values
replaced by a property placeholder configurer such as PropertySourcesPlaceholderConfigurer,
which itself is EnvironmentAware and as of Spring 3.1 is registered by default when using <context:property-placeholder/>. Configuration of the environment object must be done through the ConfigurableEnvironment interface, returned from all AbstractApplicationContext subclass getEnvironment() methods. See ConfigurableEnvironment Javadoc for usage examples demonstrating manipulation of property sources prior to application context refresh().

小结:env 是当前应用运行时所处的环境,主要管理profiles和properties ; Properties 来源有系统变量,环境变量,servlet上下文参数等

 

主类

启动为什么传入主类?它到底是什么?为什么传入非main函数所在类无法启动应用?
primarySource the primary source to load
primarySources the primary bean sources
The application context will loadbeans from the specified primary sources (see class-leveld ocumentation for details. The instance can be customized before calling run(String).

 答:主类只要有@org.springframework.boot.autoconfigure.SpringBootApplication  注解即可,main函数可以在任意类中。

所以关键在于这个注解做了什么,先看该注解说明:

Indicates a configuration class that declares one or more @Bean methods and also triggers auto-configuration and component scanning. 
This is a convenienceannotation that is equivalent to declaring @Configuration, @EnableAutoConfiguration and @ComponentScan.

也就是说它等价于@Configuration + @EnableAutoConfiguration + @ComponentScan

就是说主资源是一个配置,这里开启了自动配置和组件扫描,无法启动是因为没有自动注入 ,判定的是web应用,但是在bean工厂没有找到ServletWebServerFactory  无法启动 ServletWebServerApplicationContext ,所以报错说

missing ServletWebServerFactory bean.

Uable to start ...

 

这个bean是 org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration 中自动注入的

 

org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:156) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:544) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at cn.zno.springbootwebminimal.FooApplication.main(FooApplication.java:30) [classes/:na]
Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:203) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:179) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:153) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	... 8 common frames omitted

 

是依据具体条件要有Servlet、Tomcat和UpgradeProtocol 类,才激活。类似的还有 EmbeddedJetty和EmbeddedUndertow

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
    @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
    public static class EmbeddedTomcat {

        @Bean
        public TomcatServletWebServerFactory tomcatServletWebServerFactory(
                ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,
                ObjectProvider<TomcatContextCustomizer> contextCustomizers,
                ObjectProvider<TomcatProtocolHandlerCustomizer<?>> protocolHandlerCustomizers) {
            TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
            factory.getTomcatConnectorCustomizers()
                    .addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));
            factory.getTomcatContextCustomizers()
                    .addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));
            factory.getTomcatProtocolHandlerCustomizers()
                    .addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));
            return factory;
        }

    }

 

 

refresh

 

    protected void refresh(ApplicationContext applicationContext) {
        Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
        ((AbstractApplicationContext) applicationContext).refresh();
    }

 

上面这个操作会调用最外层子类的重写方法,实际调用的是 org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh()

但是这里面有异常的时候处理了一下,只是调用了super.refresh() ,即org.springframework.context.support.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.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);
            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);
                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);
                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);
                // Initialize message source for this context.
                initMessageSource();
                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();
                // Initialize other special beans in specific context subclasses.
                onRefresh();
                // Check for listener beans and register them.
                registerListeners();
                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);
                // Last step: publish corresponding event.
                finishRefresh();
            }

 

 

疑问:如何知道一个spring组件是在哪一步被实例化的?

思路:随便一个Component 构造函数打断点可知

 

关于 org.springframework.beans.factory.support.DefaultListableBeanFactory 完全可以单独介绍,到这里和spring framework 照面了

 

小结:在生命周期我可以做哪些事情

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class FooApplication {

    public static void main(String[] args) {
        System.out.println("run方法前");
        SpringApplication app = new SpringApplication(new Class<?>[] { FooApplication.class });
        app.setBanner(new MyBanner());
        app.addListeners(new MyApplicationListener());
        app.run(args);
        System.out.println("run方法后");
    }

}

 

可以监听事件

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("Event触发:" + event.getClass());

    }

}

 

可以设置banner

import java.io.PrintStream;

import org.springframework.boot.Banner;
import org.springframework.core.env.Environment;

public class MyBanner implements Banner {

    @Override
    public void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) {
        StringBuilder sb = new StringBuilder();
        sb.append("\r\n    ");
        sb.append("   ◢████████████◣        \r\n");
        sb.append("   ██████████████        \r\n");
        sb.append("   ██   ◥██◤   ██        \r\n");
        sb.append(" ◢███    ◥◤    ██◣       \r\n");
        sb.append(" ▊▎██◣        ◢█▊▊       \r\n");
        sb.append(" ▊▎██◤  ●  ●  ◥█▊▊      \r\n");
        sb.append(" ▊ ██          █▊▊       \r\n");
        sb.append(" ◥▇██ ▊      ▊ █▇◤       \r\n");
        sb.append("   ██ ◥▆▄▄▄▄▆◤ █▊   ◢▇▇◣ \r\n");
        sb.append("◢██◥◥▆▅▄▂▂▂▂▄▅▆███◣ ▊◢ █ \r\n");
        sb.append("█╳               ╳█ ◥◤◢◤ \r\n");
        sb.append("◥█◣   ˙     ˙   ◢█◤  ◢◤  \r\n");
        sb.append("  ▊             ▊    █   \r\n");
        sb.append("  ▊             ▊   ◢◤   \r\n");
        sb.append("  ▊      ⊕      █▇▇▇◤   \r\n");
        sb.append(" ◢█▇▆▆▆▅▅▅▅▆▆▆▇█◣       \r\n");
        sb.append(" ▊ ▂ ▊      ▊ ▂ \r\n\r\n");
        printStream.print(sb);
    }

}

 

import org.springframework.stereotype.Component;

@Component
public class MyComponent {

    {
        System.out.println("实例化MyComponent");
    }
}

 

可以执行runner(自动扫描)

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;

@Component
public class MyApplicationRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("应用Runner触发:" + JSONObject.toJSONString(args));
    }

}

 

可以执行runner(自动扫描)

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;

@Component
public class MyCommandLineRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("命令行runner触发:" + JSONObject.toJSONString(args));
    }

}

 

效果:

run方法前
Event触发:class org.springframework.boot.context.event.ApplicationStartingEvent
Event触发:class org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent

       ◢████████████◣        
   ██████████████        
   ██   ◥██◤   ██        
 ◢███    ◥◤    ██◣       
 ▊▎██◣        ◢█▊▊       
 ▊▎██◤  ●  ●  ◥█▊▊      
 ▊ ██          █▊▊       
 ◥▇██ ▊      ▊ █▇◤       
   ██ ◥▆▄▄▄▄▆◤ █▊   ◢▇▇◣ 
◢██◥◥▆▅▄▂▂▂▂▄▅▆███◣ ▊◢ █ 
█╳               ╳█ ◥◤◢◤ 
◥█◣   ˙     ˙   ◢█◤  ◢◤  
  ▊             ▊    █   
  ▊             ▊   ◢◤   
  ▊      ⊕      █▇▇▇◤   
 ◢█▇▆▆▆▅▅▅▅▆▆▆▇█◣       
 ▊ ▂ ▊      ▊ ▂ 

Event触发:class org.springframework.boot.context.event.ApplicationContextInitializedEvent
2023-05-09 16:09:49.726  INFO 18224 --- [           main] c.z.springbootwebminimal.FooApplication  : Starting FooApplication on DESKTOP-5KL2IOV with PID 18224 (started by witas in D:\e\svn\repo1\原型\springbootwebminimal)
2023-05-09 16:09:49.730  INFO 18224 --- [           main] c.z.springbootwebminimal.FooApplication  : No active profile set, falling back to default profiles: default
Event触发:class org.springframework.boot.context.event.ApplicationPreparedEvent
2023-05-09 16:09:51.095  INFO 18224 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2023-05-09 16:09:51.107  INFO 18224 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-05-09 16:09:51.107  INFO 18224 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.29]
2023-05-09 16:09:51.181  INFO 18224 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-05-09 16:09:51.182  INFO 18224 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1401 ms
实例化MyComponent
2023-05-09 16:09:51.365  INFO 18224 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2023-05-09 16:09:51.433  INFO 18224 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
2023-05-09 16:09:51.482  WARN 18224 --- [           main] org.thymeleaf.templatemode.TemplateMode  : [THYMELEAF][main] Template Mode 'HTML5' is deprecated. Using Template Mode 'HTML' instead.
Event触发:class org.springframework.context.event.ContextRefreshedEvent
2023-05-09 16:09:51.553  INFO 18224 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
Event触发:class org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent
2023-05-09 16:09:51.556  INFO 18224 --- [           main] c.z.springbootwebminimal.FooApplication  : Started FooApplication in 2.239 seconds (JVM running for 2.624)
Event触发:class org.springframework.boot.context.event.ApplicationStartedEvent
应用Runner触发:{"nonOptionArgs":[],"optionNames":[],"sourceArgs":[]}
命令行runner触发:[]
Event触发:class org.springframework.boot.context.event.ApplicationReadyEvent
run方法后

 

补充请求http之后和关闭jvm的日志

...
run方法后
2023-05-09 16:27:09.990  INFO 15460 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2023-05-09 16:27:09.990  INFO 15460 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2023-05-09 16:27:09.994  INFO 15460 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 4 ms
Event触发:class org.springframework.web.context.support.ServletRequestHandledEvent
Event触发:class org.springframework.web.context.support.ServletRequestHandledEvent
Event触发:class org.springframework.web.context.support.ServletRequestHandledEvent
Event触发:class org.springframework.web.context.support.ServletRequestHandledEvent
2023-05-09 16:27:39.412  INFO 15460 --- [on(3)-127.0.0.1] inMXBeanRegistrar$SpringApplicationAdmin : Application shutdown requested.
Event触发:class org.springframework.context.event.ContextClosedEvent
2023-05-09 16:27:39.414  INFO 15460 --- [on(3)-127.0.0.1] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

 

 

附1 :

spring-boot-2.2.2.RELEASE.jar中
META-INF/spring.factories

# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers

# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\
org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor

# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer

# FailureAnalysisReporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter
View Code

 

附2:

  1. An ApplicationStartingEvent is sent at the start of a run but before any processing, except for the registration of listeners and initializers.

  2. An ApplicationEnvironmentPreparedEvent is sent when the Environment to be used in the context is known but before the context is created.

  3. An ApplicationContextInitializedEvent is sent when the ApplicationContext is prepared and ApplicationContextInitializers have been called but before any bean definitions are loaded.

  4. An ApplicationPreparedEvent is sent just before the refresh is started but after bean definitions have been loaded.

  5. An ApplicationStartedEvent is sent after the context has been refreshed but before any application and command-line runners have been called.

  6. An AvailabilityChangeEvent is sent right after with LivenessState.CORRECT to indicate that the application is considered as live.

  7. An ApplicationReadyEvent is sent after any application and command-line runners have been called.

  8. An AvailabilityChangeEvent is sent right after with ReadinessState.ACCEPTING_TRAFFIC to indicate that the application is ready to service requests.

  9. An ApplicationFailedEvent is sent if there is an exception on startup.

 

posted on 2023-06-02 08:12  zno2  阅读(278)  评论(0编辑  收藏  举报

导航