前言
提到Spring、Springoboot,很多人马上就会想到依赖注入、控制反转、自动装配、约定大于配置、使开发变得简单等等。但是如果仅仅会使用Springboot、SpringMVC完成一些增删改查,解决一些bug,那么实际上你并没有真的懂Spring、Springboot。Spring的核心是容器,Springboot更是封装了Spring,把复杂隐藏在内部,让其在使用上更简单,同时又预留了很多的扩展。所以我认为学会Springboot的简单使用只是一个开始,对业务开发更有参考和学习意义的是Springboot如何把复杂变得简单、预留的扩展接口又是如何使用的。
在 Spring Boot 中,我们可以通过实现 ApplicationContextInitializer
接口来扩展 Spring Boot 应用程序的上下文初始化过程。该接口提供了初始化 Spring 应用程序上下文之前的回调方法,可以在应用程序上下文的构建过程中对其进行某些自定义行为。
下面是 ApplicationContextInitializer
接口的定义:
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
void initialize(C applicationContext);
}
- 当 Spring Boot 应用程序的
ApplicationContext
被创建之后,将会通知所有实现了ApplicationContextInitializer
接口的启动类都会执行其initialize()
方法; - 接口有一个泛型形参
C
限制应用内容器类型,通常是ConfigurableApplicationContext
的子类,如GenericApplicationContext
、AnnotationConfigApplicationContext
等; - 在
initialize()
方法中,我们可以自定义初始化过程,例如:添加自定义的 bean、配置属性、注册监听器、配置 profile 等。
下面介绍一下 ApplicationContextInitializer
接口常见的扩展点和其使用场景:
自定义配置文件路径
Spring Boot 默认的配置文件是 application.properties
或 application.yml
。如果我们希望使用自定义的配置文件,可以通过 ApplicationContextInitializer
扩展点实现。
下面是一个示例,其自定义配置文件位置为 /opt/config/application.properties
:
public class CustomInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.getEnvironment().getPropertySources()
.addLast(new ResourcePropertySource("file:/opt/config/application.properties"));
}
}
通过 applicationContext.getEnvironment().getPropertySources()
获取应用的环境变量,然后通过 addLast()
方法将自定义的配置文件注入到环境变量中。
要生效,我们需要在 SpringApplication
中将其注册:
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringBootApplication.class);
app.addInitializers(new CustomInitializer());
app.run(args);
}
激活 Profile
可以通过 initialize()
方法中加载自定义配置文件的方式,动态激活使用不同的 Profile。例如,在一台机器的不同环境下,使用不同的 Profile:
public class ProfileInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
Environment environment = applicationContext.getEnvironment();
String activeProfiles = environment.getProperty("spring.profiles.active");
if (StringUtils.isEmpty(activeProfiles)) {
// 默认使用 test 环境配置
environment.setActiveProfiles("test");
}
}
}
添加额外的 Bean
在 initialize()
方法中也可以注册额外的 Bean。例如,向应用程序上下文中添加自定义的 HelloService
Bean。
public class BeanInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
BeanDefinitionRegistry beanDefinitionRegistry =
(BeanDefinitionRegistry) applicationContext.getBeanFactory();
RootBeanDefinition beanDefinition = new RootBeanDefinition(HelloService.class);
beanDefinitionRegistry.registerBeanDefinition("helloService", beanDefinition);
}
}
首先,获取应用程序上下文中的 BeanDefinitionRegistry
。然后创建一个 RootBeanDefinition
实例化 HelloService
并将其注册到应用程序上下文。
最后,我们需要将它们注册到主应用程序中:
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringBootApplication.class);
app.addInitializers(new BeanInitializer());
app.run(args);
}
综上所述,通过 ApplicationContextInitializer
接口,我们可以轻松地扩展 Spring Boot 应用程序的上下文初始化过程。
文章评论