SpringBoot- default startup class 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.web.context.ServerPortInfoApplicationContextInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
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
# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
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.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
SpringBoot-start process analysis
http://blog.csdn.net/doegoo/article/details/52471310
https://www.processon.com/special/template/5d9f1a26e4b06b7d6ec5cfd4
1. Initialize SpringApplication
new SpringApplication(primarySources).run(args);
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = deduceWebApplicationType();
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
Get all ApplicationContextInitializer & ApplicationListener
1. SpringFactoriesLoader.loadFactoryNames(type, classLoader));
2. createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// Load FactoryNames from the specified location META-INF/spring.factories
2. Execute the run() method
/**
* 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);
// getSpringFactoriesInstances 从 spring.factories 加载
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, listeners, exceptionReporters, ex);
throw new IllegalStateException(ex);
}
listeners.running(context);
return context;
}
1.SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(); //Trigger ApplicationStartingEvent event
// The SpringApplicationRunListener interface specifies the life cycle of Boot, broadcasts corresponding events in each life cycle, and calls the actual ApplicationListener
2.ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments)
a>getOrCreateEnvironment();
//Create a standard environment
b>configureEnvironment(environment, applicationArguments.getSourceArgs());
//Binding CommandLinePropertySource to obtain command line parameters
//绑定Profile environment.setActiveProfiles(StringUtils.toStringArray(profiles)); 指定ActiveProfile
c>listeners.environmentPrepared(environment); //触发 EnvironmentPrepared 事件
ConfigFileApplicationListener is a listener for processing configuration files in Spring Boot
1. Obtain all EnvironmentPostProcessor after listening onApplicationEnvironmentPreparedEvent and execute the postProcessEnvironment method
2. Load the Spring configuration file after distinguishing the profile in its own postProcessEnvironment method
3. Add PropertySourceOrderingPostProcessor implements BeanFactoryPostProcessor after listening onApplicationEnvironmentPreparedEvent
3.createApplicationContext();
// 实例化 AnnotationConfigServletWebServerApplicationContext || AnnotationConfigApplicationContext
public class AnnotationConfigServletWebServerApplicationContext
extends ServletWebServerApplicationContext implements AnnotationConfigRegistry
Parent class default construction method implementation
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
4.prepareContext(context, environment, listeners, applicationArguments,printedBanner)
a> context.setEnvironment(environment);
b> postProcessApplicationContext(context);
// 注册BeanNameGenerator AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR
c> applyInitializers(context);
// Call ApplicationContextInitializer..initialize(context) initialization method
d> listeners.contextPrepared(context); // empty method
e> load(context, sources.toArray(new Object[0]));
// Take the source, the main class, as a bean and load it into the spring container
[class com.liuwei.springboot.MybatisApplication]
f> listeners.contextLoaded(context); // trigger ApplicationPreparedEvent event
5.1 refreshContext(context);
https://www.jianshu.com/p/a0a5088a651d?utm_campaign=hugo
@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();
}
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();
}
}
}
https://www.jianshu.com/p/a0a5088a651d?utm_campaign=hugo
https://www.cnblogs.com/disandafeier/p/12081301.html
// Prepare this context for refreshing.
(1) prepareRefresh ();
Initialize placeholders in the context environment
Prepare and verify system environment variables or system attributes
// Tell the subclass to refresh the internal bean factory.
(2) ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
this.beanFactory = new DefaultListableBeanFactory(); //Create and initialize beanFactory
// Prepare the bean factory for use in this context.
(3)prepareBeanFactory(beanFactory);
//Fill in various functions of BeanFactory, such as commonly used annotations @Autowired @Qualifier, etc.
//Set the parser of SPEL expression#{key}
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//Set up the resource editor register, such as PerpertyEditorSupper support
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
//Add ApplicationContextAwareProcessor processor
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//Ignore the implementation of *Aware interface in dependency injection, beanFactory.ignoreDependencyInterface such as EnvironmentAware, ApplicationEventPublisherAware, ApplicationContextAware, ResourceLoaderAware, EmbeddedValueResolverAware, MessageSourceAware, etc.
// Ignored auto-assembly (that is, beans that implement these interfaces, do not auto-wire Autowired)
//Registration dependency, if a bean property contains ApplicationEventPublisher(beanFactory), an instance of beanFactory will be injected into it
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Inject some other information beans, such as environment, systemProperties, SystemEnvironment, etc.
// Allows post-processing of the bean factory in context subclasses.
(4) postProcessBeanFactory(beanFactory);
https://fangjian0423.github.io/2017/05/10/springboot-context-refresh/
beanFactory.addBeanPostProcessor(
new WebApplicationContextServletContextAwareProcessor(this));
The GenericWebApplicationContext container will add a ServletContextAwareProcessor to the BeanFactory to call setServletContext when processing the ServletContextAware type bean initialization
// Invoke factory processors registered as beans in the context.
(5)invokeBeanFactoryPostProcessors(beanFactory);
Find out all beans in the beanFactory that implement the BeanDefinitionRegistryPostProcessor interface and the BeanFactoryPostProcessor interface
Put all the beans in the program into beanDefinitionMap. Note that this step does not instantiate the bean, but obtains the beanDefinition of the bean
// Register bean processors that intercept bean creation.
(6)registerBeanPostProcessors(beanFactory);
Find the implementation of BeanPostProcessor, register it in the container after sorting
// Initialize message source for this context.
(7)initMessageSource();
Initialize internationalization related properties
// Initialize event multicaster for this context.
(8)initApplicationEventMulticaster();
Initialize the event broadcaster
// Initialize other special beans in specific context subclasses.
(9)onRefresh();
createWebServer(); // Create a web container
// Check for listener beans and register them.
(10)registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
(11)finishBeanFactoryInitialization(beanFactory);
Instantiate all non-lazy beans in beanDefinitionMap
// The instantiation process of spring bean https://www.cnblogs.com/kevin-yuan/p/12157017.html
// Last step: publish corresponding event.
(12)finishRefresh();
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
(13)resetCommonCaches();
5.2 registerShutdownHook()
6.afterRefresh(context, applicationArguments); // empty method
7.listeners.started(context); // trigger ApplicationStartedEvent event
8.callRunners(context, applicationArguments);
// 执行 ApplicationRunner & CommandLineRunner
9.listeners.running(context); // Trigger ApplicationReadyEvent event
Application startup event mechanism
ApplicationContextInitializer
If we really need to customize an ApplicationContextInitializer, configure it through the SpringFactoriesLoader mechanism, or set it through SpringApplication.addInitializers(..)
ApplicationListener (four supported event types)
ApplicationStartedEvent:: an event executed when spring boot starts
ApplicationEnvironmentPreparedEvent: The spring boot corresponding Environment has been prepared, but the context has not been created yet.
ApplicationPreparedEvent: The spring boot context is created, but the beans in spring are not fully loaded at this time
ApplicationFailedEvent: Execution event when spring boot starts abnormally
If we want to add a custom ApplicationListener to the SpringBoot application, there are two ways:
1) Add one or more custom ApplicationListeners through the SpringApplication.addListeners(..) or SpringApplication.setListeners(..) method;
2) With the help of SpringFactoriesLoader mechanism, add configuration in the META-INF/spring.factories file
EnvironmentPostProcessor
BeanPostProcessor
BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor
Aware
@Configuration 和 Auto-configuration
They are all classes annotated with @Configuration , and @Bean , @Import , and @ImportResource can be defined in these classes .
You can use @Condition* to choose whether to load according to the situation
AnnotatedBeanDefinitionReader
ConfigurationClassPostProcessor
ConfigurationClassParser
EnableAutoConfigurationImportSelector
Built-in class description
LoggingApplicationListener
LoggingApplicationListener is used to configure the logging system, such as logback and log4j.
StandardEnvironment
StandardEnvironment has a MutablePropertySources , which contains multiple PropertySources . PropertySource is responsible for providing properties (that is, the source of property). Currently known PropertySource implementations are: MapPropertySource , SystemEnvironmentPropertySource , CommandLinePropertySource, etc.
In the actual project, if the resource information can be dynamically obtained when modifying the online product configuration, it is very convenient, the following shows a case of loading dynamically obtained resources, instead of loading hard-coded properties file information
First construct the PropertySource, and then add it to the Environment
ConfigFileApplicationListener
ConfigFileApplicationListener is used to load application.properties into StandardEnvironment .
ConfigFileApplicationListener internally uses EnvironmentPostProcessor (
ApplicationContextAwareProcessor
AnnotationConfigApplicationContext
AnnotatedBeanDefinitionReader
One, @Enable* annotation
@Enable* annotations are not newly invented annotations. These annotations were introduced as early as the Spring 3 framework, and these annotations are used to replace XML configuration files.
Many Spring developers know the @EnableTransactionManagement annotation, which can declare transaction management; the @EnableWebMvc annotation, which can enable Spring MVC; and the @EnableScheduling annotation, which can initialize a scheduler.
These annotations are actually simple configurations, imported through @Import annotations.
two,
Spring boot supports configuration files in two formats by default: .properties.yml.
Spring Boot also provides a type-safe configuration method, which associates the properties property with a Bean and its properties through @ConfigurationProperties to achieve type-safe configuration
@ConfigurationProperties(prefix = "user")
Three profile configuration
Profile is used by Spring to provide support for different configurations for different environments. Global Profile configuration is used
application-{profile}.properties 如:application-prod.properties