2012-11-14 69 views
4

當你調用一個你必須通過一個新實例作爲參數的Java方法時,這個新實例是如何由CDI容器創建的?如何創建按需實例?

在下面的例子:我添加監聽到aynchronous servlet上下文:

@WebServlet(value = "/example", asyncSupported = true) 
public class ExampleServlet extends HttpServlet { 

    @Override 
    protected void doPost(final HttpServletRequest req, 
     final HttpServletResponse resp) throws ServletException, 
     IOException { 

     // ... some code 

     AsyncContext aCtx = req.startAsync(req, resp); 
     aCtx.addListener(**new AsyncListener()** { 
      // implementation of the async listener 
     }); 
     // ... 
    } 
} 

因此,而不是手動執行這一新AsyncListener()的實例化,我想它由CDI創建容器。

當然,我希望每個異步上下文都有自己的偵聽器實例,否則我只是將@Inject的AsyncListener注入爲servlet類的字段。

現在,找不到任何方法來做到這一點。 有人有想法分享?

回答

0

bean的注入點是在bean被實例化時處理的,所以不幸的是你不能明確地觸發注入。這可能(並希望會)在CDI的後續版本中發生變化。

我知道的一種方法可以在某些情況下用於解決該限制,即封裝或派生要注入的類,併爲其提供注入字段或初始化方法。在這種情況下,它將是AsyncContext,但您無法控制HttpServletRequest將返回的內容,因此此選項在此處不適用。

也許你可以想些辦法使用CDI BeanManager - 但我擔心這會需要顯著更多的努力比調用new

5

注入你的聽衆的Instance。如果偵聽器類處於依賴範圍內,則每次調用get()都會產生一個新實例。

@Inject 
private Instance<MyAsyncListener> listenerFactory; 

和:

aCtx.addListener(listenerFactory.get()); 

我稱爲變量listenerFactory,因爲這是它是如何被用在這裏。

我在JBoss AS7.1.1上測試了這個,它使用Weld 1.1.5作爲它的CDI提供程序,但我相信這是標準行爲。

+0

+1很好知道它實際上可以進行調整 – kostja

+1

還要注意CDI 1.0中記錄良好的內存泄漏,並將實例和依賴的範圍對象注入到更大的範圍對象中,但是對於您正在做的事情您應該沒事的。 – LightGuard

+0

@LightGuard:好點,但我必須承認,我不確定爲什麼這種情況是安全的。是否因爲servlet不被視爲限定範圍的bean? –