ApplicationContext扩展
深入理解SpringBoot对ApplicationContext的扩展和增强,掌握ApplicationContext类型、上下文初始化器、上下文监听器的工作原理,学会自定义和扩展ApplicationContext。
📋 ApplicationContext扩展概览
SpringBoot在Spring的ApplicationContext基础上进行了扩展,提供了更多功能和便利性。
🎯 一、ApplicationContext类型
1.1 应用类型推断
SpringBoot根据类路径自动推断应用类型:
- SERVLET:传统Web应用
- REACTIVE:响应式Web应用
- NONE:非Web应用
java
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler",
null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet",
null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}1.2 ServletWebApplicationContext
类定义:
java
public class AnnotationConfigServletWebServerApplicationContext
extends ServletWebServerApplicationContext
implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
private final Set<Class<?>> annotatedClasses = new LinkedHashSet<>();
private String[] basePackages;
}特点:
- 支持注解配置
- 嵌入式Web服务器
- Servlet容器集成
1.3 ReactiveWebApplicationContext
类定义:
java
public class AnnotationConfigReactiveWebServerApplicationContext
extends ReactiveWebServerApplicationContext
implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
private final Set<Class<?>> annotatedClasses = new LinkedHashSet<>();
private String[] basePackages;
}特点:
- 响应式编程支持
- 非阻塞I/O
- WebFlux集成
🎯 二、ApplicationContextInitializer
2.1 接口定义
java
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
void initialize(C applicationContext);
}2.2 使用场景
- 注册自定义的Bean定义
- 设置环境变量
- 配置属性源
- 自定义BeanFactoryPostProcessor
2.3 实现示例
自定义初始化器:
java
public class MyApplicationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
// 添加自定义属性源
MapPropertySource customPropertySource = new MapPropertySource(
"customProperties",
Collections.singletonMap("custom.property", "custom-value"));
environment.getPropertySources().addLast(customPropertySource);
// 注册自定义Bean定义
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(MyCustomBean.class);
((BeanDefinitionRegistry) applicationContext.getBeanFactory())
.registerBeanDefinition("myCustomBean", beanDefinition);
}
}注册初始化器:
方式1:通过spring.factories
properties
# META-INF/spring.factories
org.springframework.context.ApplicationContextInitializer=\
com.example.MyApplicationContextInitializer方式2:通过SpringApplication
java
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyApplication.class);
app.addInitializers(new MyApplicationContextInitializer());
app.run(args);
}
}🎯 三、ApplicationListener
3.1 接口定义
java
public interface ApplicationListener<E extends ApplicationEvent>
extends EventListener {
void onApplicationEvent(E event);
}3.2 启动事件
SpringBoot在启动过程中发布的事件:
- ApplicationStartingEvent:应用启动开始
- ApplicationEnvironmentPreparedEvent:环境准备完成
- ApplicationContextInitializedEvent:上下文初始化完成
- ApplicationPreparedEvent:上下文准备完成
- ContextRefreshedEvent:上下文刷新完成
- ApplicationStartedEvent:应用启动完成
- ApplicationReadyEvent:应用就绪
3.3 监听器实现
方式1:实现接口
java
@Component
public class MyApplicationListener
implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
System.out.println("应用已就绪!");
// 执行启动后的逻辑
}
}方式2:使用注解
java
@Component
public class MyApplicationListener {
@EventListener
public void onApplicationReady(ApplicationReadyEvent event) {
System.out.println("应用已就绪!");
}
@EventListener
@Async
public void onApplicationStarted(ApplicationStartedEvent event) {
System.out.println("应用已启动!");
}
}3.4 监听器注册
自动注册:
- 使用
@Component注解 - 通过
spring.factories注册
spring.factories注册:
properties
# META-INF/spring.factories
org.springframework.context.ApplicationListener=\
com.example.MyApplicationListener🎯 四、ApplicationRunner和CommandLineRunner
4.1 ApplicationRunner
接口定义:
java
public interface ApplicationRunner {
void run(ApplicationArguments args) throws Exception;
}使用示例:
java
@Component
@Order(1)
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner执行");
// 获取命令行参数
String[] sourceArgs = args.getSourceArgs();
Set<String> optionNames = args.getOptionNames();
// 执行启动后的逻辑
}
}4.2 CommandLineRunner
接口定义:
java
public interface CommandLineRunner {
void run(String... args) throws Exception;
}使用示例:
java
@Component
@Order(2)
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner执行");
// 直接获取命令行参数
for (String arg : args) {
System.out.println("参数: " + arg);
}
}
}4.3 执行时机
ApplicationRunner和CommandLineRunner在ApplicationContext刷新完成后执行:
java
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}🎯 五、自定义ApplicationContext
5.1 扩展ApplicationContext
创建自定义上下文:
java
public class MyCustomApplicationContext
extends AnnotationConfigApplicationContext {
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.postProcessBeanFactory(beanFactory);
// 自定义后处理
}
@Override
protected void onRefresh() {
super.onRefresh();
// 自定义刷新逻辑
}
}5.2 使用自定义上下文
java
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyApplication.class);
app.setApplicationContextClass(MyCustomApplicationContext.class);
app.run(args);
}
}📖 学习资源
视频教程
网站资源
✅ 学习检查清单
- [ ] 已理解ApplicationContext类型
- [ ] 已掌握ApplicationContextInitializer的使用
- [ ] 已掌握ApplicationListener的使用
- [ ] 已理解启动事件体系
- [ ] 已掌握ApplicationRunner和CommandLineRunner
- [ ] 已能够自定义ApplicationContext
上一章节:配置属性绑定
返回目录:SpringBoot源码深度解析
下一主题:Spring源码深度解析