【Spring】多环境切换
🎈博客主页:🌈我的主页🌈
🎈欢迎点赞 👍 收藏 🌟留言 📝 欢迎讨论!👏
🎈本文由 【泠青沼~】 原创,首发于 CSDN🚩🚩🚩
🎈由于博主是在学小白一枚,难免会有错误,有任何问题欢迎评论区留言指出,感激不尽!🌠个人主页
目录
- 🌟 一、Java配置
- 🌟 二、XML配置
- 🌟 三、原理分析
- 🌟 三、自定义Profile
🌟 一、Java配置
首先创建一个 DataSource 类:
public class DataSource {private String username;private String password;private String url;@Overridepublic String toString() {return "DataSource{" +"username='" + username + '\'' +", password='" + password + '\'' +", url='" + url + '\'' +'}';}
}
向 Spring 容器中注册多个 DataSource,并且在注册的时候设置 Profile,只有当条件满足的时候,才向 Spring 容器中注册相应的 Bean,否则不注册
public class JavaConfig {@Bean@Profile("dev")DataSource devDataSource(){DataSource dev = new DataSource();dev.setUsername("dev");dev.setPassword("dev");dev.setUrl("jdbc:mysql:3306/dev");return dev;}@Bean@Profile("prod")DataSource prodDataSource(){DataSource prod = new DataSource();prod.setUsername("prod");prod.setPassword("prod");prod.setUrl("jdbc:mysql:3306/prod");return prod;}}
这里到底向 Spring 容器中注册多少个 DataSource,主要还是看条件是否满足,如果有多个条件满足,那么就注册多个 DataSource 实例到 Spring 容器中,否则就不注册。
最后,启动容器:
public static void main(String[] args) {//这里注意,不能添加配置类,如果添加了配置类,则 refresh 方法会被调用,而 Spring 容器的初始化则正是从这里开始的//此时,我们还没设置当前系统环境AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();//这里注意,不能添加配置类,如果添加了配置类,则 refresh 方法会被调用,而 Spring 容器的初始化则正是从这里开始的//此时,我们还没设置当前系统环境ConfigurableEnvironment evn = ctx.getEnvironment();evn.setActiveProfiles("prod");//此时再去设置配置类ctx.register(JavaConfig.class);//开始初始化容器ctx.refresh();DataSource dataSource = ctx.getBean(DataSource.class);System.out.println(dataSource);}
启动容器的时候,一开始不要传配置类进去,如果传了,则 refresh 方法会被自动调用,而此时我们还没设置容器的环境!所以,使用无参构造方法创建 AnnotationConfigApplicationContext 对象,然后设置系统环境,再去设置配置类,最后再去初始化容器
🌟 二、XML配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><beans profile="dev"><bean class="com.dong.demo3.DataSource" ><property name="username" value="dev"/><property name="password" value="dev"/><property name="url" value="jdbc:mysql:3306/dev"/></bean></beans><beans profile="prod"><bean class="com.dong.demo3.DataSource" ><property name="username" value="prod"/><property name="password" value="prod"/><property name="url" value="jdbc:mysql:3306/prod"/></bean></beans>
</beans>
这个是在 父标签 beans 中设置条件,满足对应的条件,父标签中的所有 Bean 才会被初始化
public class XMLDemo1 {public static void main(String[] args) {ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext();ctx.getEnvironment().addActiveProfile("prod");ctx.setConfigLocation("beans1.xml");ctx.refresh();DataSource bean = ctx.getBean(DataSource.class);System.out.println(bean);}
}
🌟 三、原理分析
@Profile
注解的定义就是一个组合注解:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 从这里可以看到,本质上就是一个条件注解,条件则是 ProfileCondition
@Conditional(ProfileCondition.class)
public @interface Profile {/*** The set of profiles for which the annotated component should be registered.*/String[] value();}
那我们来看下 ProfileCondition:
class ProfileCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 这句话实际上就是查询到 Profile 注解的所有属性// 对于 Profile 注解来说,实际上就只有 value 属性// value->dev value->prodMultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());if (attrs != null) {// attrs.get("value") 表示读取属性中的 value 属性,value 属性的值是一个数组,所以这里需要遍历for (Object value : attrs.get("value")) {//判断当前系统环境中是否包含这个 valueif (context.getEnvironment().matchesProfiles((String[]) value)) {return true;}}return false;}return true;}}
🌟 三、自定义Profile
首先,先自定义注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Conditional(MyCondition.class)
public @interface MyProfile {String[] value();
}
然后自定义条件,在自定义条件中解析注解:
public class MyCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(MyProfile.class.getName());if(attrs != null){List<Object> list = attrs.get("value");for (Object value : list) {boolean b = context.getEnvironment().acceptsProfiles(Profiles.of((String[]) value));if(b){return true;}}}return false;}
}
最后使用自定义注解:
public class JavaConfig {@Bean@MyProfile("dev")DataSource devDataSource(){DataSource dev = new DataSource();dev.setUsername("dev");dev.setPassword("dev");dev.setUrl("jdbc:mysql:3306/dev");return dev;}@Bean@MyProfile("prod")DataSource prodDataSource(){DataSource prod = new DataSource();prod.setUsername("prod");prod.setPassword("prod");prod.setUrl("jdbc:mysql:3306/prod");return prod;}}
启动容器:
public static void main(String[] args) {//这里注意,不能添加配置类,如果添加了配置类,则 refresh 方法会被调用,而 Spring 容器的初始化则正是从这里开始的//此时,我们还没设置当前系统环境AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();//这里注意,不能添加配置类,如果添加了配置类,则 refresh 方法会被调用,而 Spring 容器的初始化则正是从这里开始的//此时,我们还没设置当前系统环境ConfigurableEnvironment evn = ctx.getEnvironment();evn.setActiveProfiles("prod");//此时再去设置配置类ctx.register(JavaConfig.class);//开始初始化容器ctx.refresh();DataSource dataSource = ctx.getBean(DataSource.class);System.out.println(dataSource);}
相关文章:
【Spring】多环境切换
🎈博客主页:🌈我的主页🌈 🎈欢迎点赞 👍 收藏 🌟留言 📝 欢迎讨论!👏 🎈本文由 【泠青沼~】 原创,首发于 CSDN🚩…...
python经典百题之求10000之内的素数
题目:求10000之内的素数 程序分析 求10000之内的素数是一个常见的问题。素数是大于1且只能被1和自身整除的整数。我们可以使用循环遍历10000以内的每个数,判断其是否是素数。 方法1: 简单遍历法 遍历2到10000之间的每个数,判断其是否为素…...

ROS2 从头开始:第 5 部分 - 并发、执行器和回调组
一、说明 让我们回到基础。并发意味着系统或软件可以同时运行许多任务。例如,在单核 CPU 机器上,可以通过使用线程来实现并发。本文探讨了...

笔试强训Day3
学了一坤时Linux,赶紧来俩道题目放松放松。 T1:在字符串中找出连续最长的数字串 链接:在字符串中找出连续最长的数字串__牛客网 输入一个字符串,返回其最长的数字子串,以及其长度。若有多个最长的数字子串,…...

软考软件设计师-存储管理-文件管理-计算机网络(中
文章目录 一、存储管理页面置换算法 (最佳OPT)存储页面-先进先出置换算法(FIFO)最久未使用算法(最近最久未使用LRU) 二、文件管理初识文件管理文件目录-绝对路径文件管理-文件的结构文件管理-索引的分配 空闲存储空间的管理(位示图法)三、计算…...

Vue3的学习
create-vue创建vue3项目 create-vue是官方新的脚手架工具,底层切换到了vite(下一代构建工具),为开发提供急速响应 前提环境条件:控制面板输入node -v,显示的是安装了16.0或更高版本的Node.js创建一个Vue应…...

什么是Peppol ID?如何创建?
Peppol 网络的两大优势是安全和高效,由于Peppol 最常用于电子发票,因此这些优势在电子发票上展露无遗。相比之下,通过电子邮件发送 PDF 格式的发票和其他文件不仅处理成本较高,而且容易出现发票欺诈。 如果您所在的公共部门组织或…...
Spring注解大揭秘:@Component、@Service、@Repository详解
Spring注解大揭秘:Component、Service、Repository详解 前言比较 前言 想象一下,你正在构建一个复杂的Spring应用程序。你需要管理各种不同类型的组件,包括服务层、数据访问层和通用组件。Spring的Component、Service和Repository注解就像是你…...

Innodb底层原理与Mysql日志机制
MySQL内部组件结构 Server层 主要包括连接器、词法分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,…...
浅谈大数据背景下用户侧用电数据在电力系统的应用与发展分析
安科瑞 华楠 摘要:随着能源互联网、互联网、新型传感技术的持续推进,电力用户侧用电数据呈现指数级剧增、异构性增强的情况,逐渐构成了用户侧用电行为大数据。然而目前对电力领域的数据价值挖掘于电网内部和电源端,用户侧庞大且蕴…...

20230919在WIN10下使用python3将PDF文档转为DOCX格式的WORD文档
20230919在WIN10下使用python3将PDF文档转为DOCX格式的WORD文档 2023/9/19 11:20 python pdf word https://blog.csdn.net/u013185349/article/details/130059657 Python实现PDF转Word文档 AcceptedLin 已于 2023-04-10 14:45:17 修改 1243 收藏 1 文章标签: pd…...
PCR检测试剂——博迈伦
PCR(聚合酶链式反应)是一种常用的分子生物学技术,被广泛应用于基因分型、基因表达分析、病原体检测等领域。在PCR实验中,PCR检测试剂是必不可少的重要组成部分,它们包括引物、酶、缓冲液和核苷酸。 1. 引物(…...

spring一个项目多个模块聚合打包问题解决方案
文章目录 1.问题描述:2.解决方案一、创建聚合父工程二、创建子模块(module)三、编写子模块代码1.模块1(demo-one)2.模块2(demo-tow) 四、创建聚合模块 (demo-starter)1. …...
Linux设备树(Device Tree)何时被解析
Linux设备树(Device Tree)是在内核启动阶段就会被解析。当 Linux 内核启动的时候,它会读取设备树文件(dtb文件)并根据里面的信息来组织设备、加载驱动等。在驱动代码里,通常我们是在驱动初始化(…...
【Elasticsearch】数据简单操作(二)
简介:Elasticsearch(ES)是一个开源的分布式搜索和分析引擎,用于快速存储、搜索和分析大量数据。它具有高性能、可扩展性和灵活性的特点,被广泛用于构建实时搜索、日志分析、数据可视化等应用。 本文主要介绍ES索引的操…...

4 vCPU 实例达成 100 万 JSON API 请求/秒的优化实践
“性能工程” (Performance engineering)是个日渐流行的概念。顾名思义“性能工程”是包含在系统开发生命周期中所应用的一个技术分支,其目的就是确保满足非功能性的性能需求,例如:性能、可靠性等。由于现代软件系统变…...
呼叫中心系统有什么优势
在随着企业的管理水平也在不断提高。企业经营管理中所涉及到的各种复杂问题都有逐渐凸显出来。传统的呼叫中心已无法满足企业服务需求和客户满意度变化的要求。因此通过呼叫中心系统将企业业务流程和数据整合起来进行管理和运营已经成为目前企业管理领域中较为流行和成熟之选。…...

如何在linux操作系统下安装nvm
本文主要介绍如何在linux操作系统下安装nvm,如果想知道nvm如何在windows操作系统下使用,请参考文章如何通过nvm管理多个nodejs版本_nvm 查看所有node版本-CSDN博客。 1、nvm下载 nvm全称Node Version Manager,即Node版本管理器。访问官网地址…...

Linux 入门:基本指令
本篇文章来介绍我们在初学Linux时可以会碰倒的一些基本指令,让我们对这些指令有一个基本的了解。 目录 01. ls 指令 02. pwd 命令 03. cd 指令 04. touch 指令 05. mkdir 指令(重要) 06. rmdir指令 && rm 指令(重…...

IP转地理位置:探讨技术与应用
IP地址是互联网上设备的唯一标识符,而将IP地址转换为地理位置信息是网络管理、安全监控和市场定位等领域中的一项重要任务。本文将深入探讨IP转地理位置的技术原理和各种应用场景。 IP地址与地理位置 IP地址(Internet Protocol Address)是一…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...

以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...

人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...

免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...