2017-09-03 35 views
0

假設我有一些類注射:如何告訴CDI容器「激活」一個bean?

class MyBean { 

    @Inject 
    Helper helper; 

    // all sorts of data 
} 

這個類是在一個方式CDI容器不知道它像反射,序列化或new創建。在這種情況下,helpernull,因爲CDI沒有爲我們初始化它。

有沒有辦法告訴CDI「激活」這個bean或至少它的注入?例如,好像它是用Instance<MyBean>#get創建的?

現在我有一個黑客,我做到以下幾點:

class SomeClass { 

    @Inject 
    Instance<MyBean> beanCreator; 

    void activateBean() { 
     MyBean mybean = ... // reflection/serialization/new 
     MyBean realBean = beanCreator.get(); 
     Helper proxy = realBean.getHelper(); 
     mybean.setHelper(proxy); 
     beanCreator.destroy(realBean); 
    } 
} 

這看起來很糟糕,但它爲我測試的一切。它只是顯示我想要的最終結果。

使用Wildfly 10.1如果它很重要。

回答

2

首先,您使用MyBean的方式不是CDI方式;實際上你使用的是所謂的非上下文對象。你在做什麼是採取非CDI管理對象,並要求CDI解決注射點。這是非常不尋常的,因爲你處理生命週期的一部分(創建/銷燬),同時要求CDI去做其餘的事情。

在你的情況下,MyBean類需要變成InjectionTarget,這就是你應該開始尋找的方式。爲了觸發注射,你會想做的事(創建MyBean期間)是這樣的:

// Create an injection target from your given class 
InjectionTarget<MyBean> it = beanManager.getInjectionTargetFactory(beanManager.createAnnotatedType(MyBean.class)) 
       .createInjectionTarget(null); 
CreationalContext<MyBean> ctx = beanManager.createCreationalContext(null); 
MyBean instance = new MyBean(); 
it.postConstruct(instance); // invoke @PostContruct 
it.inject(instance, ctx); // trigger actual injection on the instance 

請注意,這種方法通常是笨拙(如硬盤,使其工作和維護),它可能是更好的做法是將您的MyBean轉換爲真正的CDI bean,並將整個生命週期管理留給CDI。不過,您的問題並未提供足夠的信息。

+0

謝謝。上下文:'MyBean'是我需要保存和加載的狀態對象的一部分,目前是序列化(請參閱我以前的[問題](https://stackoverflow.com/questions/45828159/how-to-serialize-an-注入豆))。我讀到在實體中使用注入並不是一個好主意,但是這個實體需要它。另外,在你寫'new MyBean()'的地方,它可以被反序列化或反射代替,對嗎? – Mark

+0

也許你應該考慮一下,如果它是合理的並且有必要給予MyBean它使用Helper完成的責任。有時候,如果你讓一些'Decorator','Adaptor'或者'Iterator'處理那個結構,那麼結構會更好。這些通常是可以通過容器創建的正常範圍的bean,並且可以使用數據對象。 – aschoerk

+0

如果您提供用例,以及實體如何實際依賴這些bean,那麼我們可以幫助將其重構爲更好的設計,而不需要向實體注入。理想情況下,您應該將實體視爲數據,並有一個單獨的bean來處理該數據。 – maress