SpringBoot 中的 3 种条件装配!


一、介绍

在实际的项目开发中,我们往往需要根据不同的环境做出不同的配置,例如:在开发环境下,我们会使用内存数据库以便快速启动服务并进行开发调试,在test环境、生产环境,会使用对应环境的数据库。

如果我们的应用程序可以根据自身的环境做一些这样的适配,那么我们的程序开发无疑将更加灵活、高效。

在过去的应用程序开发中,我们常常会将这些环境变量写在某个指定的配置文件中,每次服务器启动的时候,会读取服务器中指定的配置文件,从而实现根据不同的环境,应用程序能做出对应的适配。

但是这样的工作,对于运维来说,非常苦逼,尤其是应用程序到达50个以上的时候,会非常不好维护,每次上线改配置,全靠人肉,想想都觉得反人类~

当我们在使用SpringBoot来开发应用程序的时候,这些工作量将大大简化。

SpringBoot为开发者提供了三种可选的条件装配方式。

  • Profile

  • Conditional

  • ConditionalOnProperty

下面,我们一起来了解一下具体的应用实践。

二、程序实践

2.1、Profile

SpringBoot 为应用程序提供了Profile这一概念,用来表示不同的环境。例如,我们分别定义开发、测试和生产这3个环境

  • dev:开发环境

  • test:测试环境

  • production:生产环境

以上传文件为例,在开发环境下,我们将文件上传到本地,而在测试环境、生产环境,我们将文件上传到云端服务商。

1、首先编写两套上传服务

/*** 上传文件到本地* @since 2021-06-13*/
public class FileUploader implements Uploader {@Overridepublic String upload(File file) {//上传文件到本地,并返回绝对路径return null;}
}
/*** 上传文件到OSS* @since 2021-06-13*/
public class OSSUploader implements Uploader {@Overridepublic String upload(File file) {//上传文件到云端,并返回绝对路径return null;}
}

2、然后编写一个服务配置类,根据不同的环境,创建不同的实现类

@Configuration
public class AppConfig {@Bean@Profile("dev")public Uploader initFileUploader() {System.out.println("初始化一个上传到本地的bean");return new FileUploader();}@Bean@Profile("!dev")public Uploader initOSSUploader() {System.out.println("初始化一个上传到云端的bean");return new OSSUploader();}}

3、最后,运行程序

在运行程序时,加上JVM参数-Dspring.profiles.active=dev就可以指定以dev环境启动。

如果当前的Profile设置为dev,则Spring容器会调用initFileUploader()创建FileUploader,否则,调用initOSSUploader()创建OSSUploader

注意:@Profile("!dev")表示非dev环境。

当然,你还可以在application.properties文件中加上如下配置,一样可以指定环境进行运行。

spring.profiles.active=dev

2.2、Conditional

除了可以根据@Profile条件来决定是否创建某个Bean外,Spring还可以根据@Conditional决定是否创建某个Bean

以发短信为例,在生产环境,我们会提供发短信服务,而在其他环境,我们不会向运营商发短信。

1、创建一个条件配置类SMSEnvCondition

public class SMSEnvCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {return "true".equalsIgnoreCase(context.getEnvironment().getProperty("enable.sms"));}
}

2、创建一个发短信的服务

@Component
@Conditional(SMSEnvCondition.class)
public class SendMessageService {//...
}

3、在application.properties文件中,添加配置变量enable.sms

enable.sms=true

enable.smstrue的时候,会创建SendMessageService对象,否则不创建。

2.3、ConditionalOnProperty

Spring提供的条件装配@Conditional,灵活性非常强,但是具体判断逻辑还需要我们自己实现,比较麻烦。

实际上,Spring Boot为开发者提供了很多使用起来更简单的条件注解,例如:

  • ConditionalOnProperty:如果有指定的配置,条件生效

  • ConditionalOnBean:如果有指定的Bean,条件生效

  • ConditionalOnMissingBean:如果没有指定的Bean,条件生效

  • ConditionalOnMissingClass:如果没有指定的Class,条件生效

  • ConditionalOnWebApplication:在Web环境中条件生效

  • ConditionalOnExpression:根据表达式判断条件是否生效

我们以最常用的@ConditionalOnProperty注解为例,将上面的代码改成如下方式即可实现按照条件进行加载。

@Component
@ConditionalOnProperty(name="enable.sms", havingValue="true")
public class SendMessageService {//...
}

enable.sms的值等于true时,会实例化SendMessageService对象;反之,不会创建对象。

是不是超级简单~~~

当然@ConditionalOnProperty的参数还不仅仅限于此,以上面上传文件为例,在开发环境,我们总是上传到本地;在测试环境、生产环境,我们将文件上传到云端,改造过程如下:

@Component
@ConditionalOnProperty(name = "file.storage", havingValue = "file", matchIfMissing = true)
public class FileUploader implements Uploader {@Overridepublic String upload(File file) {//上传文件到本地,并返回绝对路径return null;}
}
@Component
@ConditionalOnProperty(name = "file.storage", havingValue = "oss")
public class OSSUploader implements Uploader {@Overridepublic String upload(File file) {//上传文件到云端,并返回绝对路径return null;}
}

file.storage配置值为file,会加载FileUploader类;当file.storage配置值为oss,会加载OSSUploader类。

其中@ConditionalOnProperty中的matchIfMissing参数表示,当没有找到对应配置参数时,会默认加载当前类,也就是FileUploader类。

三、小结

虽然,@Profile@Conditional@ConditionalOnProperty三个注解都能实现按照条件进行适配,但是@Profile注解控制比较粗糙,很难实现精细化控制。

在实际的使用过程中,使用最多的是@Conditional@ConditionalOnProperty,可以很灵活的实现条件装配。

其中,@ConditionalOnProperty@Conditional的一种具体扩展实现,提供了很多非常实用的操作,在使用中,推荐大家使用@ConditionalOnProperty

如果不够,可以根据@Conditional条件装配,编写一套控制开关实现类。

四、参考

1、廖雪峰-使用条件装配


往期推荐

SpringBoot 过滤器、拦截器、监听器对比及使用场景!


Spring为什么建议构造器注入?


11个小技巧,玩转Spring!



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/544714.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图说 mysql 事务隔离级别

转载于:https://blog.51cto.com/kingbox/1657916

@Autowired报错的4种解决方案和原因分析!

作者 | 王磊来源 | Java中文社群(ID:javacn666)转载请联系授权(微信ID:GG_Stone)上图的报错信息相信大部分程序员都遇到过,奇怪的是虽然代码报错,但丝毫不影响程序的正常执行&#x…

C# Winform 窗体美化(一、IrisSkin 换肤库)

IrisSkin 换肤库 IrisSkin 是为Microsoft Visual Studio dotNET开发的最易用的界面增强dotNET(WinForm)组件包。能完全自动的为应用程序添加支持换肤功能。[百度百科] 1、文件 IrisSkin4.dll - 544 KB各种 .ssk 格式的皮肤文件(一般在网上搜的是13个皮肤的压缩包…

厉害了,Spring中bean的12种定义方法!

前言在庞大的java体系中,spring有着举足轻重的地位,它给每位开发者带来了极大的便利和惊喜。我们都知道spring是创建和管理bean的工厂,它提供了多种定义bean的方式,能够满足我们日常工作中的多种业务场景。那么问题来了&#xff0…

C# Winform 窗体美化(二、LayeredSkin 界面库)

二、LayeredSkin 界面库 概况 这部分资源是 Winform 美化最多的了,效果还不错,使用时只需引入 LayeredSkin.dll - 696 KB 即可。 网上能找到的最后 LayeredSkin 版本应该是 LayeredSkin Demo2014-12-10.zip,之后作者就整合成一个更加强大的…

【WebSocket初探 】

众所周知,socket是编写网络通信应用的基本技术,网络数据交换大多直接或间接通过socket进行。对于直接使用socket的client与服务端,一旦连接被建立则均可主动向对方传送数据,而对于使用更上层的HTTP/HTTPS协议的应用,因…

Spring Cache 实战:兼容所有缓存中间件!

作者 | 悟空聊架构来源 | 悟空聊架构(ID:PassJava666)本篇给大家介绍一种兼容所有缓存中间件的方案,不论我们是使用 Redis 还是 Ehcache,都不需要关心如何操作 Redis 或者 Ehcache,这套方案统统帮你搞定。这…

C# Winform 窗体美化(三、不规则窗体)

三、不规则窗体 概况 之前学习的 LayeredSkin 看到里面有个异形窗口,比较感兴趣,所以就找一下资料研究一下。不规则窗体学习有一个比较好的例子,叫 GoldFishProject,是一条鱼金鱼在屏幕上游。 不规则窗口示例代码 GoldFishProj…

Mybatis中SQL注入攻击的3种方式,真是防不胜防!

作者 | sunnyf来源 | https://www.freebuf.com/vuls/240578.html前言SQL注入漏洞作为WEB安全的最常见的漏洞之一,在java中随着预编译与各种ORM框架的使用,注入问题也越来越少。新手代码审计者往往对Java Web应用的多个框架组合而心生畏惧,不知…

Hadoop源代码分析(MapReduce概论)

大家都熟悉文件系统,在对HDFS进行分析前,我们并没有花很多的时间去介绍HDFS的背景,毕竟大家对文件系统的还是有一定的理解的,而且也有很好的文档。在分析Hadoop的MapReduce部分前,我们还是先了解系统是如何工作的&…

再有人问你MySql的隔离级别,直接把这篇文章发给他!

作者 l zyz1992来源 l Hollis(ID:hollischuang)首先要明白什么是事务?事务是程序中一系列严密的操作,所有的操作必须完成,否则在所有的操作中所做的所有的更改都会被撤销。也就是事务的原子性,一…

生产环境一次诡异的NPE问题,反转了4次

前言公司为了保证系统的稳定性,加了很多监控,比如:接口响应时间、cpu使用率、内存使用率、错误日志等等。如果系统出现异常情况,会邮件通知相关人员,以便于大家能在第一时间解决隐藏的系统问题。此外,我们这…

ZooKeeper学习笔记—配置管理

为什么80%的码农都做不了架构师?>>> 最近在工作中,为了完善公司集群服务的架构,提高可用性,降低运维成本,因此开始学习ZooKeeper。 至于什么是ZooKeeper?它能做什么?如何安装ZooKee…

C# Winform 窗体美化(六、双层窗体)

六、双层窗体 大概情况 双层床体是为了平滑的创建异形窗体的一个解决方案,找了很多资料,整理了一下。 双层窗体的逻辑是建立在 UpdateLayeredWindow 不能绘制控件的基础上,上层再添加一个专门放置控件的层;这样就可以在上层“控…

批处理框架 Spring Batch 这么强,你会用吗?

来源:blog.csdn.net/topdeveloperr/article/details/84337956spring batch简介Spring Batch架构介绍Spring Batch核心概念介绍chunk 处理流程批处理操作指南spring batch简介 spring batch是spring提供的一个数据处理框架。企业域中的许多应用程序需要批量处理才能在…

Android Bundle类别

即使在今天发现自己Bundle类不明确,因此,花时间去研究了一下。 依据google官方文件(http://developer.android.com/reference/android/os/Bundle.html) Bundle类是一个key-value对,“A mapping from String values to …

C# Winform 窗体美化(七、Win7 Aero 毛玻璃效果)

七、Win7 Aero 毛玻璃效果 在 Win7 上有一种 Aero 效果,毛玻璃透明效果,搭配不同风格的颜色,效果很好。在学习 Winform 美化的时候顺便看到的这种效果,也整理进来了。 注意:Win7 上想看到这种效果需要开启并使用 Aer…

非导向传输媒体| 计算机网络

Transmission media can be categorized in two ways, 传输媒体可以通过两种方式进行分类: Guided Transmission Media 引导传输媒体 Unguided Transmission Media 非引导传输媒体 1)非引导传输媒体 (1) Unguided Transmission Media) It is also called wireless …

面霸篇:MQ 的 5 大关键问题详解

最近mq越来越火,很多公司在用,很多人在用,其重要性不言而喻。但是如果我让你回答下面的这些问题:我们为什么要用mq?引入mq会多哪些问题?如何解决这些问题?你心中是否有答案了呢?本文…

C# Winform 窗体美化(八、Icon)

八、Icon 之前 Winform 项目也有在 Icon 上遇到些问题(这里的 Icon 指的是 .ico 类型的文件),比如刚开始不知道怎么让自己的程序 Icon 和其他软件一样可以放大,还有放大之后在音量合成器中会出现比较奇葩的效果之类的问题&#x…