Spring實戰筆記——Profile詳解

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.activespring.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.activespring.profiles.default@ActiveProfiles中,profile使用的都是複數形式。這意味着可以同時激活多個profile,這可以通過列出多個profile名稱,並以逗號分隔來實現。用來同時設置多個彼此不相關的profile。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章