2017-06-13 74 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。 –