Статьи

Почему я люблю псевдонимы Spring Bean

Spring Framework широко используется в качестве контейнера для внедрения зависимостей, и это по веским причинам. Прежде всего, это облегчает интеграционное тестирование и дает нам возможность настраивать создание и инициализацию bean-компонента (например, @Autowired для типов List ).

Но есть и очень полезная функция, которая может быть упущена из виду, поэтому давайте обсудим псевдонимы bean-компонентов .

Псевдонимы компонентов позволяют нам переопределять уже настроенные компоненты и заменять их определением другого объекта. Это наиболее полезно, когда определения bean-компонентов наследуются от внешнего ресурса, который находится вне нашего контроля.

В следующем примере я покажу вам, как работает псевдонимы bean-компонентов. Давайте начнем со следующего определения bean-компонента, взятого из файла конфигурации src / main / resources / spring / applicationContext-tx.xml .

Этот контекстный файл содержит множество функций, связанных с транзакциями / JPA, которые мы хотели бы использовать в наших интеграционных тестах.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<bean id="dataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init" destroy-method="close">
    <property name="className" value="${jdbc.driverClassName}"/>
    <property name="uniqueName" value="dataSource"/>
    <property name="minPoolSize" value="0"/>
    <property name="maxPoolSize" value="5"/>
    <property name="allowLocalTransactions" value="false" />
    <property name="driverProperties">
        <props>
            <prop key="user">${jdbc.username}</prop>
            <prop key="password">${jdbc.password}</prop>
            <prop key="url">${jdbc.url}</prop>
        </props>
    </property>
</bean>
 
<bean id="jtaTransactionManager" factory-method="getTransactionManager"
    class="bitronix.tm.TransactionManagerServices" depends-on="btmConfig, dataSource"
    destroy-method="shutdown"/>

Определение bean-компонента dataSource предполагает наличие источника данных XA, но, поскольку HSQLDB не предоставляет его, я вынужден полагаться на LrcXADataSource для преодоления этого ограничения. Но это подразумевает изменение источника данных для использования другого className и driverProperties, и мы не можем этого сделать, так как определение контекста происходит от внешнего артефакта.

К счастью, здесь на помощь приходит псевдоним бобов. Вот как наш контекст Integration Testing src / test / resources / spring / applicationContext-test.xml использует эту удобную функцию:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<import resource="classpath:spring/applicationContext-tx.xml" />
 
<bean id="testDataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init" destroy-method="close">
    <property name="className" value="bitronix.tm.resource.jdbc.lrc.LrcXADataSource"/>
    <property name="uniqueName" value="testDataSource"/>
    <property name="minPoolSize" value="0"/>
    <property name="maxPoolSize" value="5"/>
    <property name="allowLocalTransactions" value="false" />
    <property name="driverProperties">
        <props>
            <prop key="user">${jdbc.username}</prop>
            <prop key="password">${jdbc.password}</prop>
            <prop key="url">${jdbc.url}</prop>
            <prop key="driverClassName">${jdbc.driverClassName}</prop>
        </props>
    </property>
</bean>
 
<alias name="testDataSource" alias="dataSource"/>

TestDataSource относится к тому же типу Class, что и унаследованный dataSource, но поставляется с другой конфигурацией объекта. Это источник данных, который мы хотели бы использовать каждый раз, когда требуется зависимость dataSource, вместо исходного варианта. Это возможно с помощью ключевого слова alias, которое указывает контейнеру внедрения зависимостей заменить исходное определение источника данных новой версией.