【问题标题】:CDI @Specializes and Constructor Injection with @PostconstructCDI @Specializes 和 @Postconstruct 的构造函数注入
【发布时间】:2015-03-19 10:39:10
【问题描述】:

我有以下课程:

@Named
@ViewScoped
public class BaseClass {
    private SomeDependency dep;

    public BaseClass(){}

    @Inject
    public BaseClass(SomeDependency dep) {
        this.dep = dep;
    }

    @PostConstruct
    private void initialize() {
        dep.doSomething(); // Point "A"
    }

    public String getProperty() {
        return "BaseClass-Property";
}

@Specializes
public class SpecialClass extends BaseClass() {

    @Override
    public String getProperty() {
        return "SpecialClass-Property";
    }
}

现在在一些 .xhtml 中我有类似的东西

<h:outputText value="#{baseClass.property}" />

没有SpecialClass 也能正常工作。如果我在项目中包含SpecialClass,它将在点“A”处与NullPointerException 中断。

好吧,根据to the Weld specification,这或多或少是预期的行为:

当一个启用的 bean 专门化另一个 bean 时,另一个 bean 永远不会 由容器实例化或调用。

尽管如此,现在我必须确保每个 @Specializes bean 都实现了完整的构造函数,例如

public SpecialClass() {}

@Inject
public SpecialClass(SomeDependency dep) { super(dep); }

恕我直言,这有点违反直觉,会产生大量重复的样板代码,尤其是每个构造函数都有 5-6 个参数。此外,在创建新的专用 bean 时永远不会发现这种情况,因为项目始终是编译干净的。

是我做错了什么,还是除了一遍又一遍地实现构造函数别无选择?

顺便说一句,我确实使用构造函数注入来创建易于测试的类,我可以只使用构造函数来“注入”依赖项的虚拟实现。

【问题讨论】:

  • 当然,即使是默认的原始 java 实例化也会失败。构造函数不被继承,除了默认的无参数构造函数。
  • 嗯,我知道“原始”实例化,我曾希望 CDI 逻辑可以减轻我作为程序员的负担...... ;-)

标签: jsf dependency-injection cdi postconstruct


【解决方案1】:

4.3 节中的 CDI 1.1 规范说:

“一个 bean 完全覆盖第二个 bean 的唯一方法 注入点是它是否实现了所有 bean 类型并声明 第二个 bean 的所有限定符。”

您的基类使用 Named 限定符进行注释,而专门化类则没有。您还应该用 Alternative 标记它并在 beans.xml 中启用它。还有 ViewScoped 注释。除非它是 Omnifaces 的 ViewScoped,否则您似乎将 JSF 托管 bean 与 CDI bean 混合在一起。

【讨论】:

  • HInt:如果 bean 没有实现 Serializable,OmniFaces @ViewScoped 会抛出异常。
  • 它是 OmniFaces ViewScoped,因为我在 JEE6 / CDI 1.0 上,但 1.0 在该段落中声明了相同的规范。该项目中使用了专门的bean,一切正常,我只是在使用我希望以更简单的方式处理的那个注入构造器逻辑......
猜你喜欢
  • 2011-04-02
  • 2013-05-23
  • 1970-01-01
  • 1970-01-01
  • 2021-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多