JSF应用程序范围实例化和注入

时间:2013-01-05 14:32:58

标签: jsf scope code-injection instantiation

可能我的问题很简单,但我之前从未使用过应用程序范围bean。我需要应用程序bean,因为我必须花时间在数据库上进行事务处理。 我的搜索根本不能满足我的好奇心。 我不知道为什么,但我没有设法初始化bean(它是null)或应用程序崩溃。 所以我有一个应用程序范围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的正确方法。我真的很困惑......

谢谢大家的时间!

2 个答案:

答案 0 :(得分:25)

有两个潜在的错误。

首先,@ManagedBean(eager=true)仅作为its javadoc说明,仅适用于应用程序作用域的JSF托管bean。因此,仅当您使用@ApplicationScoped javax.faces.bean个包(因此不是javax.enterprise.context包!)时,它才有效。 eager=true基本上意味着bean将在webapp的启动时自动实例化,而不是仅在以后第一次在EL中引用时。

其次,根据Javabeans规范,托管bean名称默认为decapitalized形式的classname。您没有显式指定任何托管bean名称,例如@ManagedBean(name="container", eager=true),因此托管bean名称将默认为applicationContainer,但是您仍然尝试将其引用为#{container}而不是#{applicationContainer} {1}}。

您根本不清楚自己面临哪些问题/错误。如果您遇到异常,您应该完全阅读/解释它,如果您无法理解它,请将其完整地复制 - 包括问题中的堆栈跟踪。它代表了你自己问题的全部答案。你只需要解释和理解它(或者我们只需要用外行的术语解释它)。你真的不应该忽视它们,并将它们排除在外,就好像它们是无关的装饰一样。他们不是!

总而言之,完整而正确的方法将是完整的导入声明,以确保,还有一些穷人的stdout打印用于调试:

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;
    }

}

答案 1 :(得分: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投入使用。看起来好像很黑……