2017-04-22 144 views
1

中调用的无参数构造函数,我想知道构造函数注入如何与需要一个bean类需要一个无参数构造函数的需求结合起来。在下面描述的测试之后,我的结论是,无参数构造函数被调用两次,然后调用注入的构造函数。任何人都能解释我为什么?什么时候注入构造函数,什么时候是CDI

为了测试这种行为我创建了一个HelloProducer类:

public class HelloProducer { 

    @Produces 
    @Hello 
    public String helloWildFly() { 
     return "Hello!"; 
    } 

} 

Hello预选赛:

@Qualifier 
@Retention(RUNTIME) 
@Target({METHOD, FIELD, PARAMETER, TYPE}) 
public @interface Hello { 
} 

然后,我创建了一个使用此生产者作为注入的构造的bean类:

@Stateless 
public class HelloBean { 

    private final Logger log = LoggerFactory.getLogger("HelloBean"); 
    private String hello; 

    public HelloBean() { 
     log.warn("No-args constructor called"); 
     this.hello = "Hi!"; 
    } 

    @Inject 
    public HelloBean(@Hello String hello) { 
     log.warn("Injected constructor called"); 
     this.hello = hello; 
    } 

    public String getHello() { 
     return hello; 
    } 

} 

那么,当我调用getHello()方法?你好!或嗨!?让我们测试:

@RunWith(Arquillian.class) 
public class HelloBeanIT { 

    @Deployment 
    public static JavaArchive createDeployment() { 
     return ShrinkWrap.create(JavaArchive.class, "test.jar") 
       .addClass(HelloProducer.class) 
       .addClass(Hello.class) 
       .addClass(HelloBean.class) 
       .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); 
    } 

    @Inject 
    HelloBean helloBean; 

    @Test 
    public void testSomeMethod() { 
     assertThat(helloBean.getHello(), is("Hello!")); 
    } 

} 

那么,该测试运行良好,所以被调用的最终构造函数是注入构造函数。但是,如果我看我看到日志如下:

WARN [HelloBean] No-args constructor called 
WARN [HelloBean] No-args constructor called 
WARN [HelloBean] Injected constructor called 

那么,为什么是注入的构造函数之前通过CDI叫了两声无参数的构造函数?

+0

注:当我删除注入的构造的'HelloBean'测试方法返回嗨!并且无参数构造函数被调用三次。 –

回答

2

所以,通过一点挖掘,我发现了那里实际发生的事情。

no-args构造函数调用在代理初始化期间发生,而带参数的唯一调用是实际的对象创建(以及最终得到的结果)。为了进一步阐述,你的bean是@Stateless--这意味着它是EJB和CDI bean(EJB的定义和CDI自动为你选择)。这两个规范的操作方式都是在实际的实例之上创建一个代理对象,然后您只是传递代理引用而不是实际的实例。

因此,它是这样的:

WARN [HelloBean] No-args constructor called -> CDI Proxy on top of EJB proxy 
WARN [HelloBean] No-args constructor called -> EJB proxy 
WARN [HelloBean] Injected constructor called -> actual instance creation 
+0

有道理!感谢您的解释。 –

相关问题