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。