CDI bean总是在服务器启动时实例化,即使使用@ViewScoped或@RequestScoped

时间:2015-12-09 12:08:07

标签: jsf cdi

我在Tomcat 7下运行了一个JSF webapp(Mojarra 2.2.12,PrimeFaces 5.2,OmniFaces 2.2)(我按照这些步骤安装了CDI:http://balusc.omnifaces.org/2013/10/how-to-install-cdi-in-tomcat.html)。

我正在尝试使用@ManagedBean注释将我的JSF bean转换为带有@Named注释的CDI bean。我的问题是每当我使用@Named注释一个bean时,即使它有@ViewScoped注释,它也会在webapp启动时获得实例化。要找出错误,我已将下面的3个bean添加到webapp(灵感来自http://showcase.omnifaces.org/cdi/ViewScoped

“纯粹的”JSF bean

import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import org.omnifaces.util.Faces;

@ManagedBean
@ViewScoped
public class JsfViewScopedBean implements Serializable {

    private static final long serialVersionUID = 1L;

    @PostConstruct
    public void postConstruct() {
        System.out.println(getClass().getSimpleName()
                + ".postConstruct() invoked");
    }

    public void submit() {
        System.out.println(getClass().getSimpleName() + ".submit() invoked");
    }

    public String navigate() {
        System.out.println(getClass().getSimpleName() + ".navigate() invoked");
        return Faces.getViewId();
    }

    public void rebuildView() {
        System.out.println(getClass().getSimpleName()
                + ".rebuildView() invoked");
        Faces.setViewRoot(Faces.getViewId());
    }

    @PreDestroy
    public void preDestroy() {
        System.out
                .println(getClass().getSimpleName() + ".preDestroy() invoked");
    }

}

带有javax.faces.view.ViewScoped注释的CDI bean

import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

import org.omnifaces.util.Faces;

@Named
@ViewScoped
public class CdiJsfViewScopedBean implements Serializable {

    private static final long serialVersionUID = 1L;

    @PostConstruct
    public void postConstruct() {
        System.out.println(getClass().getSimpleName()
                + ".postConstruct() invoked");
    }

    public void submit() {
        System.out.println(getClass().getSimpleName() + ".submit() invoked");
    }

    public String navigate() {
        System.out.println(getClass().getSimpleName() + ".navigate() invoked");
        return Faces.getViewId();
    }

    public void rebuildView() {
        System.out.println(getClass().getSimpleName()
                + ".rebuildView() invoked");
        Faces.setViewRoot(Faces.getViewId());
    }

    @PreDestroy
    public void preDestroy() {
        System.out
                .println(getClass().getSimpleName() + ".preDestroy() invoked");
    }
}

带有org.omnifaces.cdi.ViewScoped注释的CDI bean

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Named;

import org.omnifaces.cdi.ViewScoped;
import org.omnifaces.util.Faces;

@Named
@ViewScoped
public class CdiOmnifacesViewScopedBean implements Serializable {

    private static final long serialVersionUID = 1L;

    @PostConstruct
    public void postConstruct() {
        System.out.println(getClass().getSimpleName()
                + ".postConstruct() invoked");
    }

    public void submit() {
        System.out.println(getClass().getSimpleName() + ".submit() invoked");
    }

    public String navigate() {
        System.out.println(getClass().getSimpleName() + ".navigate() invoked");
        return Faces.getViewId();
    }

    public void rebuildView() {
        System.out.println(getClass().getSimpleName()
                + ".rebuildView() invoked");
        Faces.setViewRoot(Faces.getViewId());
    }

    @PreDestroy
    public void preDestroy() {
        System.out
                .println(getClass().getSimpleName() + ".preDestroy() invoked");
    }

}

当我启动webapp时,应用程序范围bean按预期进行了解释,但是CdiJsfViewScopedBean和CdiOmnifacesViewScopedBean也是实例化的,因为我在日志中获得了这些行:

CdiJsfViewScopedBean.postConstruct() invoked
CdiOmnifacesViewScopedBean.postConstruct() invoked

从一开始就显然出现了问题...我已经添加了一个网页来调查我的bean的行为(正如@BalusC在他的展示中所做的那样)并且事实证明JsfViewScopedBean的行为与BalusC的行为完全相同展示,但那些带有@Named注释的2,无论我按什么按钮都不会再次实现...

这是网页:

<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui" xmlns:c="http://java.sun.com/jsp/jstl/core"
    template="/templates/resosLayout.xhtml">

    <ui:define name="content">

        <h3>JsfViewScopedBean</h3>
        <h:form id="jsfViewScopedBeanForm">
            <p>Status:</p>
            <ul>
                <li>It's now: #{now}</li>
                <li>Session ID: #{session.id}</li>
                <li>JSF view scoped bean: #{jsfViewScopedBean}</li>
            </ul>
            <p>
                <h:commandButton value="submit form without ajax" action="#{jsfViewScopedBean.submit}" />
                <h:commandButton value="submit form with ajax" action="#{jsfViewScopedBean.submit}">
                    <f:ajax execute="@form" render="@form" />
                </h:commandButton>
                <h:commandButton value="rebuild view" action="#{jsfViewScopedBean.rebuildView}">
                    <f:ajax execute="@form" render="@form" />
                </h:commandButton>
                <h:commandButton value="navigate on POST" action="#{jsfViewScopedBean.navigate}">
                    <f:ajax execute="@form" render="@form" />
                </h:commandButton>
                <h:button value="refresh page" />
            </p>
            <p>Messages from jsfViewScopedBeanForm:</p>
            <h:messages for="jsfViewScopedBeanForm" />
        </h:form>


        <hr />

        <h3>CdiJsfViewScopedBean</h3>
        <h:form id="cdiJsfViewScopedBeanForm">
            <p>Status:</p>
            <ul>
                <li>It's now: #{now}</li>
                <li>Session ID: #{session.id}</li>
                <li>JSF view scoped bean: #{cdiJsfViewScopedBean}</li>
            </ul>
            <p>
                <h:commandButton value="submit form without ajax" action="#{cdiJsfViewScopedBean.submit}" />
                <h:commandButton value="submit form with ajax" action="#{cdiJsfViewScopedBean.submit}">
                    <f:ajax execute="@form" render="@form" />
                </h:commandButton>
                <h:commandButton value="rebuild view" action="#{cdiJsfViewScopedBean.rebuildView}">
                    <f:ajax execute="@form" render="@form" />
                </h:commandButton>
                <h:commandButton value="navigate on POST" action="#{cdiJsfViewScopedBean.navigate}">
                    <f:ajax execute="@form" render="@form" />
                </h:commandButton>
                <h:button value="refresh page" />
            </p>
            <p>Messages from cdiJsfViewScopedBeanForm:</p>
            <h:messages for="cdiJsfViewScopedBeanForm" />
        </h:form>

        <hr />

        <h3>CdiOmnifacesViewScopedBean</h3>
        <h:form id="cdiOmnifacesViewScopedBeanForm">
            <p>Status:</p>
            <ul>
                <li>It's now: #{now}</li>
                <li>Session ID: #{session.id}</li>
                <li>JSF view scoped bean: #{cdiOmnifacesViewScopedBean}</li>
            </ul>
            <p>
                <h:commandButton value="submit form without ajax" action="#{cdiOmnifacesViewScopedBean.submit}" />
                <h:commandButton value="submit form with ajax" action="#{cdiOmnifacesViewScopedBean.submit}">
                    <f:ajax execute="@form" render="@form" />
                </h:commandButton>
                <h:commandButton value="rebuild view" action="#{cdiOmnifacesViewScopedBean.rebuildView}">
                    <f:ajax execute="@form" render="@form" />
                </h:commandButton>
                <h:commandButton value="navigate on POST" action="#{cdiOmnifacesViewScopedBean.navigate}">
                    <f:ajax execute="@form" render="@form" />
                </h:commandButton>
                <h:button value="refresh page" />
            </p>
            <p>Messages from CdiOmnifacesViewScopedBean:</p>
            <h:messages for="cdiOmnifacesViewScopedBeanForm" />
        </h:form>

    </ui:define>

</ui:composition>

我的猜测是,我要么错过了CDI bean,要么我的CDI设置有问题,或者可能与其他libs有些冲突(我使用spring)但是我不知道从哪里开始排序...

1 个答案:

答案 0 :(得分:0)

最后我解决了(非常感谢@Kukeltje,你把我放在正确的轨道上)但是我真的不明白整个事情......

这是春天的一个问题:在我的webapp的spring配置文件中,我有:

<context:component-scan base-package="org.sarcomabcb.resos.web" />

当我将3个bean移动到spring未扫描的目录时,它们突然开始按预期运行。

可能会帮助像我这样的新手...