The example project created in this article is developed using SpringBoot 2.2.1.RELEASE
maven 3.5.3
idea
I won’t go into details about the specific SpringBoot project creation. The core pom file does not require additional dependencies.
Configuration file application.yml
, and there is no special configuration.
When we want to implement a custom context initialization, it is very simple, implement the above interface That’s it, like
public class ApplicationContextInitializer01 implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { System.out.println("ApplicationContextInitializer01"); } }
Customize an extension point above, how to make it effective?
The official provides three ways, such as registering directly at startup: springApplication.addInitializers(new ApplicationContextInitializer01());
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication springApplication = new SpringApplication(Application.class); springApplication.addInitializers(new ApplicationContextInitializer01()); try (ConfigurableApplicationContext context = springApplication.run(args)) { } } }
When our extension point When it is provided to the outside world in a jar package, it is obviously not feasible to use the above startup registration method. At this time, the more recommended method is to register through Spring's SPI mechanism
## in the resource directory #META-INF/spring.factoriesRegister in the file
org.springframework.context.ApplicationContextInitializer=com.git.hui.extention.context.ApplicationContextInitializer02
Instructions
AutoConfiguration is usually registered in this way
application.properties or
application.yml, configure the following
context: initializer: classes: com.git.hui.extention.context.ApplicationContextInitializer03
Start the test
above For the three registration methods, we implement three customized extension points, and then after starting, look at the actual output The above output can simply draw a conclusion, Priority of different registration methods (in order to more reasonably verify the following point of view, it is recommended that you modify the above three custom extensions to eliminate the sorting problem caused by the extension)@Order annotation. For example, when the above three extension points are all registered through the startup method,
@Order(5) public class ApplicationContextInitializer01 implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { System.out.println("ApplicationContextInitializer01"); } } @Order(2) public class ApplicationContextInitializer02 implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { System.out.println("ApplicationContextInitializer02"); } } @Order(10) public class ApplicationContextInitializer03 implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { System.out.println("ApplicationContextInitializer03"); } } @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication springApplication = new SpringApplication(Application.class); springApplication.addInitializers(new ApplicationContextInitializer01(), new ApplicationContextInitializer02(), new ApplicationContextInitializer03()); try (ConfigurableApplicationContext context = springApplication.run(args)) { } } }The output example is as follows
Then the key point comes
@Order The order of annotation modification cannot break the order of
Configuration File> SPI > Startup Mode Registration
@Order Annotations are used for modification. The smaller the value, the higher the priority.
public class ApplicationContextInitializer03 implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { // 指定激活prod对应的配置文件 configurableApplicationContext.getEnvironment().setActiveProfiles("prod"); } }But generally it is rare to see anyone doing this, because just use the configuration parameters directly. So is there any scenario that requires this? The answer is of course yes. For example, in the now widely popular docker container deployment, when we want to use the same image every time, and then during actual operation, we can determine the current image according to different environments. Which configuration files are enabled will be useful at this timeFor example, we use the container's environment parameters
app.env to obtain the current running environment. If it is prod, activate
application- prod.yml; If it is test, activate
application-test.yml
public class EenvActiveApplicationContextInitializer implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { String env = System.getenv("app.env"); if ("prod".equalsIgnoreCase(env)) { configurableApplicationContext.getEnvironment().setActiveProfiles("prod"); } else if ("test".equalsIgnoreCase(env)) { configurableApplicationContext.getEnvironment().setActiveProfiles("test"); } else { throw new RuntimeException("非法的环境参数:" + env); } } }
The above is the detailed content of How to call back ApplicationContextInitializer before SpringBoot container refreshes. For more information, please follow other related articles on the PHP Chinese website!