在环境或应用程序上下文启动之前对其进行自定义

 

目录

 

官网文档

71.3 Customize the Environment or ApplicationContext before it starts

翻译

71.3 在环境或应用程序上下文启动之前对其进行自定义


官网文档

71.3 Customize the Environment or ApplicationContext before it starts

SpringApplication has ApplicationListeners and ApplicationContextInitializers that are used to apply customizations to the context or environment. Spring Boot loads a number of such customizations for use internally from META-INF/spring.factories. There is more than one way to register additional ones:

  • Programmatically per application by calling the addListeners and addInitializers methods on SpringApplication before you run it.
  • Declaratively per application by setting context.initializer.classes or context.listener.classes.
  • Declaratively for all applications by adding a META-INF/spring.factories and packaging a jar file that the applications all use as a library.

The SpringApplication sends some special ApplicationEvents to the listeners (even some before the context is created), and then registers the listeners for events published by the ApplicationContext as well. See Section 23.5, “Application events and listeners” in the ‘Spring Boot features’ section for a complete list.

It is also possible to customize the Environment before the application context is refreshed using EnvironmentPostProcessor. Each implementation should be registered in META-INF/spring.factories:

org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor

The implementation can load arbitrary files and add them to the Environment. For instance, this example loads a YAML configuration file from the classpath:

public class EnvironmentPostProcessorExample implements EnvironmentPostProcessor {

	private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();

	@Override
	public void postProcessEnvironment(ConfigurableEnvironment environment,
			SpringApplication application) {
		Resource path = new ClassPathResource("com/example/myapp/config.yml");
		PropertySource<?> propertySource = loadYaml(path);
		environment.getPropertySources().addLast(propertySource);
	}

	private PropertySource<?> loadYaml(Resource path) {
		if (!path.exists()) {
			throw new IllegalArgumentException("Resource " + path + " does not exist");
		}
		try {
			return this.loader.load("custom-resource", path, null);
		}
		catch (IOException ex) {
			throw new IllegalStateException(
					"Failed to load yaml configuration from " + path, ex);
		}
	}

}
[Tip]

The Environment will already have been prepared with all the usual property sources that Spring Boot loads by default. It is therefore possible to get the location of the file from the environment. This example adds the custom-resource property source at the end of the list so that a key defined in any of the usual other locations takes precedence. A custom implementation may obviously defines another order.

[Note]

While using @PropertySource on your @SpringBootApplication seems convenient and easy enough to load a custom resource in the Environment, we do not recommend it as Spring Boot prepares the Environment before the ApplicationContext is refreshed. Any key defined via @PropertySource will be loaded too late to have any effect on auto-configuration.

翻译

71.3 在环境或应用程序上下文启动之前对其进行自定义

SpringApplication具有ApplicationListeners和ApplicationContextInitializers属性,

public class SpringApplication {
...
private List<ApplicationContextInitializer<?>> initializers;

private List<ApplicationListener<?>> listeners;
...
}

用于对上下文或者环境进行自定义。SpringBoot从META-INF/Spring.Factories中加载了许多这样的定制以供内部使用。有多种方法可以注册其他方法:

  • 通过在运行SpringApplication之前对其调用addListeners和addInitializers方法,以编程方式为每个应用程序提供支持。

  • 通过设置context.initializer.classes或context.listener.classes声明每个应用程序。

  • 通过添加META-INF/spring.factures并打包应用程序都用作库的JAR文件,声明性地针对所有应用程序。

SpringApplication向监听器发送一些特殊的applicationEvents(甚至在创建上下文之前发送一些),然后为applicationContext发布的事件注册监听器。有关完整列表,请参阅“Spring引导功能”部分的第23.5节“应用程序事件和侦听器”

还可以在使用EnvironmentPostProcessor自定义环境在刷新应用程序上下文之前。每个实现都应该在META-INF/Spring.Factories中注册:

org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor

实现可以加载任意文件并将其添加到环境中。例如,本例从类路径加载yaml配置文件:

public class EnvironmentPostProcessorExample implements EnvironmentPostProcessor {

	private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();

	@Override
	public void postProcessEnvironment(ConfigurableEnvironment environment,
			SpringApplication application) {
		Resource path = new ClassPathResource("com/example/myapp/config.yml");
		PropertySource<?> propertySource = loadYaml(path);
		environment.getPropertySources().addLast(propertySource);
	}

	private PropertySource<?> loadYaml(Resource path) {
		if (!path.exists()) {
			throw new IllegalArgumentException("Resource " + path + " does not exist");
		}
		try {
			return this.loader.load("custom-resource", path, null);
		}
		catch (IOException ex) {
			throw new IllegalStateException(
					"Failed to load yaml configuration from " + path, ex);
		}
	}

}

 环境已经准备好了所有通常的属性源,默认情况下Spring引导加载这些属性源。因此,可以从环境中获取文件的位置。此示例将自定义资源属性源添加到列表的末尾,以便在任何通常的其他位置中定义的键优先。自定义实现显然可以定义另一个顺序。

[Note]虽然在@SpringBootApplication 上使用@PropertySource似乎非常方便和容易,可以在环境中加载自定义资源,但我们不建议这样做,因为在刷新ApplicationContext 之前,Spring boot会准备好环境。通过@PropertySource定义的任何键将被加载太晚,无法对自动配置产生任何影响。

猜你喜欢

转载自blog.csdn.net/yyqhwr/article/details/88058531
今日推荐