SpringBoot-startup process analysis

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

  1. EnvironmentAware
  2. EmbeddedValueResolverAware
  3. ResourceLoaderAware

 

  1. ApplicationEventPublisherAware
  2. MessageSourceAware
  3. ApplicationContextAware

 

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

 

 

 

 

Guess you like

Origin blog.csdn.net/lewee0215/article/details/111828975