Spring中使用SpEL動態選擇加載Bean

1、背景

個人組須要開發一個公共基礎Spring配置,來完成多個工程所需的共性配置與功能。但帶來的問題則是Spring配置擴展問題,公共的Spring配置當然好,但若是須要擴展某個Bean就有問題了。列舉一個典型的例子,如公共模塊中LocalSessionFactoryBean已經定義了annotatedClasses列表。但引用公共模塊配置的工程但願在裏面加入本身的附加annotatedClasses列表。 html

2、分析

因爲Spring的Xml配置啓動時就由於自動按依賴關係加載好須要的依賴Bean。若是想幹擾Bean初始化的過程是比較麻煩的,有可能須要編寫一些特殊的BeanFactory類來完成。在查閱資料時發現Spring 3中的SpEL功能比較強大,也許能夠不用作Java開發經過純Xml配置來完成我想要的配置。 java

3、SpEL動態配置樣例

一、common.xml(公共模塊配置)

<bean id="annotatedClassesList" class="java.util.ArrayList" >
        <constructor-arg index="0" value="#{ getBeanFactory().containsBean('otherAnnotatedClassesList') ? @otherAnnotatedClassesList : annotatedClassesEmptyList}" />
    </bean>

    <bean id="annotatedClassesEmptyList" class="java.util.Collections" factory-method="emptyList"/>

    <bean id="annotatedClassesListAddDefault" factory-bean="annotatedClassesList" factory-method="addAll">
        <constructor-arg index="0">
            <list>
                <value>org.noahx.XXXX1</value>
                <value>org.noahx.XXXX2</value>
                <value>org.noahx.XXXX3</value>
            </list>
        </constructor-arg>
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" depends-on="annotatedClassesListAddDefault">
        <property name="dataSource" ref="dataSource"/>
        <property name="annotatedClasses" ref="annotatedClassesList"/>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>

讓咱們經過逆序追蹤的方法來看Bean加載過程。 spring

一、sessionFactory中加入了depends-on屬性,因此在加載sessionFactory前必先加載annotatedClassesListAddDefault
二、annotatedClassesListAddDefault負責調用annotatedClassesList的addAll方法加入默認持久類列表,因此以前必先加載annotatedClassesList
三、annotatedClassesList初始化時,構造函數的參數中會使用SpEL來作一個判斷
四、SpEL中使用getBeanFactory().containsBean()方式,能夠檢查整個Spring環境中是否存在otherAnnotatedClassesList(關鍵)

五、存在則將otherAnnotatedClassesList注入構造函數參數,不存在則將annotatedClassesEmptyList注入構造函數參數
六、這樣SpEL就能夠決定annotatedClassesList初始化時的結果
sql

二、project.xml(項目配置)

<import resource="classpath:org/noahx/xxx/common.xml"></import> <!--引用公共Jar中的Xml配置-->

 <bean id="otherAnnotatedClassesList" class="java.util.ArrayList" >
        <constructor-arg index="0">
            <list>
                <value>org.noahx.XXXX4</value>
                <value>org.noahx.XXXX5</value>
            </list>
        </constructor-arg>
    </bean>

若是項目須要加入本身的classes就能夠定義一個otherAnnotatedClassesList。公共類加載時,也會將XXXX4與XXXX5一同加載。若是項目不須要修改持久類,則徹底能夠不定義otherAnnotatedClassesList。 express

這樣,otherAnnotatedClassesList就變爲一個配置擴展點,不須要項目作什麼高級的處理。有擴展點加載執行,沒有不加載執行。 session

4、總結

SpEL仍是比較強大的,除了我採用getBeanFactory().containsBean()這樣很是規方式來判斷Bean是否存外,SpEL還有很是多的特性。它的使用將使咱們的Spring配置具備更強的靈活性。 函數

Spring 4的說明(SpEL):http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/expressions.html spa

注:Spring 3後就可使用SpEL,只是高版本支持的功能更多。 hibernate

相關文章
相關標籤/搜索