2017-06-13 95 views
0

我有一个奇怪的问题(或者只是关于Spring 4.1.7一些误解):@Autowired覆盖@Bean

有一个组件,让我们把它叫做myComponent的,看起来像这样...

@Component 
public class MyComponent extends BaseComponent { 
... 
} 

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初始化,但事后,春天注入了“正常hibernateTemplate进入它(这是错误的)。

我试图明确添加autowire = Autowire.NO到@Bean定义,即使这已经是默认......也没有两个myComponent的豆子,它总是同一个...

有没有人一个想法为什么发生这种情况,如果是的话,如何防止它呢?我一直认为@Bean参与时,@Autowired不会覆盖那个?

请注意:因为MyComponent也用于其他项目,所以我绝对不能碰它。我无法删除@Autowired,我也不能添加@Qualifier或类似的东西,因为那会破坏很多其他项目。通常情况下,它工作正常,因为它使用“主要”(通常是唯一的)数据库连接。就在这个模块中,另一个数据库应该是主数据库,因此需要告知MyComponents使用次数据库。

+2

为什么不简单地删除'@ Autowired'? – Henry

+0

不能这样做,因为'MyComponent'被用于许多其他模块,它被组件扫描。就在这个模块中,它不应该是(因为这个模块使用了不同的“主”数据库)。 –

+0

为了理解你的问题,第一次在hibernateTemplate变量中用hibernateTemplate对象从hibernateTemplateSecondary()方法和后来的hibernateTemplate变量绑定到BaseComponent中,用hibernateTemplate()方法用hibernateTemplate覆盖最初的hibernateTemplate变量。这是你的观点吗? –

回答

1

难道你不能在BaseComponent中使用@Qualifier(“hibernateTemplateSecondary”),以便它可以拾取正确的bean吗?

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

另一种方法是使用原注释看起来并不好你的情况(考虑到它是你的第二豆)

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

不幸的是,我无法触摸'MyComponent'。我知道这无疑会解决问题,实际上它也是我的首选方法,但它被用于多个其他模块(并且在那里使用组件扫描)。 –

1

也许有更好的解决方案,但你可以解决这与这样了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; 
    } 
} 

这将豆后注入正确的模板已初见并将覆盖错误的一个。

+0

这与当前的解决方法相似(但稍好一些)(使用MyComponent将二级hibernate模板注入所有bean并再次调用setter)。谢谢。它本身并不能解决问题,但它似乎是一个更合理的解决方法。 –

+0

我也有一些成功的使用自定义'InstantiationAwareBeanPostProcessorAdapter'返回'false' for'postProcessAfterInstantiation' MyComponent',但是这些都是战斗症状,我仍然不知道为什么它自动装配。它不应该那样做,afaik。 –