@Profile 可精准控制 Bean 或配置类按环境加载,避免资源浪费与误加载;支持单个 Bean(如不同数据源)或整组 Bean(如云 SDK)的环境隔离,并需配合 application-{profile}.yml 实现配置与 Bean 双重绑定。

直接用 @Profile 标注 Bean 或配置类,让 Spring 容器只加载当前激活环境对应的 Bean,而不是靠 if 判断选逻辑——这样既节省资源,又避免误加载。
在 @Bean 方法上加 @Profile
最常用、最灵活的方式。适合单个 Bean 有明显环境差异的场景,比如不同环境用不同数据源或 SDK 客户端:
- 开发环境用 H2 内存数据库:@Bean @Profile("dev") public DataSource h2DataSource() { ... }
- 测试环境连测试 MySQL:@Bean @Profile("test") public DataSource testMysqlDataSource() { ... }
- 生产环境用连接池+读写分离配置:@Bean @Profile("prod") public DataSource prodDataSource() { ... }
- 多个环境共用同一套逻辑(如 dev 和 test 都用 mock 支付):@Bean @Profile({"dev", "test"}) public PaymentService mockPaymentService() { ... }
在 @Configuration 类上加 @Profile
适合一组强关联 Bean 整体按环境切换,比如整套阿里云 SDK 初始化(含 endpoint、region、凭证等):
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 开发环境用本地模拟客户端:@Configuration @Profile("dev") public class AliyunDevClientConfig { @Bean public IAcsClient acsClient() { ... } }
- 生产环境走真实 VPC 终端节点:@Configuration @Profile("prod") public class AliyunProdClientConfig { @Bean public IAcsClient acsClient() { ... } }
- 注意:类上加了 @Profile,里面所有 @Bean 都受约束,无需重复标注
配合 application-{profile}.yml 实现配置与 Bean 双重隔离
Bean 注入靠 @Profile,配置值靠命名配置文件,两者绑定才完整:
- application-dev.yml 中配:spring.datasource.url=jdbc:h2:mem:testdb
- application-prod.yml 中配:spring.datasource.url=jdbc:mysql://prod-db:3306/app
- 启动时指定 profile:java -jar app.jar --spring.profiles.active=prod
- Spring Boot 自动合并 application.yml(通用) + application-prod.yml(专属),再结合 @Profile("prod") 加载对应 Bean
避免常见误区
这些细节不注意,Bean 往往“不生效”却查不出原因:
- profile 名称必须全小写、无下划线、无连字符,例如用 dev,别用 development 或 dev_env,否则可能抛 IllegalArgumentException
- 禁用 @Profile("!prod") 这类否定表达式——当同时激活 prod,debug 时,该条件仍为 true,容易误注册
- 不要在代码里写 if ("prod".equals(env)) 做分支,这会让所有 Bean 都被创建,只是没注入,浪费内存且破坏可测试性
- 敏感信息(如数据库密码、AK/SK)一律不写进 yml,改用 ${DB_PASSWORD} 占位,由环境变量或配置中心注入

















