玩转SpringBoot:动态排除Starter配置,轻松部署
引言
在软件开发中,进行本地单元测试是一项常规且必要的任务。然而,在进行单元测试时,有时需要启动一些中间件服务,如Kafka、Elasticjob等。举例来说,我曾经遇到过一个问题:项目中使用了Redisson
锁,但由于Redisson
版本较低,在Mac环境下偶尔会报错# RedisConnectionException: Unable to init enough connections amount
。鉴于升级版本带来的风险,以及问题仅在本地启动时出现,我决定在本地环境中排除Redisson
的Starter,从而避免影响其他环境的配置。那么,我们应该如何做呢?
我们以上篇介绍如何自定义Starter中的文章中示例
CoderAcademyStarter
为例。我们引入了这个starter。
Starter自动配置类的排除
在《SpringBoot如何自定义Starter》中,我们介绍了如何在META-INF/spring.factories
文件中使用org.springframework.boot.autoconfigure.EnableAutoConfiguration
来指定Starter的自动配置类。Spring Boot启动时会扫描所有已引入jar包中的spring.factories
文件,并根据EnableAutoConfiguration
键下的类来加载和执行相应的自动配置逻辑。当我们不希望应用启动时使用该Starter的功能时,就需要排除自动配置类。
我们可以通过spring.autoconfigure.exclude
属性排除CoderAcademyStarter
的自动配置类:
spring.autoconfigure.exclude=com.springboot.starter.coderacademy.config.CoderAcademyAutoConfig
spring.autoconfigure.exclude
是Spring Boot中的一个属性,用于指定在自动配置过程中要排除的自动配置类。通过设置该属性,我们可以明确告知Spring Boot不要自动配置指定的类,即使它们满足自动配置的条件。当需要禁用特定的自动配置类时,可以在application.properties
或application.yml
中设置spring.autoconfigure.exclude
属性,并提供要排除的自动配置类的完全限定类名。这样,Spring Boot在自动配置过程中将不会考虑这些类。
此时,如果我们在使用CoderAcademyService
时会出现错误:
根据不同环境排除Starter自动配置类
在日常开发中,我们通常需要针对不同的环境指定不同的配置。我们可以通过spring.actice.profiles
属性来指定不同环境的配置文件的加载。例如,我们可以在本地指定spring.actice.profiles=local
,然后创建一个application-local.properties
的配置文件,在其中指定spring.autoconfigure.exclude
。
另外,我们还可以实现ApplicationListener<ApplicationContextInitializedEvent>
接口,通过监听上下文初始化事件来根据环境变量的标识排除Starter的自动配置类。当Spring应用程序的ApplicationContext
被初始化时,将触发ApplicationContextInitializedEvent
事件。通常,在应用程序的上下文初始化过程中会先加载bean定义、执行后处理器等操作。因此,通过监听ApplicationContextInitializedEvent
事件,我们可以在Spring容器初始化的早期阶段执行一些定制化的逻辑。
我们可以通过实现ApplicationListener<ApplicationContextInitializedEvent>
接口,根据一些环境变量的标识排除Starter的自动配置类。例如,我们可以定义一个coderacademy.enable
的标识来决定是否扫描Starter。以下是一个示例:
import org.springframework.boot.context.event.ApplicationContextInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
@Configuration
public class EnvironmentHandler implements ApplicationListener<ApplicationContextInitializedEvent> {
@Override
public void onApplicationEvent(ApplicationContextInitializedEvent event) {
ConfigurableEnvironment environment = event.getApplicationContext().getEnvironment();
if (environment.getProperty("coderacademy.enable") != null && "false".equals(environment.getProperty("coderacademy.enable"))) {
System.setProperty("spring.autoconfigure.exclude", "com.springboot.starter.coderacademy.config.CoderAcademyAutoConfig");
}
}
}
然后,在启动应用时,通过-Dcoderacademy.enable=false
指定排除Starter的自动配置类。这种方式特别适用于本地启动应用时排除Starter或其他Bean的初始化。
当然本地启动也可以直接通过-Dspring.autoconfigure.exclude=com.springboot.starter.coderacademy.config.CoderAcademyAutoConfig
也可以满足排除Starter的配置。
自定义Starter Bean排除
在《SpringBoot如何自定义Starter》文中,我们还提到了一种调用方使用Starter的方式,我们可以不是用自动配置类的Starter,可以自定义配置的信息,在手动创建Starter对应的服务的Bean。例如:
@Data
@Configuration
public class StarterConfig {
@Value("${springboot.coderacademy.name}")
private String staterMsg;
@Bean
public CoderAcademyService coderAcademyService(){
CoderAcademyConfig coderAcademyConfig = new CoderAcademyConfig();
coderAcademyConfig.setUrl(staterMsg);
return new CoderAcademyService(coderAcademyConfig);
}
}
对于这种情况,我们可以使用Spring Boot的注解@ConditionalOnProperty
来控制是否创建Bean。@ConditionalOnProperty
是一个条件注解,根据配置属性的值来决定是否应该创建一个Bean或应用某个配置。具体来说,@ConditionalOnProperty
的name
属性表示配置属性的名称,havingValue
属性表示配置属性的期望值,默认为true
,matchIfMissing
属性表示当配置属性不存在时是否匹配条件,默认为false
。
因此,我们可以给CoderAcademyService
的Bean添加@ConditionalOnProperty
注解:
@Data
@Configuration
public class StarterConfig {
@Value("${springboot.coderacademy.name}")
private String staterMsg;
@ConditionalOnProperty(name = "coderacademy.enable", havingValue = "true", matchIfMissing = true)
@Bean
public CoderAcademyService coderAcademyService(){
CoderAcademyConfig coderAcademyConfig = new CoderAcademyConfig();
coderAcademyConfig.setUrl(staterMsg);
return new CoderAcademyService(coderAcademyConfig);
}
}
这样,我们在启动应用时可以通过-Dcoderacademy.enable=false
变量来控制是否创建CoderAcademyService
,而设置了matchIfMissing=true
,即使其他环境没有该环境变量也不受影响。
除了@ConditionalOnProperty
之外,Spring Boot还提供了其他一些条件注解,用于根据不同的条件来决定是否应该创建Bean或者是否应该应用某个配置。一些常见的条件注解包括:
@ConditionalOnClass
:当类路径中存在指定的类时,才会创建Bean或应用配置。@ConditionalOnMissingClass
:当类路径中不存在指定的类时,才会创建Bean或应用配置。@ConditionalOnBean
:当容器中存在指定的Bean时,才会创建Bean或应用配置。@ConditionalOnMissingBean
:当容器中不存在指定的Bean时,才会创建Bean或应用配置。@ConditionalOnExpression
:当满足SpEL表达式定义的条件时,才会创建Bean或应用配置。@ConditionalOnJava
:当JVM运行的Java版本符合指定条件时,才会创建Bean或应用配置。@ConditionalOnWebApplication
:当运行的环境是Web应用程序时,才会创建Bean或应用配置。@ConditionalOnNotWebApplication
:当运行的环境不是Web应用程序时,才会创建Bean或应用配置。
总结
本文介绍了在Spring Boot项目中如何排除Starter自动配置类,以及根据不同环境动态排除配置的方法。通过spring.autoconfigure.exclude
属性和条件注解如@ConditionalOnProperty
,我们可以灵活控制Bean的创建和配置的应用,从而更好地适应不同的部署环境和需求。
本文已收录于我的个人博客:码农Academy的博客,专注分享Java技术干货,包括Java基础、Spring Boot、Spring Cloud、Mysql、Redis、Elasticsearch、中间件、架构设计、面试题、程序员攻略等
玩转SpringBoot:动态排除Starter配置,轻松部署的更多相关文章
- 【玩转SpringBoot】给自动配置来个整体大揭秘
上一篇文章中提到的条件注解,只是自动配置整体解决方案中的一个环节而已,可以说是管中窥豹. 本文就逐步擦除迷雾,让整体浮现出来,这样就会有一个宏观的认识. 除了写代码之外,还能干点什么? 提到“配置”这 ...
- 【玩转SpringBoot】异步任务执行与其线程池配置
同步代码写起来简单,但就是怕遇到耗时操作,会影响效率和吞吐量. 此时异步代码才是王者,但涉及多线程和线程池,以及异步结果的获取,写起来颇为麻烦. 不过在遇到SpringBoot异步任务时,这个问题就不 ...
- 【玩转SpringBoot】看似复杂的Environment其实很简单
喜欢写代码,讨厌配环境 我相信这十个字的小标题代表了大多数码农的心声. 十年前读大学时,学校开设了C语言还有C++.但是学习这两种语言,对于新手来说非常没有成就感. 于是我就在校门口买个光盘,装个VS ...
- 【玩转SpringBoot】翻身做主人,一统web服务器
寄人篱下的日子 一直以来受传统影响,我们的web工程总是打成war包,然后放入tomcat的webapps目录下面. 如下图01: 当tomcat启动时,会去解压war包,然后运行web工程.这大家都 ...
- 【玩转SpringBoot】让错误处理重新由web服务器接管
其实web服务器是会处理错误的 在web.xml还是随处可见的年代时(确实有点老黄历了),下面的这些配置应该都不陌生. 根据错误代码处理错误,如下图01: 根据异常类型处理错误,如下图02: 不过我们 ...
- 【玩转SpringBoot】通过事件机制参与SpringBoot应用的启动过程
生命周期和事件监听 一个应用的启动过程和关闭过程是归属到“生命周期”这个概念的范畴. 典型的设计是在启动和关闭过程中会触发一系列的“事件”,我们只要监听这些事件,就能参与到这个过程中来. 要想监听事件 ...
- 【玩转SpringBoot】SpringBoot应用的启动过程一览表
SpringBoot应用的启动方式很简单,就一行代码,如下图01: 其实这行代码背后主要执行两个方法,一个是构造方法,一个是run方法. 构造方法主要内容就是收集一些数据,和确认一些信息.如下图02: ...
- 【玩转SpringBoot】用好条件相关注解,开启自动配置之门
自动配置隐含两层含义,要搞清楚 上帝让程序员的发量减少,是为了让他变得更聪明,如果有一天聪明到了极点,那就是绝顶聪明. 据说在大脑高速运转下,这样更有利于散热,不至于核心温度过高而产生告警. 聪明的大 ...
- SpringBoot 动态配置邮箱发件人
SpringBoot 动态配置邮箱发件人 现在的消息模块少不了邮件发送.短信发送和手机推送的功能.邮件发送的功能历史最为悠久,也算的上烂大街的功能.一般在配置文件中设置好邮箱地址.账号.密码和发件服务 ...
- SpringBoot集成Mybatis(0配置注解版)
Mybatis初期使用比较麻烦,需要各种配置文件.实体类.dao层映射关联.还有一大推其它配置.当然Mybatis也发现了这种弊端,初期开发了generator可以根据表结构自动生成实体类.配置文件和 ...
随机推荐
- [转帖]高并发下nginx配置模板
user web; # One worker process per CPU core. worker_processes 8; # Also set # /etc/s ...
- [转帖]一文说清 Linux System Load
https://zhuanlan.zhihu.com/p/447661302 双十一压测过程中,常见的问题之一就是load 飙高,通常这个时候业务上都有受影响,比如服务rt飙高,比如机器无法登录,比如 ...
- [转帖]ls 只显示目录
https://www.cnblogs.com/lavin/p/5912369.html 只显示目录: ls -d */ 在实际应用中,我们有时需要仅列出目录,下面是 4 种不同的方法. 1. 利用 ...
- [转帖]5. Tikv安装部署
5. Tikv安装部署 5.1. 概述 TiDB 是 PingCAP 公司自主设计.研发的开源分布式关系型数据库,是一款同时支持在线事务处理与在线分析处理 (Hybrid Transactiona ...
- [转帖]【Redis】Redis中使用Lua脚本
Lua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能. Lua具体语法参考:https://www.runoob. ...
- [转帖]010 Linux 文本统计与去重 (wc 和 uniq)
https://my.oschina.net/u/3113381/blog/5427461 wc 命令一般是作为组合命令的一员与其他命令一同起到统计的作用.而一般情况下使用 wc -l 命令较多. u ...
- 在线获取所有依赖rpm包的方法
背景 现在经常有一些不能上网的LInux机器但是需要安装一些软件. 但是有时候经常因为有依赖关系找不到的情况比较麻烦. 或者是一些公司的网络总是受限,网络速度非常慢. 下载安装非常折磨人. 这个时候就 ...
- 学习React中的jsx-保证你看的明明白白
安装react的脚手架 1==>行 npx create-react-app myreactdemo01 解释一下: npx create-react-app 你的项目名称 npx create ...
- golang 中使用 writev (sendmsg) 系统调用来一次发送多块数据
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 writev,或者说 sendmsg 等系统调用,能够发送 ...
- NetCore高级系列文章01---创建项目及配置文件
.NET Core是适用于 Windows.Linux 和 macOS 的免费.开源托管的计算机软件框架,作为.NET开发人员,全面拥抱.NetCore将成为趋势. 本系列文章将分为两大部分讲解.Ne ...