Profile详解
在项目开发的过程中,我们在不同阶段可能需要不同的配置,而我们不可能花费两个项目去实现这样的功能,但Spring就提供了一个很好的特性,利用profile进行配置可以实现此目的。
配置Profile Bean
例如我们在开发和生产的过程中使用不同的数据库
一、通过JavaConfig进行配置
创建Spring配置类
package com.zheng.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.zheng.spring")
public class Config {
private final DataSource dataSource;
@Autowired(required = false)
public Config(DataSource dataSource) {
this.dataSource = dataSource;
}
}
package com.zheng.spring;
import javax.sql.DataSource;
public interface DatabaseConfig {
DataSource createDataSource();
}
开发阶段(使用H2)
package com.zheng.spring;
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 javax.sql.DataSource;
@Profile("Dev") // 使用@Profile注解
@Configuration
public class DevDatabaseConfig implements DatabaseConfig {
@Override
@Bean
public DataSource createDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:schema.sql")
.addScript("classpath:test-data.sql")
.build();
}
}
生产阶段(使用JNDI)
package com.zheng.spring;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jndi.JndiObjectFactoryBean;
import javax.sql.DataSource;
@Profile("Prod")
@Configuration
public class ProductionDatabaseConfig implements DatabaseConfig {
@Override
@Bean
public DataSource createDataSource() {
JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
jndiObjectFactoryBean.setJndiName("jdbc/myDS");
jndiObjectFactoryBean.setResourceRef(true);
jndiObjectFactoryBean.setProxyInterface(javax.sql.DataSource.class);
return (DataSource) jndiObjectFactoryBean.getObject();
}
}
测试类
package com.zheng.spring;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class AppMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("Prod"); // 选择Profile的参数,将决定你使用哪个bean
context.scan("com.zheng.spring");
context.refresh();
context.close();
}
}
二、通过xml配置
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<beans profile="Dev">
<jdbc:embedded-database id="dataSource">
<jdbc:script location="classpath:schema.sql" />
<jdbc:script location="classpath:test-data.sql" />
</jdbc:embedded-database>
</beans>
<beans profile="Prod">
<jee:jndi-lookup id="dataSource"
jndi-name="jdbc/myDatabase"
resource-ref="true"
proxy-interface="javax.sql.DataSource" />
</beans>
</beans>
测试类
package com.zheng.spring;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppMain {
public static void main(String args[]) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
context.getEnvironment().setActiveProfiles("Dev"); // 激活Profile
context.close();
}
}
激活Profile
Spring提供了两个属性用来决定那个profile被激活, 分别是spring.profiles.active
和spring.profiles.default
。如果active被设置, 那么就会忽略default, 否则查看default所设置的值, 如果default也没有被设置, 那么只有没有profile的bean才会被创建。
有以下几种方式来设置这两个属性:
- 作为
DispatcherServlet
的初始化参数 - 作为网站应用的上下文参数
- 作为JNDI条目
- 作为环境变量
- 作为JVM系统属性
- 使用集成test类的
@ActiveProfiles
注解
在web.xml文件设置默认的profile
<!-- 为上下文设置默认的profile -->
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>Dev</param-value>
</context-param>
<!-- 为Servlet设置默认的profile -->
<servlet>
<servlet-name>AppServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatherServlet
</servlet-class>
<init-param>
<param-name>spring.profiles.default</param-name>
<param-value>Dev</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AppServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
使用profile进行Spring JUnit测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={AppConfig.class})
@ActiveProfiles("Development")
public class ConfigTest {
// ...
}
在spring.profiles.active
、spring.profiles.default
和@ActiveProfiles
中,profile使用的都是复数形式。这意味着可以同时激活多个profile,这可以通过列出多个profile名称,并以逗号分隔来实现。用来同时设置多个彼此不相关的profile。