Spring @Profile注解详解

news/2025/3/22 13:07:04/文章来源:https://www.cnblogs.com/euler-blog/p/18786434

Spring @Profile注解详解

一、基本概念

@Profile注解用于在不同环境下启用不同的Bean或配置类。它允许我们根据当前激活的profile来决定哪些Bean应该被创建,哪些不应该被创建。

二、基本使用

1. 在配置类上使用

@Configuration
@Profile("dev")
public class DevConfig {@Beanpublic DataSource dataSource() {return DataSourceBuilder.create().url("jdbc:mysql://localhost:3306/dev_db").username("dev").password("dev123").build();}
}@Configuration
@Profile("prod")
public class ProdConfig {@Beanpublic DataSource dataSource() {return DataSourceBuilder.create().url("jdbc:mysql://prod-server:3306/prod_db").username("prod").password("prod123").build();}
}

2. 在Bean方法上使用

@Configuration
public class AppConfig {@Bean@Profile("dev")public EmailService mockEmailService() {return new MockEmailService();}@Bean@Profile("prod")public EmailService realEmailService() {return new RealEmailService();}
}

3. 在组件类上使用

@Service
@Profile("dev")
public class DevServiceImpl implements MyService {// 开发环境实现
}@Service
@Profile("prod")
public class ProdServiceImpl implements MyService {// 生产环境实现
}

三、Profile的激活方式

1. 配置文件方式

# application.yml
spring:profiles:active: devgroup:dev: dev-db, dev-mqprod: prod-db, prod-mq

2. 命令行方式

java -jar app.jar --spring.profiles.active=dev

3. 编程方式

@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication app = new SpringApplication(Application.class);app.setAdditionalProfiles("dev");app.run(args);}
}

四、Profile的实现原理

1. 核心类和接口

// Spring的核心接口和类
public interface Environment extends PropertyResolver {String[] getActiveProfiles();String[] getDefaultProfiles();boolean acceptsProfiles(Profiles profiles);
}public interface ConfigurableEnvironment extends Environment {void setActiveProfiles(String... profiles);void addActiveProfile(String profile);void setDefaultProfiles(String... profiles);
}// Profile条件判断
public class ProfileCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 获取@Profile注解的值MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());if (attrs != null) {String[] profiles = (String[]) attrs.getFirst("value");// 检查是否匹配当前激活的profilereturn context.getEnvironment().acceptsProfiles(Profiles.of(profiles));}return true;}
}

2. 注解处理过程

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile {String[] value();
}

3. 配置处理过程

public class AnnotationConfigApplicationContext extends GenericApplicationContext {private final AnnotatedBeanDefinitionReader reader;public AnnotationConfigApplicationContext() {this.reader = new AnnotatedBeanDefinitionReader(this);// 注册配置类}@Overrideprotected void prepareRefresh() {// 准备EnvironmentConfigurableEnvironment env = getEnvironment();// 配置激活的profiles}
}

五、高级用法

1. 组合Profile

@Configuration
public class MultiProfileConfig {@Bean@Profile({"dev", "test"})public DataSource devTestDataSource() {return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();}@Bean@Profile("!dev & !test")public DataSource productionDataSource() {// 生产环境数据源return new DriverManagerDataSource();}
}

2. Profile表达式

@Configuration
public class ProfileExpressionConfig {@Bean@Profile("dev | test")    // dev或test环境public SecurityConfig devSecurityConfig() {return new DevSecurityConfig();}@Bean@Profile("prod & !eu")    // 生产环境但不是欧盟区public SecurityConfig prodSecurityConfig() {return new ProdSecurityConfig();}
}

3. 默认Profile

@Configuration
public class DefaultProfileConfig {@Bean@Profile("default")    // 当没有激活的profile时使用public DataSource defaultDataSource() {return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();}
}

六、实际应用示例

1. 多环境配置管理

@Configuration
public class MultiEnvironmentConfig {@Bean@Profile("dev")public LoggingService devLogging() {return new DetailedLoggingService();}@Bean@Profile("prod")public LoggingService prodLogging() {return new MinimalLoggingService();}@Bean@Profile("dev")public CacheConfig devCache() {return new LocalCacheConfig();}@Bean@Profile("prod")public CacheConfig prodCache() {return new DistributedCacheConfig();}
}

2. 测试配置

@SpringBootTest
@ActiveProfiles("test")
public class ServiceTest {@Autowiredprivate MyService service;@Testpublic void testWithTestProfile() {// 使用测试环境的配置进行测试}
}

3. 条件化配置

@Configuration
public class ConditionalConfig {@Bean@Profile("dev")@ConditionalOnProperty(name = "debug", havingValue = "true")public DebugService debugService() {return new DebugServiceImpl();}@Bean@Profile("prod")@ConditionalOnClass(name = "com.amazonaws.services.s3.AmazonS3")public StorageService s3StorageService() {return new S3StorageService();}
}

Profile注解的处理过程:

  1. Spring容器启动时,首先准备Environment
  2. 读取配置文件和命令行参数,确定激活的profiles
  3. 在处理@Configuration类时,通过ProfileCondition检查@Profile注解
  4. 根据当前激活的profiles决定是否创建相应的Bean
  5. 在整个应用生命周期中维护profile状态

使用建议:

  1. 合理规划profile的粒度
  2. 使用有意义的profile名称
  3. 避免过度使用profile
  4. 提供合适的默认配置
  5. 记录profile的使用文档

通过正确使用@Profile注解,可以实现灵活的环境配置管理,提高应用的可维护性和部署效率。

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

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

相关文章

什么是RabbitMQ入门

一.什么是RabbitMQ 中间件(Middleware)是处于操作系统和应用程序之间的软件,也有人认为它应该属于操作系统中的一部分。人们在使用中间件时,往往是一组中间件集成在一起,构成一个平台(包括开发平台和运行平台),但在这组中间件中必须要有一个通信中间件,即中间件=平台+…

使用BL0937 IC进行交流电源监控

一个简单的电路来监测交流电源,接线板可以插在任何地方,显示电压,电流和功率。交流电源监控是当今物联网相关应用中的一个惊人功能,例如智能风扇,开关和板。一些优秀的公司董事会在他们的产品中实施了这项技术,并持续监控供应的输出功率。在本地设备层面监控电源有其自身…

20244224 实验一《Python程序设计》实验一报告

课程:《Python程序设计》 班级: 2442 姓名: 旦曾央京 学号:20244224 实验教师:王志强 实验日期:2025年3月18日 必修/选修: 公选课 1.实验内容 1.熟悉Python开发环境; 2.练习Python运行、调试技能; 3.编写程序,练习变量和类型、字符串、对象、缩进和注释等; 4.编…

【智慧构造题】CF1427E Xum

我们发现这个原数为奇数的条件比较神秘,于是我们考虑每次把这个数字第一位 \(1\) 给干了。 考虑怎么构造。 令 $d=\lfloor \log_2 x \rfloor $ 令 \(x=1abc1\) \(x1=1abc10000\) \(x2=1abc0abc1\) \(x3=x2+x1=1abc01abc1\) \(x4=x ⊕ x3=1abc000000\) \(x5=x1+x1=1abc100000…

DataGrip结果运行在代码区域

DataGrip运行过后发现运行的结果在代码区域解决方式进入设置界面 点击左上角File(文件)->settings(设置) 搜索栏输入results或output and results 找到下面的设置界面 找到Results下的 Show results in editor ,取消勾选

我们接着创建项目中的app

在pycharm中运行以下代码python manage.py startapp teslaapp运行后呢会在目录中在创建一个名字叫teslaapp的包接着我们还需要在项目Tesla包中的setting文件中 添加我们刚创建的app名称

CMU_15445_Project4_BonusTask_Serializable_Verification

Serializable Verification 我们知道 MVCC 并不能解决幻读以及写偏差的问题, 仅通过 MVCC 的事务调度是无法保证数据库引擎的 ACID 原则的, 那么为了保证数据库的 ACID 原则, 即使在调度的过程中无法保证, 可以通过在 Commit 的时候, 通过验证, Abort 可能造成写偏差于幻读的事…

使用低代码平台设计UI

由于自己不是专业的设计师,就自己简单画个UI界面,那么就可以用到下面的低代码平台 http://120.92.142.115:81/vform3/ 里面可以选择体验vue3模板 进入下面图中的设计界面可以自己拖动组件 修改组件展示给用户的标签名称 以及数据传输时发送的字段名称 可以设置是否必填 默认值…

使用 Hosting 构建 WPF 程序 - prism 篇

WPF + .NET Generic Host + Prism + CommunityToolkit.Mvvm在 使用 Hosting 构建 WPF 程序 - Stylet 篇 中,使用 Hosting + Stylet 的方式,构建了一个 WPF 框架, 本文用于记录使用 .NET Generic Host + Prism 构建 WPF 所需的修改,仅供参考。 示例代码:Jasongrass/Demo.Ap…

如何构建一个用于3D扫描的电动转台

在这个项目中,我将向您展示如何构建一个用于3D扫描的电动转台。这个DIY项目由三个主要部分组成:顶板、中央齿轮驱动板和底座。顶板保持静止,作为放置待扫描物体的平台。在设计的核心,中间板的特点是一个内部齿轮机构,隐藏在视线之外,这是由一个步进电机驱动。这个齿轮板旋…

【每日一题】20250322

【每日一题】 1.(18分) \(\hspace{0.7cm}\)I.(5分)根据单摆周期公式 \(\displaystyle T=2\pi\sqrt{\frac{l}{g}}\),可以通过实验测量当地的重力加速度.如图 \(1\) 所示,将细线的上端固定在铁架台上,下端系一小钢球,就做成了单摆.\(\hspace{0.7cm}\)(1)用游标卡尺测…

Git 和 GitHub 笔记

笔记说明 该笔记记录所有我使用 Git 和 GitHub 过程中遇到的、觉得需要记录的事情。复杂的问题按需抽出来单独称为一篇笔记,换成博客链接。 修改远程仓库名字后,本地仓库做什么处理? git remote -v git remote set-url origin https://github.com/用户名/新仓库名.git or gi…