【问题标题】:Override @Autowired property annotation with XML configuration使用 XML 配置覆盖 @Autowired 属性注释
【发布时间】:2016-01-13 23:33:21
【问题描述】:

我有一个类EntityLoader,用于使用 Hibernate 从 MySQL 数据库中获取一些数据。但现在需要从两个不同的数据库(本例中为 MySQL 和 Oracle)获取数据。所以我想要两个 EntityLoader 的 bean,但在每个中注入不同的 SessionFactory

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;
    }   
}

而上下文配置为:

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

到目前为止,它工作正常。为此,我做了以下更改:

  • component-scan 中排除EntityLoader 以避免自动创建EntityLoader
  • 添加 mysqlSessionFactoryoracleSessionFactory bean 定义
  • 添加 mysqlEntityRepoLoaderoracleEntityRepoLoader bean 定义

请注意,在mysqlEntityRepoLoaderoracleEntityRepoLoader 中,我添加了autowired="no" 属性,希望这样可以 告诉 Spring 不要自动装配 SessionFactory 而是使用定义的 ref。

生成的配置是:

<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> 

但无论如何,Spring 似乎首先尝试自动装配SessionFactory。我收到以下错误:

没有定义 [org.hibernate.SessionFactory] ​​类型的限定 bean: 预期单个匹配 bean,但找到 2: mysqlSessionFactory,oracleSessionFactory

如果我删除 @Autowired 一切正常。但我想维护它,因为此代码是用于其他应用程序的通用库的一部分,通常情况下仅从一个数据库加载。

有什么方法可以在不删除注释的情况下完成它?

【问题讨论】:

  • 你可以创建一个名为sessionFactory的虚拟bean...
  • 只需从您的EntityLoader 中删除@Component 注释?您正在 XML 中手动创建实例(因此不需要 @Component),并且您正在通过调用 setSessionFactory 方法手动连接会话工厂(因此不需要 @Autowired)。
  • 如果我删除注释,那么我需要在所有其他使用它的应用程序中以 XML 配置这个 bean。我的意图正是要避免这种情况。

标签: java spring spring-annotations xml-configuration


【解决方案1】:

如果您能够修改包含 EntityLoader 的库,则执行以下 2 步即可:

  1. EntityLoader 中将您的@Autowired 设为可选:

    @Autowired(required=false)

  2. 在 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>

瞧!

【讨论】:

  • 谢谢!你说的对!关键是autowire-candidate = "false"
【解决方案2】:

导致问题的是组件扫描。您的 bean 已经手动创建,但 Spring 正在尝试创建 另一个 EntityLoader,因为组件扫描正在获取您的 @Component 注释。

您可以告诉组件扫描(仅针对您的应用)忽略该类:

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

【讨论】:

  • 我已经在component-scan 中使用exclude-filter。无论如何,如果我删除@Component 但保留@Autowired,问题仍然存在。
  • 我认为问题在于 spring 自动装配属性忽略了我的 xml 配置。好像注解优先于 xml。
猜你喜欢
  • 2011-12-25
  • 1970-01-01
  • 2021-06-22
  • 2015-06-30
  • 2022-11-02
  • 2011-06-10
  • 1970-01-01
  • 2010-12-01
  • 1970-01-01
相关资源
最近更新 更多