不调用@PostConstruct的抽象祖先

时间:2015-04-22 03:16:51

标签: java unit-testing jersey jax-rs cdi

我正在编写JAX-RS库(不是应用程序)。

我有:

abstract class A {

    @PostConstruct
    private void constructed_a() {} // not invoked

    @Inject
    private Some some;
}


public abstract class B extends A {

    @PostConstruct
    private void constructed_b() {} // not invoked
}

测试班:

@Path("c")
public class C extends B {

    @PostConstrct
    private void constructed_c() {} // invoked
}

我正在使用泽西测试框架v2.17进行测试

我发现只调用了constructed_c(),并且没有调用祖先定义的那些方法。请注意,在some类中使用@Inject声明的字段(A)已正确注入。

这是正常的吗?我该怎么办?


结论

我使用embedded-glassfish进行了测试,发现正如Antonin Stefanutti指出的那样,这些回调方法按预期顺序调用。

constructed_a()
constructed_b()
constructed_c()

2 个答案:

答案 0 :(得分:6)

根据JSR 318 - Interceptors 1.2规范的目标类上声明的拦截器的调用顺序:

  

在目标类或其超类上声明的拦截器方法   按以下顺序调用:

     
      
  • 如果目标类具有超类,则调用在这些超类上定义的任何拦截器方法,首先是大多数通用超类。
  •   
  • 调用目标类本身的拦截器方法(如果有)。
  •   
     

如果拦截器方法被另一个方法覆盖(无论如何)   无论该方法本身是一种拦截器方法,它都不会   被调用。

这意味着在编写库/框架时,可以在父类和子类中使用@PostConstruct生命周期回调时实现可扩展性。

Camel CDI扩展中使用了该机制,该扩展声明了https://github.com/astefanutti/camel-cdi/blob/b6f52d91b247e36eefb6f3ecde61016d681d3535/impl/src/main/java/org/apache/camel/cdi/CdiCamelContext.java#L37

中具有@PostConstruct生命周期回调的默认Camel上下文

这可以由https://github.com/astefanutti/camel-cdi/blob/b6f52d91b247e36eefb6f3ecde61016d681d3535/envs/se/src/main/java/org/apache/camel/cdi/se/bean/CustomLifecycleCamelContext.java#L37中的用户扩展,声明自己的@PostConstruct生命周期回调。

容器按照指定的顺序调用它们。

这意味着从设计的角度来看,您的方法是正确的。但是,由于泽西依赖注入基于HK2而不是CDI并且依赖于像jersey-gf-cdi这样的桥梁,因此在该级别可能存在问题。

答案 1 :(得分:2)

注释不会被继承。您必须为每个子类创建一个@PostConstruct注释方法。

为了帮助/提醒开发人员,您可能需要postConstruct()方法,并希望开发人员根据其名称建议对其进行适当注释:

public abstract class A {

    @PostConstruct // annotation here has no value except as a reminder
    public abstract void postConstruct();