Java @自动连线覆盖@Bean

Java @自动连线覆盖@Bean,java,spring,Java,Spring,我有一个奇怪的问题(或者可能只是对Spring4.1.7的一些误解): 有一个组件,我们称之为MyComponent,看起来像这样 @Component public class MyComponent extends BaseComponent { ... } public class BaseComponent { @Autowired private HibernateTemplate hibernateTemplate; public void setHib

我有一个奇怪的问题(或者可能只是对Spring4.1.7的一些误解):

有一个组件,我们称之为MyComponent,看起来像这样

@Component
public class MyComponent extends BaseComponent {
...
}
public class BaseComponent {    
   @Autowired
   private HibernateTemplate hibernateTemplate;

   public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
      this.hibernateTemplate = hibernateTemplate;
   }
}
BaseComponent是这样的

@Component
public class MyComponent extends BaseComponent {
...
}
public class BaseComponent {    
   @Autowired
   private HibernateTemplate hibernateTemplate;

   public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
      this.hibernateTemplate = hibernateTemplate;
   }
}
由于历史原因,该类用@Component注释,但该包的组件扫描未激活,因此不会自动找到该组件。因此,我在@Configuration中有一个定义

@Configuration
public class MyConfiguration {

 @Bean 
 public HibernateTemplate hibernateTemplate() { ... create one ... }


 @Bean 
 public HibernateTemplate hibernateTemplateSecondary() { ... create another one ... }


 @Bean
 public MyComponent myComponent() {
    MyComponent component = new MyComponent();
    component.setHibernateTemplate( hibernateTemplateSecondary() );
    return component;
 } 
}
不幸的是,现在发生的情况是,myComponent将首先使用辅助
HibernateTemplate
正确初始化,但之后,Spring将“normal
HibernateTemplate
注入其中(这是错误的)

我已经尝试显式地将
autowire=autowire.NO
添加到@Bean定义中,即使这已经是默认值了。。。也没有两个myComponent豆子,总是同一个

有人知道为什么会发生这种情况吗?如果有,如何预防?我一直认为当涉及@Bean时,@Autowired不会覆盖它吗


请注意:因为MyComponent也用于其他项目,所以我绝对不能触摸它。我不能删除
@Autowired
,也不能添加
@Qualifier
或类似内容,因为这会破坏许多其他项目。通常情况下,它工作正常,因为它使用了“主”(通常是唯一)数据库连接。就在这个模块中,另一个数据库应该是主数据库,因此需要告诉MyComponents使用辅助数据库。

你不能在BaseComponent中使用@Qualifier(“hibernateTemplateSecondary”)这样它就可以选择正确的bean吗

@Autowired
@Qualifier("hibernateTemplateSecondary")
private HibernateTemplate hibernateTemplate;
另一种方法是使用在您的情况下看起来不好的主注释(考虑到它是您的辅助bean)


你不能在BaseComponent中使用@Qualifier(“hibernateTemplateSecondary”),这样它就可以选择正确的bean了吗

@Autowired
@Qualifier("hibernateTemplateSecondary")
private HibernateTemplate hibernateTemplate;
另一种方法是使用在您的情况下看起来不好的主注释(考虑到它是您的辅助bean)


也许有更好的解决方案,但您可以使用以下BeanPostProcessor解决此问题:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

  @Autowired
  @Qualifier("hibernateTemplateSecondary")
  private HibernateTemplate hibernateTemplateSecondary;

  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
  }

  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof MyComponent) {
      ((MyComponent) bean).setHibernateTemplate(hibernateTemplateSecondary);
    }
    return bean;
  }
}

这将在初始化bean后注入正确的模板,并覆盖错误的模板。

也许有更好的解决方案,但您可以使用如下BeanPostProcessor解决此问题:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

  @Autowired
  @Qualifier("hibernateTemplateSecondary")
  private HibernateTemplate hibernateTemplateSecondary;

  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
  }

  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof MyComponent) {
      ((MyComponent) bean).setHibernateTemplate(hibernateTemplateSecondary);
    }
    return bean;
  }
}

这将在初始化bean后注入正确的模板,并覆盖错误的模板。

我刚刚在谷歌上发现了你的问题。我是这样解决的: (在spring boot 2.0/spring 5.0中测试)


我只是在谷歌上搜索同样的问题时偶然发现了你的问题。我是这样解决的: (在spring boot 2.0/spring 5.0中测试)


为什么不简单地删除
@Autowired
?无法做到这一点,因为
MyComponent
被用于许多其他组件扫描的模块中。就在这个模块中,它不应该是(因为这个模块使用不同的“主”数据库)方法,然后使用hibernateTemplate from hibernateTemplate()方法覆盖初始的hibernateTemplate变量。这是你的观点吗?对。第一次,在我的
@Bean
方法中,我使用
hibernateTemplateSecondary()
中的
hibernateTemplate
正确初始化了
MyComponent
,但之后,Spring决定它也应该
@Autowire
它,因此将我设置的
hibernateTemplate
替换为
hibernateTemplate()
中的一个。根据条件更改配置类以创建单个hibernateTemplate对象。在本例中,返回hibernateTemplate对象的单个方法。在方法内部,您可以设置创建HibernateTemplate对象的条件。如果这不起作用,你可以使用@conditional annotation。为什么不简单地删除
@Autowired
?不能这样做,因为
MyComponent
在许多其他模块中使用,在这些模块中它是组件扫描的。就在这个模块中,它不应该是(因为这个模块使用不同的“主”数据库)方法,然后使用hibernateTemplate from hibernateTemplate()方法覆盖初始的hibernateTemplate变量。这是你的观点吗?对。第一次,在我的
@Bean
方法中,我使用
hibernateTemplateSecondary()
中的
hibernateTemplate
正确初始化了
MyComponent
,但之后,Spring决定它也应该
@Autowire
它,因此将我设置的
hibernateTemplate
替换为
hibernateTemplate()
中的一个。根据条件更改配置类以创建单个hibernateTemplate对象。在本例中,返回hibernateTemplate对象的单个方法。在方法内部,您可以设置创建HibernateTemplate对象的条件。如果这不起作用,你可以选择@conditional annotation。不幸的是,我不能触摸
MyComponent
。毫无疑问,我知道这会解决问题,实际上这也是我最喜欢的方法,但它也被用于多个其他模块中(在那里,使用了组件扫描)。不幸的是,我无法触摸
MyComponent
。毫无疑问,我知道这将解决问题,实际上这也是我更喜欢的方法,但它也被用于多个其他模块中(在那里,使用了组件扫描)。这与当前的解决方法类似(但稍好一些)(将辅助hibernate模板注入到