简体   繁体   English

使用XML配置覆盖@Autowired属性注释

[英]Override @Autowired property annotation with XML configuration

I've a class EntityLoader that's used to fetch some data from a MySQL database using Hibernate. 我有一个EntityLoader类,它用于使用Hibernate从MySQL数据库中获取一些数据。 But now the need is to fetch data from two different databases (MySQL and Oracle in this case). 但现在需要从两个不同的数据库(在这种情况下是MySQL和Oracle)中获取数据。 So I want to have two beans of EntityLoader but injecting a different SessionFactory in each one. 所以我希望有两个EntityLoader bean,但每个bean都注入一个不同的SessionFactory

EntityLoader is defined as follows: EntityLoader定义如下:

package com.demo

@Component
public class EntityLoader {

    @Autowired
    private SessionFactory sessionFactory;

    /* Code ... */

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }   
}

And the context configuration is: 上下文配置是:

<context:component-scan base-package="com.demo" />
<bean id="mysqlSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">

So far it works fine. 到目前为止它工作正常。 Over this I have done the following changes: 在此我做了以下更改:

  • Exclude EntityLoader from component-scan in order to avoid the auto creation of a EntityLoader component-scan中排除EntityLoader以避免自动创建EntityLoader
  • Add mysqlSessionFactory and oracleSessionFactory bean definitions 添加mysqlSessionFactoryoracleSessionFactory bean定义
  • Add mysqlEntityRepoLoader and oracleEntityRepoLoader bean definitions 添加mysqlEntityRepoLoaderoracleEntityRepoLoader bean定义

Note that in mysqlEntityRepoLoader and oracleEntityRepoLoader I've added the attribute autowired="no" hoping that this would tell Spring to not autowire the SessionFactory and use the defined ref instead. 请注意,在mysqlEntityRepoLoaderoracleEntityRepoLoader我添加了属性autowired="no"希望这会告诉Spring不要自动装配SessionFactory并使用定义的ref。

The resulting configuration is: 结果配置为:

<context:component-scan base-package="com.demo">
    <context:exclude-filter type="regex" expression="com.demo.EntityLoader"/>
</context:component-scan>

<bean id="mysqlSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <!-- ... config ... -->
</bean>
<bean id="oracleSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <!-- ... config ... -->
</bean>

<bean id="mysqlEntityRepoLoader" class="com.dome.imserso.api.core.data.EntityRepoLoader" autowire="no">
    <property name="sessionFactory" ref="mysqlSessionFactory"/>
</bean> 
<bean id="oracleEntityRepoLoader" class="com.dome.imserso.api.core.data.EntityRepoLoader" autowire="no">
    <property name="sessionFactory" ref="oracleSessionFactory"/>
</bean> 

But it seems that Spring is trying first to autowire the SessionFactory in any case. 但似乎Spring在任何情况下都首先尝试自动装配SessionFactory I get the following error: 我收到以下错误:

No qualifying bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: mysqlSessionFactory,oracleSessionFactory 没有定义[org.hibernate.SessionFactory]类型的限定bean:期望的单个匹配bean但找到2:mysqlSessionFactory,oracleSessionFactory

If I remove the @Autowired all works fine. 如果我删除@Autowired一切正常。 But I would like to maintain it, as this code is part of a generic lib used for other apps where the usual case is to load only from one database. 但我想维护它,因为此代码是用于其他应用程序的通用库的一部分,其中通常的情况是仅从一个数据库加载。

Is there any way to accomplish it without removing the annotation? 有没有办法在不删除注释的情况下完成它?

If you are able to modify your lib which contains EntityLoader, following these 2 step will do the trip : 如果您能够修改包含EntityLoader的lib,则执行以下两步操作:

  1. In EntityLoader make your @Autowired optional: EntityLoader@Autowired可选:

    @Autowired(required=false) @Autowired(所需=假)

  2. In XML configuration, exclude mysqlSessionFactory and oracleSessionFactory beans from autowire candidates, add autowire-candidate="false" to each sessionFactory: 在XML配置中,从autowire候选者中排除mysqlSessionFactory和oracleSessionFactory bean,将autowire-candidate="false"到每个sessionFactory:

<bean id="mysqlSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" autowire-candidate="false">
    <!-- ... config ... -->
</bean>
<bean id="oracleSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" autowire-candidate="false">
    <!-- ... config ... -->
</bean>

Voilà! 瞧!

It's the component-scan that's causing problems. 这是导致问题的组件扫描。 Your beans are already manually created, but Spring is trying to create another EntityLoader because the component scan is picking up your @Component annotation. 您的bean已经手动创建,但Spring正在尝试创建另一个 EntityLoader因为组件扫描正在拾取您的@Component注释。

You can tell the component scan (for just your app) to ignore that class: 您可以告诉组件扫描(仅针对您的应用)忽略该类:

<context:component-scan ...>
    <context:exclude-filter expression="com\.demo\.EntityLoader" type="regex" />
</context:component-scan>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM