最新实战案例锦集:《Spring Boot3实战案例合集》持续更新,每天至少更新一篇文章,订阅后将赠送文章最后展示的所有MD文档(学习笔记)。
环境:SpringBoot3.2.5
1. 简介
Spring Boot 提供了非常多的强大扩展点,通过这些扩展点可以满足我们在不同场景下的定制化需求。开发者可以通过这些扩展点在应用生命周期的关键时刻介入,从而实现特定的功能或逻辑。下面是本篇文章将要介绍的扩展点:
AutoConfigurationImportFilter
用于限制自动配置类。
ApplicationContextFactory
用于创建 SpringApplication 使用的 ConfigurableApplicationContext 的策略接口。创建的上下文应以默认形式返回,由 SpringApplication 负责配置和刷新上下文。
SpringApplicationRunListener
通过该接口,我们可以自定义Spring Boot在启动过程中每个阶段需要执行的事件监听动作。
ApplicationContextInitializer
该接口在Spring容器执行刷新动作执行执行,在refresh你可以对容器进行相应的操作。
接下来,我们将详细的介绍上面几个强大的容器扩展点的应用。
2. 实战案例
2.1 AutoConfigurationImportFilter
默认情况下,Spring Boot提供了3个该接口的实现,如下:
OnBeanCondition
该实现用来检查当前容器中是否存在相应的Bean。
OnClassCondition
检查当前CLASSPATH下是否有相应的类。
OnWebApplicationCondition
检查当前Spring运行的环境:SERVLET,REACTIVE。
我们可以通过自定义实现自己的检查,如下示例:
public class PackClassCondition implements AutoConfigurationImportFilter, EnvironmentAware {
private Environment environment ;
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
boolean[] matchs = new boolean[autoConfigurationClasses.length] ;
for (int i = 0, len = matchs.length; i < len; i++) {
if (autoConfigurationClasses[i] != null &&
autoConfigurationClasses[i].equals(PackAutoConfiguration.class.getName())) {
Boolean ret = this.environment.getProperty("pack.app.enabled", Boolean.class, false) ;
matchs[i] = ret ;
} else {
matchs[i] = true ;
}
}
return matchs ;
}
public void setEnvironment(Environment environment) {
this.environment = environment ;
}
}
在该实现中,我们判断了当前的类是否是PackAutoConfiguration,如果是则判断当前配置的 pack.app.enabled 是否为true,只有为true该自动配置才会生效。
接下来,需要在META-INF/spring.factories中进行注册
\ =
com.pack.extension.autoImportfilter.PackClassCondition
通常情况,我们是不需要自己实现该接口的,Spring Boot提供的有关条件注解基本上是能够满足我们的需求的。
2.2 ApplicationContextFactory
该接口用来创建当前Spring Boot所需的ApplicationContext容器。这里你可以根据当前的环境或者其它一些自定义的条件进行容器的创建。默认提供了2种环境下的容器创建:分别是,SERVLET,REACTIVE。如下示例:
public class PackApplicationContextFactory implements ApplicationContextFactory {
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
return (webApplicationType != WebApplicationType.SERVLET) ? null : createContext();
}
private ConfigurableApplicationContext createContext() {
System.err.println("使用自定义容器...") ;
return new PackApplicationContext();
}
public static class PackApplicationContext extends AnnotationConfigServletWebServerApplicationContext{
protected void prepareRefresh() {
System.err.println("准备执行容器核心方法refresh") ;
super.prepareRefresh();
}
}
}
这里我们自定义了ApplicationContext容器,不过仅仅是重写了prepareRefresh方法,打印了一段话。
在META-INF/spring.factories中进行注册
\ =
com.pack.extension.contextfactory.PackApplicationContextFactory
启动应用见看到到如下信息
使用了我们自定义的ApplicationContext容器。
2.3 SpringApplicationRunListener
该接口中定义了如下Spring Boot在启动过程中不同阶段将会触发的事件
public interface SpringApplicationRunListener {
default void starting(ConfigurableBootstrapContext bootstrapContext) {
}
default void environmentPrepared(
ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment) {
}
default void contextPrepared(ConfigurableApplicationContext context) {
}
default void contextLoaded(ConfigurableApplicationContext context) {
}
default void started(ConfigurableApplicationContext context, Duration timeTaken) {
}
default void ready(ConfigurableApplicationContext context, Duration timeTaken) {
}
default void failed(ConfigurableApplicationContext context, Throwable exception) {
}
}
Spring Boot默认提供了 EventPublishingRunListener 实现,在该实现中针对不同的阶段都会触发相应的事件。如下自定义实现:
public class PackSpringApplicationRunListener implements SpringApplicationRunListener, Ordered {
public int getOrder() {
return 1 ;
}
public void contextPrepared(ConfigurableApplicationContext context) {
System.err.println("ApplicationContext 创建并准备好, 还没有开始调用refresh方法") ;
}
// 上下文已经被刷新,并且应用程序已经启动,但是 *Runners 尚未被调用。
public void started(ConfigurableApplicationContext context, Duration timeTaken) {
System.err.printf("上下文已经被刷新,并且应用程序已经启动,但 *Runners 尚未被调用, 应用程序启动所花费时间: %dms%n", timeTaken.toMillisPart()) ;
}
}
这里仅仅是打印了一段文字,演示效果
在META-INF/spring.factories中进行注册
\ =
com.pack.extension.eventpublisher.PackSpringApplicationRunListener
启动服务
注意:在自定义实现的SpringApplicationRunListener构造函数中,我们可以添加2个参数,分别是为
SpringApplication
该参数值就是当前main函数启动的那个实例。
String[] args
该数组参数是main函数启动时添加的命令行参数。
如下示例:
private SpringApplication app ;
private final String[] args ;
public PackSpringApplicationRunListener(SpringApplication app, String[] args) {
this.app = app ;
this.args = args ;
System.err.printf("%s%s%n", app, Arrays.toString(this.args)) ;
}
启动应用是设置如下:
java -jar App.jar --pack.title=xxxooo, --pack.version=1.0.0
输出结果
org.SpringApplication@78ac1102[--pack.title=xxxooo,, --pack.version=1.0.0]
注:目前只支持这2中数据类型。
2.4 ApplicationContextInitializer
该接口可以在Spring容器在正式刷新执行执行,此时我们可以对容器进行相应的配置管理。
public class PackApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
public void initialize(ConfigurableApplicationContext context) {
context.addApplicationListener(null) ;
context.addBeanFactoryPostProcessor(null) ;
context.getEnvironment().getConversionService().addConverter(null) ;
// ...
}
}
在该示例中,我们可以像容器中注册ApplicationListener事件监听器、BeanFactoryPostProcessor 容器后处理器,给当前Environment添加类型转换器。
在META-INF/spring.factories中进行注册
\ =
com.pack.extension.contextinitializer.PackApplicationContextInitializer
以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏
推荐文章
性能提升!@Async与CompletableFuture优雅应用
进阶!@ConfigurationProperties注解高级用法你知道吗?
掌握这3个Spring Boot技能,实时监控Controller接口性能
SpringBoot整合Flink CDC,实时追踪数据变动,无缝同步至Redis