spring 高級裝配(三)

本章內容

  • spring prifile
  • 條件話的bean聲明
  • 自動裝配與歧義性
  • bean的作用域
  • Spring表達式語言

3.1 環境與profile

軟件開發的生命週期中,很多時候涉及到環境的遷移,而各種環境的配置文件會有所不同.最簡單的方式就是爲不同的階段配置不同的配置類或者xml文件.然後在構建的時候確定使用哪一個.

  • 配置 profile bean

①: spring會在運行的時候確定使用哪個配置文件,這樣的好處是同一個部署(可能會是war)單元能夠適應所有的環境,沒有必要進行重新構建.
在java配置中使用@Profile 註解指定某個bean屬於哪個profile 在3.1版本中@Profile是類級別的註解,從3.2開始是方法級別的註解與@Bean註解一同使用,這樣就可以將bean的聲明放到同一個配置類之中. —特別注意bean聲明在profile中,並且只有當規定的profile激活時,相應的bean纔會被創建.

②:在xml中配置profile
我們可以使用 < beans > 元素的profile屬性,在xml中配置 profile bean.

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd" profile="qa"> <!-- 可以配置多個配置文件 在這裏做區分 不同的文件命名  profile="qa"-->
</beans>

也可以在同一個xml中引入不同的beans標籤

<?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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd">

<!--測試環境的配置文件-->
    <beans profile="qa">
        <context:property-placeholder location="classpath:environment.properties"/>
    </beans>
<!--生產環境的配置文件-->
    <beans profile="pro">
        <context:property-placeholder location="file:${ENVIRONMENT_FILE}"/>
    </beans>
</beans>

3.1.2激活profile

Spring 在確定那個profile激活狀態時,需要依賴2個獨立的屬性
spring.profiles.active 和spring.profoles.default.如果設置了spring.profiles.active屬性的話,那麼它的值就會用來確定哪個profile是激活的.但是如果沒有設置的話spring會查找spring.profiles.default的值.如果都沒有設置的話,那就沒有激活的profile,因此只會創建那些沒有定義在profile中的bean

可以用多種方式來設置這2個屬性
- 作爲DispatcherServlet的初始化參數;
- 作爲Web應用上下文的參數;
- 作爲JNDI條目
- 作爲環境變量
- 作爲JVM的系統屬性
- 在集成測試類上,使用@ActiveProfiles註解設置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
    <!-- 爲上下文設置默認的profile -->
    <context-param>
        <param-name>spring.profiles.default</param-name>
        <param-value>qa</param-value>
    </context-param>
    <!-- 爲Servlet設置默認的profile -->
    <servlet>
        <init-param>
            <param-name>spring.profiles.default</param-name>
            <param-value>qa</param-value>
        </init-param>
    </servlet>
</web-app>

當設置spring.profiles.active以後,系統會優先使用active中所設置的profile.就會不關心default的設置了

profile使用的是複數的形式,這意味着可以同時激活多個profile.多個之間使用,分隔來實現

    <beans profile="qa,dev,pro">
        <context:property-placeholder location="file:${ENVIRONMENTS_FILE}"/>
    </beans>
  • 使用profile進行測試
    如果配置中的bean定義在了profile中,那麼運行測試的時候,我們需要有一種方式來啓用合適的profile
    spring提供了註解@ActiveProfiles激活profile
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring.xml")
@ActiveProfiles("dev")
public class AlsTest {
    @Test
    public void  testApp()throws Exception{

    }
}

3.2 條件話的bean

在條件話初始bean方面spring的profile機制是一種很棒的方法,這裏的條件要基於那個profile處於激活狀態來判斷.spring4.0提供了一種更爲通用的機制來實現條件話的bean定義,在這種機制下,條件完全由自己確定.

假設你希望一個或者多個bean在滿足指定的條件下才會創建.spring4.0引入了一個新的註解@Conditional註解,它可以用到帶有@bean的註解上.如果給定的條件結果爲true就會創建這個bean.否則的話被忽略

    //可以看到@Condition中給定了一個Class,它指明瞭條件,在本例中MagicExistsCondition會通過Condition接口進行條件對比
    @Bean
    @Conditional(MagicExistsCondition.class)
    public MagicBean magicBean(){
        return new MagicBean();
    }

/**
 * 設置給Conditional的類可以是任意實現了Condition接口的類型
 * 這個接口只需要實現matches()方法即可
 */
public class MagicExistsCondition implements Condition {

    /**
     *通過給定的ConditionContext對象進而得到Environment對象,並使用這個對象檢查環境中是否存在名爲magic的環境屬性,
     * 屬性值是什麼無所謂,只要屬性存在即可滿足要求,bean就會被創建,屬性不存在不滿足bean就不會被創建
     * 如果這個屬性不存在的話,就無法滿屋條件,返回false,就不會被創建
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Environment env = context.getEnvironment();
        return env.containsProperty("magic");//檢查magic屬性
    }
}

MagicExistsCondition 中只是用了CoditionContext得到的Environment,但是Condition實現的考量因爲會更多.matches()方法會得到ConditionContext和AnnotateTypeMetadata對象來做出決策
通過ConditionContext ,我們可以做到如下幾點

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