Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Practical Analysis of Spring Boot externalization configuration

2025-01-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/03 Report--

I. process Analysis 1.1 entry Program

In SpringApplication#run (String...) Args) method, the key process of externalization configuration is divided into the following four steps

Public ConfigurableApplicationContext run (String... Args) {... SpringApplicationRunListeners listeners = getRunListeners (args); / / 1 listeners.starting (); try {ApplicationArguments applicationArguments = new DefaultApplicationArguments (args); ConfigurableEnvironment environment = prepareEnvironment (listeners, applicationArguments); / / 2 configureIgnoreBeanInfo (environment); Banner printedBanner = printBanner (environment); context = createApplicationContext () ExceptionReporters = getSpringFactoriesInstances (SpringBootExceptionReporter.class, new Class [] {ConfigurableApplicationContext.class}, context); prepareContext (context, environment, listeners, applicationArguments, printedBanner); / / 3 refreshContext (context); / / 4 afterRefresh (context, applicationArguments); stopWatch.stop () If (this.logStartupInfo) {new StartupInfoLogger (this.mainApplicationClass) .logStarted (getApplicationLog (), stopWatch);} listeners.started (context); callRunners (context, applicationArguments);}.} 1.2 key process mind map

1.3 detailed explanation of key processes

The four steps marked in the entry program are analyzed as follows

1.3.1 SpringApplication#getRunListeners

Load META-INF/spring.factories

Get SpringApplicationRunListener

The objects stored are EventPublishingRunListener types and custom SpringApplicationRunListener implementation types

1.3.2 SpringApplication#prepareEnvironment

The three main steps in the prepareEnvironment method are as follows

Private ConfigurableEnvironment prepareEnvironment (SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {/ / Create and configure the environment ConfigurableEnvironment environment = getOrCreateEnvironment (); / / 2.1 configureEnvironment (environment, applicationArguments.getSourceArgs ()); / / 2.2 listeners.environmentPrepared (environment); / / 2.3. Return environment;} 1) getOrCreateEnvironment method

Under the WebApplicationType.SERVLET web application type, StandardServletEnvironment will be created. This article takes StandardServletEnvironment as an example. The hierarchical structure of the class is as follows.

When the customizePropertySources method is called by creating the StandardServletEnvironment,StandardServletEnvironment parent class AbstractEnvironment, the StandardServletEnvironment#customizePropertySources and StandardEnvironment#customizePropertySources are executed. The source code is as follows: AbstractEnvironment

Public AbstractEnvironment () {customizePropertySources (this.propertySources); if (logger.isDebugEnabled ()) {logger.debug ("Initialized" + getClass (). GetSimpleName () + "with PropertySources" + this.propertySources);}}

StandardServletEnvironment#customizePropertySources

/ * * Servlet context init parameters property source name: {@ value} * / public static final StringSERVLET_CONTEXT_PROPERTY_SOURCE_NAME = "servletContextInitParams"; / * * Servlet config init parameters property source name: {@ value} * / public static final StringSERVLET_ CONFIG_PROPERTY_SOURCE_NAME = "servletConfigInitParams"; / * * JNDI property source name: {@ value} * / public static final String JNDI_PROPERTY_SOURCE_NAME = "jndiProperties" @ Overrideprotected void customizePropertySources (MutablePropertySources propertySources) {propertySources.addLast (new StubPropertySource (SERVLET_CONFIG_PROPERTY_SOURCE_NAME)); propertySources.addLast (new StubPropertySource (SERVLET_CONTEXT_PROPERTY_SOURCE_NAME)); if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable ()) {propertySources.addLast (new JndiPropertySource (JNDI_PROPERTY_SOURCE_NAME));} super.customizePropertySources (propertySources);}

StandardEnvironment#customizePropertySources

/ * * System environment property source name: {@ value} * / public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment"; / * * JVM system properties property source name: {@ value} * / public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties"; @ Overrideprotected void customizePropertySources (MutablePropertySources propertySources) {propertySources.addLast (new MapPropertySource (SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties (); propertySources.addLast (new SystemEnvironmentPropertySource (SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,getSystemEnvironment ());}

PropertySources order:

ServletConfigInitParams

ServletContextInitParams

JndiProperties

SystemProperties

SystemEnvironment

The relationship between PropertySources and PropertySource is 1 to N

2) configureEnvironment method

Call configurePropertySources (environment, args), and set the PropertySources of Environment in the method, including defaultProperties and

SimpleCommandLinePropertySource (commandLineArgs), PropertySources add defaultProperties to the end, add

SimpleCommandLinePropertySource (commandLineArgs) to the front

PropertySources order:

CommandLineArgs

ServletConfigInitParams

ServletContextInitParams

JndiProperties

SystemProperties

SystemEnvironment

DefaultProperties3) listeners.environmentPrepared method

SpringApplicationRunListener#environmentPrepared execution will be traversed in order of priority, such as EventPublishingRunListener and custom SpringApplicationRunListener

EventPublishingRunListener release

ApplicationEnvironmentPreparedEvent event

ConfigFileApplicationListener snooping

ApplicationEvent event, handle ApplicationEnvironmentPreparedEvent event, load all EnvironmentPostProcessor, including yourself, and then make method callback in order

-ConfigFileApplicationListener#postProcessEnvironment method callback, and then addPropertySources method call

RandomValuePropertySource#addToEnvironment, add random after systemEnvironment, and then add the attribute source of the configuration file (see source code ConfigFileApplicationListener.Loader#load () for more information

Extension point

Customize SpringApplicationRunListener, override environmentPrepared method

Custom EnvironmentPostProcessor

Custom ApplicationListener listens for ApplicationEnvironmentPreparedEvent events

ConfigFileApplicationListener, which is both EnvironmentPostProcessor and ApplicationListener, has the following hierarchy

@ Overridepublic void onApplicationEvent (ApplicationEvent event) {/ / handle ApplicationEnvironmentPreparedEvent event if (event instanceof ApplicationEnvironmentPreparedEvent) {onApplicationEnvironmentPreparedEvent ((ApplicationEnvironmentPreparedEvent) event);} / / handle ApplicationPreparedEvent event if (event instanceof ApplicationPreparedEvent) {onApplicationPreparedEvent (event) }} private void onApplicationEnvironmentPreparedEvent (ApplicationEnvironmentPreparedEvent event) {/ / load EnvironmentPostProcessor List configured in META-INF/spring.factories / / load your own ConfigFileApplicationListener postProcessors.add (this); / / prioritize AnnotationAwareOrderComparator.sort by Ordered (postProcessors) / / callback EnvironmentPostProcessor for (EnvironmentPostProcessor postProcessor: postProcessors) {postProcessor.postProcessEnvironment (event.getEnvironment (), event.getSpringApplication ());}} List return SpringFactoriesLoader.loadFactories (EnvironmentPostProcessor.class, getClass () .getClassLoader ()) } @ Overridepublic void postProcessEnvironment (ConfigurableEnvironment environment, SpringApplication application) {addPropertySources (environment, application.getResourceLoader ());} / * * Add config file property sources to the specified environment. * @ param environment the environment to add source to * @ param resourceLoader the resource loader * @ see # addPostProcessors (ConfigurableApplicationContext) * / protected void addPropertySources (ConfigurableEnvironment environment, ResourceLoader resourceLoader) {RandomValuePropertySource.addToEnvironment (environment); / / add the property source new Loader (environment, resourceLoader). Load ();}

RandomValuePropertySource

Public static void addToEnvironment (ConfigurableEnvironment environment) {/ / add random environment.getPropertySources () .addAfter (StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, new RandomValuePropertySource (RANDOM_PROPERTY_SOURCE_NAME)) after systemEnvironment; logger.trace ("RandomValuePropertySource add to Environment");}

Add a property source for the profile: execute

New Loader (environment, resourceLoader). Load ()

Call load (Profile, DocumentFilterFactory, DocumentConsumer) (getSearchLocations ()

Get the configuration file location, which can be specified by spring.config.additional-location, spring.config.location, spring.config.name parameters or using default values), and then call addLoadedPropertySources-> addLoadedPropertySource (load the found PropertySource to PropertySources and make sure it is placed in front of the defaultProperties)

Default lookup location, configured as

"classpath:/,classpath:/config/,file:./,file:./config/", search order from back to front

PropertySources order:

CommandLineArgs

ServletConfigInitParams

ServletContextInitParams

JndiProperties

SystemProperties

SystemEnvironment

Random

Application.properties...

DefaultProperties1.3.3 SpringApplication#prepareContext

The three main steps in the prepareContext method are as follows

Private void prepareContext (ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {. ApplyInitializers (context); / / 3.1listeners.contextPrepared (context); / / 3.2... Listeners.contextLoaded (context); / / 3. 3} 1) applyInitializers method

Will traverse and execute all the ApplicationContextInitializer#initialize

Extension point

Custom ApplicationContextInitializer2) listeners.contextPrepared method

SpringApplicationRunListener#contextPrepared execution will be traversed in order of priority, such as EventPublishingRunListener and custom SpringApplicationRunListener

Extension point

Customize SpringApplicationRunListener, override contextPrepared method

3) listeners.contextLoaded method

SpringApplicationRunListener#contextLoaded execution will be traversed in order of priority, such as EventPublishingRunListener and custom SpringApplicationRunListener

EventPublishingRunListener release

ApplicationPreparedEvent event

ConfigFileApplicationListener snooping

ApplicationEvent event handling

ApplicationPreparedEvent event

Extension point

Customize SpringApplicationRunListener, override contextLoaded method

Custom ApplicationListener, listening for ApplicationPreparedEvent events

ConfigFileApplicationListener

@ Overridepublic void onApplicationEvent (ApplicationEvent event) {/ / handle ApplicationEnvironmentPreparedEvent event if (event instanceof ApplicationEnvironmentPreparedEvent) {onApplicationEnvironmentPreparedEvent ((ApplicationEnvironmentPreparedEvent) event);} / / handle ApplicationPreparedEvent event if (event instanceof ApplicationPreparedEvent) {onApplicationPreparedEvent (event);}} private void onApplicationPreparedEvent (ApplicationEvent event) {this.logger.replayTo (ConfigFileApplicationListener.class); addPostProcessors (ApplicationPreparedEvent) event). GetApplicationContext ()) } / / add PropertySourceOrderingPostProcessor processor, configure PropertySourcesprotected void addPostProcessors (ConfigurableApplicationContext context) {context.addBeanFactoryPostProcessor (new PropertySourceOrderingPostProcessor (context));}

PropertySourceOrderingPostProcessor

/ / callback processing (when configuring class attribute source resolution) @ Overridepublic void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) throws BeansException {reorderSources (this.context.getEnvironment ());} / / adjust the PropertySources order, first remove defaultProperties, and then add defaultProperties to the last private void reorderSources (ConfigurableEnvironment environment) {PropertySource. Remove (DEFAULT_PROPERTIES); if (defaultProperties! = null) {environment.getPropertySources (). AddLast (defaultProperties);}}

PropertySourceOrderingPostProcessor is BeanFactoryPostProcessor.

1.3.4 SpringApplication#refreshContext

The @ Configuration configuration class property source is parsed, and @ PropertySource annotations on your @ Configuration classes is processed, but the order is after defaultProperties, so the defaultProperties will be adjusted to the end.

AbstractApplicationContext#refresh calls invokeBeanFactoryPostProcessors (PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors), and then performs BeanFactoryPostProcessor callback processing, such as PropertySourceOrderingPostProcessor callback (see above for source code)

PropertySources order:

CommandLineArgs

ServletConfigInitParams

ServletContextInitParams

JndiProperties

SystemProperties

SystemEnvironment

Random

Application.properties...

@ PropertySource annotations on your @ Configuration classes

DefaultProperties

(this method is not recommended. It is recommended to be prepared before refreshContext. @ PropertySource loads too late and will not have any effect on automatic configuration.)

II. Extension externalization configuration attribute source 2.1 based on EnvironmentPostProcessor extension public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor2.2 based on ApplicationEnvironmentPreparedEvent extension public class ApplicationEnvironmentPreparedEventListener implements ApplicationListener2.3 based on SpringApplicationRunListener extension public class CustomSpringApplicationRunListener implements SpringApplicationRunListener, Ordered

Can be extended by overriding methods environmentPrepared, contextPrepared, and contextLoaded

2.4 extending public class CustomApplicationContextInitializer implements ApplicationContextInitializer based on ApplicationContextInitializer

For integration with Spring Cloud Config Client, externalize configuration-loaded extensions (bind to Config Server and initialize Environment with remote property sources), refer to source code PropertySourceBootstrapConfiguration (extension to ApplicationContextInitializer), ConfigServicePropertySourceLocator#locate

The remote property sources is obtained by RestTemplate by sending a GET request to http://{spring.cloud.config.uri}/{spring.application.name}/{spring.cloud.config.profile}/{spring.cloud.config.label}

2.5.Extensible public class ApplicationPreparedEventListener implements ApplicationListener2.6 based on ApplicationPreparedEvent 2.6.1 extension configuration

Add the configuration file META-INF/spring.factories under classpath, as follows

# SpringApplicationRun Listenersorg.springframework.boot.SpringApplicationRunListener=\ springboot.propertysource.extend.listener.CustomSpringApplicationRunListener# ApplicationContext Initializersorg.springframework.context.ApplicationContextInitializer=\ springboot.propertysource.extend.initializer.CustomApplicationContextInitializer# Application Listenersorg.springframework.context.ApplicationListener=\ springboot.propertysource.extend.event.listener.ApplicationEnvironmentPreparedEventListener,\ springboot.propertysource.extend.event.listener.ApplicationPreparedEventListener# EnvironmentPost Processorsorg.springframework.boot.env.EnvironmentPostProcessor=\ springboot.propertysource.extend.processor.CustomEnvironmentPostProcessor

You can choose one of the above extensions, but the loading time of the attribute source is not the same.

2.6.2 extend the instance code

Https://github.com/shijw823/springboot-externalized-configuration-extend.git

PropertySources order:

PropertySourceName: [ApplicationPreparedEventListener], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [CustomSpringApplicationRunListener-contextLoaded], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [CustomSpringApplicationRunListener-contextPrepared], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [CustomApplicationContextInitializer], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [bootstrapProperties], propertySourceClassName: [CompositePropertySource]

PropertySourceName: [configurationProperties], propertySourceClassName: [ConfigurationPropertySourcesPropertySource]

PropertySourceName: [CustomSpringApplicationRunListener-environmentPrepared], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [CustomEnvironmentPostProcessor-dev-application], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [ApplicationEnvironmentPreparedEventListener], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [commandLineArgs], propertySourceClassName: [SimpleCommandLinePropertySource]

PropertySourceName: [servletConfigInitParams], propertySourceClassName: [StubPropertySource]

PropertySourceName: [servletContextInitParams], propertySourceClassName: [ServletContextPropertySource]

PropertySourceName: [systemProperties], propertySourceClassName: [MapPropertySource]

PropertySourceName: [systemEnvironment], propertySourceClassName: [OriginAwareSystemEnvironmentPropertySource]

PropertySourceName: [random], propertySourceClassName: [RandomValuePropertySource]

PropertySourceName: [applicationConfig: [classpath:/extend/config/springApplicationRunListener.properties]], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [applicationConfig: [classpath:/extend/config/applicationListener.properties]], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [applicationConfig: [classpath:/extend/config/applicationContextInitializer.properties]], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [applicationConfig: [classpath:/extend/config/environmentPostProcessor.properties]], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [applicationConfig: [classpath:/extend/config/application.properties]], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [applicationConfig: [classpath:/extend/config/config.properties]], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [applicationConfig: [classpath:/application.properties]], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [springCloudClientHostInfo], propertySourceClassName: [MapPropertySource]

PropertySourceName: [applicationConfig: [classpath:/bootstrap.properties]], propertySourceClassName: [OriginTrackedMapPropertySource]

PropertySourceName: [propertySourceConfig], propertySourceClassName: [ResourcePropertySource]

PropertySourceName: [defaultProperties], propertySourceClassName: [MapPropertySource]

BootstrapProperties is the property sources that acquires the config-server

The loading sequence can also be found in http://{host}:{port}/actuator/env.

PropertySources unit test sequence:

@ TestPropertySource#properties

@ SpringBootTest#properties

@ TestPropertySource# locations III. References

Https://docs.spring.io/spring-boot/docs/2.0.5.RELEASE/reference/htmlsingle/#boot-features-external-config

Author: Shi Jianwei

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report