2015-02-07 144 views
1

我嘗試CDI的@New註釋是否工作 - 看起來沒有。@新註解不起作用

在我的應用程序創建這樣的類:

package pl.piotrek; 
import java.util.Date; 
import javax.enterprise.inject.Produces; 
import javax.enterprise.context.SessionScoped; 
public class DateFactory { 
    public @Produces @SessionScoped Date produceDate() { 
     return new Date((long)(Math.random() * 2000000000000L)); 
    } 
} 

然後我嘗試使用它在我的servlet:

package pl.piotrek; 
import java.io.IOException; 
import java.io.PrintWriter; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.servlet.annotation.WebServlet; 
import java.util.Date; 
import javax.inject.Inject; 
import javax.enterprise.inject.New; 
@WebServlet("/HelloWorld") 
public class MyServlet extends HttpServlet { 
    @New @Inject 
    private Date d1; 
    @New @Inject 
    private Date d2; 
    @New @Inject 
    private Date d3; 
    @Override 
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { 
     PrintWriter writer = resp.getWriter(); 
     writer.println(d1 + "\n" + d2 + "\n" + d3); 
     writer.close(); 
    } 
} 

我預計該servlet將打印出三種不同的日期 - 我註解使用@New註釋進行注射 - 但它會打印三個相同的日期,如下所示:

Sat Feb 07 07:53:36 CET 2015 
Sat Feb 07 07:53:36 CET 2015 
Sat Feb 07 07:53:36 CET 2015 

爲什麼?

回答

0

從生產者方法中刪除@SessionScoped。返回的Date綁定到會話,不會再被調用。

+0

返回的日期是不是一個隨機的事實一個(在製片人編碼),但問題的確切日期似乎並不奇怪巧合? – 2015-02-07 13:43:52

0

我不確定您對@New限定符的期待是什麼(請記住它在CDI 1.1中已棄用)。閱讀corresponding section the spec可能會有用。

無論如何,@New與Managed Bean和會話Bean(EJB)不是生產者有關。該規範規定

注意,這第二個bean存在 - 而且可能被啓用,可供 注射 - 即使第一個bean是禁用的,由 啓用和禁用豆類的定義,或者如果bean類被部署在Bean歸檔中定義的Bean歸檔的外部 之外,因此在包裝和 部署中定義的bean發現過程中未發現 。容器通過檢查 其他啓用的bean的注入點來發現@New限定的bean。

所以,當你寫

@New @Inject 
private Date d1; 

不使用你的製作人,這是所使用的Date類。爲什麼你總是有當前的日期。

-1

使用@New註釋CDI只創建一個用@New註釋的值定義的類的新實例。如果該值被省略,則聲明的注入點的類型被採用。

沒有@New註釋CDI創建代理實例而不是實際實例。現在使用@New實例,因爲只有一個新的()實例被請求,所以沒有可用的代理。因此不需要調用一個生產者方法..用@New @Produces註釋不被調用。

示例代碼:

package pl.piotrek; 

import java.util.Date; 
import javax.enterprise.inject.New; 
import javax.enterprise.inject.Produces; 
import javax.inject.Inject; 
import org.jglue.cdiunit.CdiRunner; 
import org.junit.Test; 
import org.junit.runner.RunWith; 

@RunWith(CdiRunner.class) 
public class AtNewAndProducerTest { 

    @Produces 
    public Date produceDate() { 
     return new Date((long)(Math.random() * 2000000000000L)); 
    } 

    @New @Inject 
    private Date d1; 

    @New @Inject 
    private Date d2; 

    @New @Inject 
    private Date d3; 

    @Inject 
    private Date d4; 

    @Inject 
    private Date d5; 

    @Test 
    public void test() { 
     System.out.println(d1); 
     System.out.println(d2); 
     System.out.println(d3); 
     System.out.println(d4); 
     System.out.println(d5); 

     // will output something like this: 
     // Sat Feb 07 13:16:05 CET 2015 
     // Sat Feb 07 13:16:05 CET 2015 
     // Sat Feb 07 13:16:05 CET 2015 
     // Mon Sep 19 12:31:29 CEST 2005 
     // Sat Aug 14 21:51:06 CEST 1999 
    } 

} 

你可以在Github上找到這個例子: https://github.com/StefanHeimberg/stackoverflow-28379562

+0

我們儘量讓CDI規格儘可能容易閱讀。所以請花點時間閱讀http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#new並檢查我的答案。 – 2015-02-07 13:40:39

1

答案很簡單:刪除@New@SessionScoped

+1

一個簡短的解釋是值得的:使用'@ New'完全跳過生產者並創建一個普通的Data對象的新實例 - 因此所有的對象都會指向當前的數據,雖然它們不相等。 '@ SessionScoped'導致在單個會話中,您將始終獲得生成器中創建的相同隨機對象。範圍應該是未指定的或'@ Dependent'以便每次生成新的對象。 – OndrejM 2015-10-15 08:26:43