Spring入门实战之Profile详解

发布时间 - 2026-01-10 22:59:45    点击率:

前言

Spring中的Profile功能其实早在Spring 3.1的版本就已经出来,它可以理解为我们在Spring容器中所定义的Bean的逻辑组名称,只有当这些Profile被激活的时候,才会将Profile中所对应的Bean注册到Spring容器中。

看到Profile这个关键字,或许你从来没有正眼瞧过他,又或者脑海中有些模糊的印象,比如除了这里Springmvc中的Profile,maven中也有Profile的标签。

从字面意思来看,Profile表示侧面,那什么情况下才会用到侧面这个功能呢,而侧面具体又有什么含义呢

打一个比方,对于数据库的配置问题,在开发的眼中可以使用嵌入的数据库,并且加载测试数据(后面会给出代码示例)。但是在测试的眼中,可能会配一个数据库连接池类似这样

@Bean(destroyMethod="close")
public DataSource dataSource () {
 BasicDataSource dataSource = new BasicDataSource();
 dataSource.setUrl("jdbc:h2:tcp://dbserver/~/test");
 dataSource.setDriverClassName("org.h2.Driver");
 dataSource.setUsername("sa");
 dataSource.setPassword("password");
 dataSource.setInitialSize(20);
 dataSource.setMaxActive(30);
 return dataSource; 
}

当然还有产品环境下的配置等等。对于这种百花齐放的配置方式你还能说什么,默默的为这一套套的环境都部署相应的配置文件啊,没有profile这套我们一直都是这么做。

但是现在有了Profile,我们就多了一种选择,一种更加智能省心的配置方式。通过Profile配置,Spring可以在根据环境在运行阶段来决定bean的创建与否,先举例如下,主要从Profile bean的配置和激活来展开。

Profile bean的配置

通过注解@Profile配置

对于上面比方中的第一种情况,在开发环境中我们配置一个数据源可能是这样的

@Bean(destroyMethod = "shutdown")
public DataSource embeddedDataSource() {
 return new EmbeddedDatabaseBuilder()
 .addScript("classpath:schema.sql")
 .addScript("classpath:test-data.sql")
 .build();
 }

这里会使用EmbeddedDatabaseBuilder创建一个嵌入式数据库,模式定义在类文件下的schema.sql文件中

schema.sql

create table Things (
 id identity,
 name varchar(100)
);

这里定义了一张Things表包含了两个字段

除了模式文件,还需要通过test-data.sql加载测试数据

test-data.sql

insert into Things (name) values ('A')

对于这个@Bean完全不知道是放在开发的环境下创建还是产品的环境下。所以我们这里可以使用注解@Profile帮助我们为这个bean打上标识。

从Spring 3.1版本中就引入了bean profile的功能,可以让你将不同的bean定义到一个或者多个profile里,然后在部署应用时告知要激活那个profile,则相应的bean就会被创建。

比如这里

@Configuration
@Profile("dev")
public class DevelopmentProfileConfig {

 @Bean(destroyMethod = "shutdown")
 public DataSource embeddedDataSource() {
 return new EmbeddedDatabaseBuilder()
 .setType(EmbeddedDatabaseType.H2)
 .addScript("classpath:schema.sql")
 .addScript("classpath:test-data.sql")
 .build();
 }
}

通过@Profile("dev")为EmbedderDataSource bean标记为dev环境下要创建的bean。

注意:1. @Profile被加载类级别上,如果dev profile没有被激活,那么类中对应的所有bean就不会被创建

         2. 如果当前是dev环境被激活了,那么对于没有使用@Profile的bean都会被创建,被标记为其他的profile如prod,则不会创建相应的bean

         3. 从3.2开始@Profile不仅仅可以加载类级别上,还可以加载方法上,具体代码如下

package com.myapp;

import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.jndi.JndiObjectFactoryBean;

@Configuration
public class DataSourceConfig {
 
 @Bean(destroyMethod = "shutdown")
 @Profile("dev")
 public DataSource embeddedDataSource() {
 return new EmbeddedDatabaseBuilder()
 .setType(EmbeddedDatabaseType.H2)
 .addScript("classpath:schema.sql")
 .addScript("classpath:test-data.sql")
 .build();
 }

 @Bean
 @Profile("prod")
 public DataSource jndiDataSource() {
 JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
 jndiObjectFactoryBean.setJndiName("jdbc/myDS");
 jndiObjectFactoryBean.setResourceRef(true);
 jndiObjectFactoryBean.setProxyInterface(javax.sql.DataSource.class);
 return (DataSource) jndiObjectFactoryBean.getObject();
 }

}

通过xml配置文件配置

除了简单的注解方式,我们哈可以通过在xml配置文件中声明的方式,具体配置如下

datasource-config.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" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
 xmlns:jee="http://www.springframework.org/schema/jee" xmlns:p="http://www.springframework.org/schema/p"
 xsi:schemaLocation="
 http://www.springframework.org/schema/jee
 http://www.springframework.org/schema/jee/spring-jee.xsd
 http://www.springframework.org/schema/jdbc
 http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
 http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd">

 <beans profile="dev">
 <jdbc:embedded-database type="H2">
 <jdbc:script location="classpath:schema.sql" />
 <jdbc:script location="classpath:test-data.sql" />
 </jdbc:embedded-database>
 </beans>
 
 <beans profile="prod">
 <jee:jndi-lookup 
 lazy-init="true"
 jndi-name="jdbc/myDatabase"
 resource-ref="true"
 proxy-interface="javax.sql.DataSource" />
 </beans>
</beans>

这里分别声明了两种环境以及对应的profile。

profile激活

虽然我们已经配置好了profile,但是如何激活相应的环境呢。这里我们需要两个属性spring.profile.active以及spring.profile.default

如果spring.profile.active被赋值了,则spring.profile.default就不会起作用,如果spring.profie.active没有赋值,则使用默认的spring.profile.default设置的值。当然,如果两者都没有设置的话,则只会创建那些定义在相应的profile中的bean。

设置这两个属性的方式有很多:

作为DispactcherServlet的初始化参数

作为Web应用上下文参数

作为JNDI条目

作为环境变量

作为JVM的系统属性

在集成测试类上,使用@ActiveProfiles注解设置

比如我们在web.xml中可以声明代码如下

<?xml version="1.0" encoding="UTF-8"?>
<web -app version="2.5"
...>

 //为上下文设置默认的profile
 <context-param>
 <param-name>spring.profile.default</param-name>
 <param-value>dev</param-value>
 </context-param>

...

 <servlet>
 ...
 //为Serlvet设置默认的profile
 <init-param>
  <param-name>spring-profiles.default</param-name>
  <param-value>dev</param-value>
 </init-prama>

...
<web-app>

这样就可以指定需要启动那种环境,并准备相应的bean。

另外对于测试,spring为什么提供了一个简单的注解可以使用@ActiveProfiles,它可以指定运行测试的时候应该要激活那个profile。比如这里的测试类DevDataSourceTest

package profiles;

import static org.junit.Assert.*;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.sql.DataSource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.myapp.DataSourceConfig;

public class DataSourceConfigTest {

 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration(classes=DataSourceConfig.class)
 @ActiveProfiles("dev")
 public static class DevDataSourceTest {
 @Autowired
 private DataSource dataSource;
 
 @Test
 public void shouldBeEmbeddedDatasource() {
 assertNotNull(dataSource);
 JdbcTemplate jdbc = new JdbcTemplate(dataSource);
 List<String> results = jdbc.query("select id, name from Things", new RowMapper<String>() {
 @Override
 public String mapRow(ResultSet rs, int rowNum) throws SQLException {
  return rs.getLong("id") + ":" + rs.getString("name");
 }
 });
 
 assertEquals(1, results.size());
 assertEquals("1:A", results.get(0));
 }
 }

 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration(classes=DataSourceConfig.class)
 @ActiveProfiles("prod")
 public static class ProductionDataSourceTest {
 @Autowired
 private DataSource dataSource;
 
 @Test
 public void shouldBeEmbeddedDatasource() {
 // should be null, because there isn't a datasource configured in JNDI
 assertNull(dataSource);
 }
 }
 
 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration("classpath:datasource-config.xml")
 @ActiveProfiles("dev")
 public static class DevDataSourceTest_XMLConfig {
 @Autowired
 private DataSource dataSource;
 
 @Test
 public void shouldBeEmbeddedDatasource() {
 assertNotNull(dataSource);
 JdbcTemplate jdbc = new JdbcTemplate(dataSource);
 List<String> results = jdbc.query("select id, name from Things", new RowMapper<String>() {
 @Override
 public String mapRow(ResultSet rs, int rowNum) throws SQLException {
  return rs.getLong("id") + ":" + rs.getString("name");
 }
 });
 
 assertEquals(1, results.size());
 assertEquals("1:A", results.get(0));
 }
 }

 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration("classpath:datasource-config.xml")
 @ActiveProfiles("prod")
 public static class ProductionDataSourceTest_XMLConfig {
 @Autowired(required=false)
 private DataSource dataSource;
 
 @Test
 public void shouldBeEmbeddedDatasource() {
 // should be null, because there isn't a datasource configured in JNDI
 assertNull(dataSource);
 }
 }

}

运行shouldBeEmbeddedDatasource方法,测试通过

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。


# spring  # profile  # 配置  # 注解  # 使用Spring boot 的profile功能实现多环境配置自动切换  # 浅谈关于spring profile的误解  # Spring Boot使用profile如何配置不同环境的配置文件  # spring @profile注解的使用方法  # Maven管理SpringBoot Profile详解  # 详解Spring Boot Profiles 配置和使用  # 详解springboot + profile(不同环境读取不同配置)  # 通过实例了解Spring中@Profile的作用  # 加载  # 可以使用  # 配置文件  # 它可以  # 都是  # 测试数据  # 眼中  # 这一  # 就会  # 也有  # 让你  # 好了  # 放在  # 还可以  # 多个  # 是这样  # 有很多  # 还能  # 说什么  # 才会 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何使用Service Provider注册服务_Laravel服务提供者配置与加载  phpredis提高消息队列的实时性方法(推荐)  如何在香港免费服务器上快速搭建网站?  网站制作价目表怎么做,珍爱网婚介费用多少?  如何注册花生壳免费域名并搭建个人网站?  Laravel请求验证怎么写_Laravel Validator自定义表单验证规则教程  Laravel广播系统如何实现实时通信_Laravel Reverb与WebSockets实战教程  jimdo怎样用html5做选项卡_jimdo选项卡html5实现与切换效果【指南】  HTML5段落标签p和br怎么选_文本排版常用标签对比【解答】  如何在Ubuntu系统下快速搭建WordPress个人网站?  java中使用zxing批量生成二维码立牌  怎样使用JSON进行数据交换_它有什么限制  如何解决hover在ie6中的兼容性问题  如何在腾讯云服务器快速搭建个人网站?  什么是javascript作用域_全局和局部作用域有什么区别?  Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控  百度输入法ai组件怎么删除 百度输入法ai组件移除工具  C#如何调用原生C++ COM对象详解  node.js报错:Cannot find module &#39;ejs&#39;的解决办法  如何构建满足综合性能需求的优质建站方案?  Laravel如何实现邮件验证激活账户_Laravel内置MustVerifyEmail接口配置【步骤】  Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】  iOS UIView常见属性方法小结  如何快速辨别茅台真假?关键步骤解析  Android GridView 滑动条设置一直显示状态(推荐)  大连 网站制作,大连天途有线官网?  如何在七牛云存储上搭建网站并设置自定义域名?  laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法  Laravel怎么实现API接口鉴权_Laravel Sanctum令牌生成与请求验证【教程】  javascript日期怎么处理_如何格式化输出  Java遍历集合的三种方式  如何挑选最适合建站的高性能VPS主机?  简单实现Android验证码  Laravel怎么集成Vue.js_Laravel Mix配置Vue开发环境  如何用景安虚拟主机手机版绑定域名建站?  Laravel中Service Container是做什么的_Laravel服务容器与依赖注入核心概念解析  如何自定义建站之星网站的导航菜单样式?  Laravel如何生成API文档?(Swagger/OpenAPI教程)  香港服务器建站指南:外贸独立站搭建与跨境电商配置流程  Laravel如何使用Seeder填充数据_Laravel模型工厂Factory批量生成测试数据【方法】  如何在建站主机中优化服务器配置?  Claude怎样写结构化提示词_Claude结构化提示词写法【教程】  Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】  文字头像制作网站推荐软件,醒图能自动配文字吗?  HTML 中如何正确使用模板变量为元素的 name 属性赋值  Laravel怎么使用Intervention Image库处理图片上传和缩放  如何快速使用云服务器搭建个人网站?  哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?  如何在服务器上三步完成建站并提升流量?  最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?