11

可能我的问题是一个微不足道的问题,但我以前从未使用过应用程序范围 bean。我需要应用程序 bean,因为我必须在数据库上执行耗时的事务。我的搜索根本满足不了我的好奇心。我不知道为什么,但我没有设法初始化 bean(它为空)或者应用程序崩溃了。所以我有一个应用程序范围bean

@ManagedBean(eager=true)
@ApplicationScoped
public class ApplicationContainer {
...
}

eager=true 我读到它告诉 JSF 在每次启动应用程序服务器(我使用 GlassFish)时启动 bean。

我在几个地方读到我只需要放置这个注释并且 bean 被初始化。对我来说不是...在我读到之后,如果我想将应用程序 bean 注入另一个 bean,我必须使用 @PostConstuct 注释

@ManagedBean
@SessionScoped
public class TestsBean implements Serializable {

    private static final long serialVersionUID = 1L;
    @ManagedProperty(value = "#{container}")
    private ApplicationContainer container;

    @PostConstruct
    public void init() {
    container.contructContainer();
    }

这会在我将 TestsBean 注入的其他 bean 中产生错误...

  • 如果应用程序 bean 在服务器启动时被初始化,它在应用程序 bean 的主体中调用什么方法来执行它需要的操作?或者在注入的bean中它是在post构造方法中完成的?

请告诉我处理应用程序 bean 的正确方法。我真的很困惑...

谢谢大家的时间!

4

2 回答 2

29

有2个潜在错误。

首先,@ManagedBean(eager=true)正如它的 javadoc所说,这些工作仅适用于应用程序范围的 JSF 托管 bean。所以它只有在你使用@ApplicationScopedjavax.faces.bean包时才有效(因此不是javax.enterprise.context包!)。这eager=true基本上意味着 bean 将在 webapp 的启动时自动实例化,而不是稍后在 EL 中第一次引用它时。

其次,根据 Javabeans 规范,托管 bean 名称默认为非大写形式的类名。您没有明确指定任何托管 bean 名称@ManagedBean(name="container", eager=true),因此托管 bean 名称将默认为applicationContainer,但是您仍然尝试将其引用#{container}#{applicationContainer}.

您根本不清楚您面临哪些问题/错误。如果您遇到异常,您绝对应该阅读/解释它,如果您无法理解它,请将其全部复制粘贴 - 包括问题中的堆栈跟踪。它本身代表了您问题的全部答案。你只需要解释和理解它(或者我们只需要用外行的话来解释它)。你真的不应该忽视它们,把它们当作无关紧要的装饰一样置之不理。他们不是!

总而言之,完整和正确的方法是,为了确保完整的导入声明,以及一些用于调试的穷人的标准输出打印:

package com.example;

import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;

@ManagedBean(eager=true)
@ApplicationScoped
public class ApplicationContainer {

    public ApplicationContainer() {
        System.out.println("ApplicationContainer constructed");
    }

}
package com.example;

import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class TestsBean implements Serializable {

    @ManagedProperty("#{applicationContainer}")
    private ApplicationContainer container;

    public TestsBean() {
        System.out.println("TestsBean constructed");
    }

    @PostConstruct
    public void init() {
        System.out.println("ApplicationContainer injected: " + container);
    }

    public void setContainer(ApplicationContainer container) {
        this.container = container;
    }

}
于 2013-01-05T14:57:15.477 回答
0

由于我遇到了同样的问题,并且我使用了@BalusC 代码来解决它,我觉得这里可能只是要添加一些东西。

问题作者指出:

在我读到之后,如果我想将应用程序 bean 注入另一个 bean,我必须使用 @PostConstuct 注释

这正是我的问题。我做了 BalusC 在他的回答中所做的一切,除了我没有在 Session Bean 的 init() 方法中以任何方式使用 Application Bean。所以,我补充说

@ManagedBean
@SessionScoped
public class TestsBean implements Serializable {

@PostConstruct 
init(){
....
System.out.println("appbean session init size" + appbean.getPinovi().size());
....
} 

这是我必须做的让它工作,只是以某种方式使用 appBean。它看起来像黑客,虽然......

于 2019-09-11T13:26:03.633 回答