在JSF请求期间,@ ManagedBean @Component类中的@Autowired服务为null

时间:2015-02-09 23:57:46

标签: spring jsf-2 dependency-injection managed-bean

我尝试使用JSF 2联合Spring 3(MVC)。我在Spring和JSF方面有一些经验,但从未尝试过加入它们。最后我有2个文件

@ManagedBean(name = "userBean")
@Scope
@Component
public class someBean {

  @Autowired
  private TestService testService;

  public void printString() {
    System.out.println(testService.getString());
  }
}

@ManagedBean(name = "studentBean")
@Scope
@Component
public class StudentBean {

  @Autowired
  private TestService testService;

  public void printString() {
    System.out.println(testService.getString());
  }
}

对于这些文件,我有正确的spring,jsf和web.xml配置。并有.xhtml页面,我为'someBean'和'StudentBean'启动printString()。我在第一种情况下使用NPE,在第二种情况下在控制台中使用“some string”。 原因很简单 - Spring上下文和JSF中的bean名称不同。

后完成所有问题
@Component => @Component("userBean") 
public class someBean {

在调试中我看到了

private TestService testService;

@Autowired
public void setTestService(TestService testservice) {
  this.testService = testService;
}

当JSF bean创建的testService集不为null时,但在

的JSF生命周期中它是null
public void pringString() {
  testService.blah();
}

testService为null。这是我无法理解的。有谁深入了解Spring和JSF详细描述这种情况?

3 个答案:

答案 0 :(得分:10)

JSF和Spring都可以充当bean容器。 @ManagedBean注释指示JSF托管bean工具创建该类的新实例,并在给定名称下对其进行管理。 @Component注释指示Spring ApplicationContext创建类的新实例,并在给定名称下管理它。也就是说,JSF和Spring都创建了该类的实例,JSF可以通过EL访问,但是Spring会注入其依赖项(因为,作为一个spring注释,@ Autowired不被JSF托管bean工具理解)

所以你可以选择:将JSF托管bean工具用于所有东西(我不推荐,因为它相当有限),对所有东西使用CDI(这是一个选项,但不使用Spring),或者使用通过删除@ManagedBean注释,通过在faces-config.xml中注册SpringBeanFacesELResolver,可以通过EL访问Spring bean,从而实现Spring的一切(我通常会这样做)。 Spring参考手册在section 19.3.1中描述了这一点。

答案 1 :(得分:1)

我有同样的问题,这是由于@ManagedBean注释的属性名称。我的支持bean看起来像这样

@Component
@ManagedBean(name="mainBean")
@SessionScoped
public class MainManagedBean{...}

如您所见,bean(mainBean)的名称与支持bean应具有的默认名称(mainManagedBean)不同。

我已通过将属性名称设置为" mainManagedBean"来修复此问题。我的豆变成这样:

@Component
@ManagedBean(name="mainManagedBean")
@SessionScoped
public class MainManagedBean{...}

我希望这可以帮到你

答案 2 :(得分:0)

我认为testService为null的原因是因为在构造托管bean时还没有实例化testService。因此,您可以使用@PostConstruct将Spring bean注入托管bean。

@ManagedBean(name = "userBean")
@Scope
@Component
public class someBean {

    @Autowired
    private TestService testService;

    public void printString() {
        System.out.println(testService.getString());
    }

    @PostConstruct
    private void init() {
    ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        ServletContext servletContext = (ServletContext) externalContext.getContext();
    WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext).
                                   getAutowireCapableBeanFactory().
                                   autowireBean(this);
    }
}

@Service
public class TestService {
    ......
}