Java @自动连线覆盖@Bean
我有一个奇怪的问题(或者可能只是对Spring4.1.7的一些误解): 有一个组件,我们称之为MyComponent,看起来像这样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
@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模板注入到