9

我添加了PhaseListener一个faces-config.xml

<lifecycle>
    <phase-listener>com.project.NotificationListener</phase-listener>
</lifecycle>

该类似乎是正确的,因为它非常简单。

public class NotificationListener implements PhaseListener {

    @Inject
    private MyCDIStuff stuff;

    @Override
    public PhaseId getPhaseId() {
        return PhaseId.RENDER_RESPONSE;
    }

    @Override
    public void beforePhase(PhaseEvent event) {
        this.stuff.doStuff();
    }
}

'beforePhase' 方法被正确调用,但是 MyCDIStuff 对象为空。我尝试@Singleton对很可能不正确的类使用注释,但它也没有使注入工作。

有没有办法在 中注入 CDI 托管 bean PhaseListener

4

2 回答 2

13

在 JSF 2.2 之前,PhaseListeners 没有注册为 CDI 注入目标。使用@Inject(and @EJB) 在 s 中实际上没有效果PhaseListener。您需要通过以编程方式评估引用@Named's(隐式)名称的 EL 表达式或作为最后手段通过 JNDI 手动获取 CDI 托管 bean,BeanManager这非常笨拙。

因此,如果您无法升级到 JSF 2.2(它应该与任何 JSF 2.0/2.1 和 Servlet 3.0 兼容的 Web 应用程序兼容),那么您最好的选择是以编程方式评估引用该@Named名称的 EL 表达式。假设你有一个

@Named("stuff")
public class MyCDIStuff {}

那么这应该这样做:

FacesContext context = event.getFacesContext();
MyCDIStuff stuff = context.getApplication().evaluateExpressionGet(context, "#{stuff}", MyCDIStuff.class);
// ...
于 2013-11-12T13:23:13.543 回答
4

如果你不能使用 JSF 2.2,你最好的选择是使用 Deltaspike Core。

它提供 MyCDIStuff myCDIStuff = BeanProvider.getContextualReference(MyCDIStuff.class, false);

Deltaspike 是你应该如何获得东西而不是自己发明的方法。例如,如果您必须拥有 BeanManager(例如触发事件),那么 Deltaspike 核心也提供BeanManagerProvider.

http://deltaspike.apache.org/core.html

于 2013-11-12T15:29:05.057 回答