@ManagedBean @Component class 内的@Autowired 服务在 JSF 请求期间为空
@Autowired service inside a @ManagedBean @Component class is null during JSF request
我尝试将 Spring 3(MVC) 与 JSF 2 结合使用。我在 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 时设置不为空,但在
时在 JSF 生命周期期间它为空
public void pringString() {
testService.blah();
}
测试服务为空。这是我无法理解的。是否有人深入了解 Spring 和 JSF 来详细描述这种情况?
JSF 和 Spring 都可以充当 bean 容器。 @ManagedBean
注释指示 JSF 托管 bean 工具创建 class 的新实例,并在给定的名称下管理它。 @Component
注释指示 Spring ApplicationContext 创建 class 的新实例,并在给定的名称下管理它。也就是说,JSF 和 Spring 都创建了 class 的实例,JSF 可以通过 EL 访问,但是 Spring 可以注入它的依赖项(因为,作为 spring 注释,@Autowired 不被 JSF 托管 bean 工具理解。
因此您可以选择:对所有内容使用 JSF 托管 bean 工具(我不推荐,因为它相当有限),对所有内容使用 CDI(这是一个选项,但不使用 Spring), 或者对所有事情使用 Spring (我通常这样做), 通过删除 @ManagedBean
注释, 并通过在 EL 中注册 SpringBeanFacesELResolver
使 Spring beans 可访问你的脸-config.xml。 Spring 参考手册在 section 19.3.1 中对此进行了描述。
我认为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 {
......
}
我有同样的问题,这是由于@ManagedBean 属性 的名称 annotation.My backing bean 看起来像这样
@Component
@ManagedBean(name="mainBean")
@SessionScoped
public class MainManagedBean{...}
如您所见,为 bean 指定的名称 (mainBean) 与支持 bean 应具有的默认名称 (mainManagedBean) 不同。
我已通过将 属性 名称设置为 "mainManagedBean" 解决了这个问题。我的bean变成这样:
@Component
@ManagedBean(name="mainManagedBean")
@SessionScoped
public class MainManagedBean{...}
希望对您有所帮助
我尝试将 Spring 3(MVC) 与 JSF 2 结合使用。我在 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 时设置不为空,但在
时在 JSF 生命周期期间它为空public void pringString() {
testService.blah();
}
测试服务为空。这是我无法理解的。是否有人深入了解 Spring 和 JSF 来详细描述这种情况?
JSF 和 Spring 都可以充当 bean 容器。 @ManagedBean
注释指示 JSF 托管 bean 工具创建 class 的新实例,并在给定的名称下管理它。 @Component
注释指示 Spring ApplicationContext 创建 class 的新实例,并在给定的名称下管理它。也就是说,JSF 和 Spring 都创建了 class 的实例,JSF 可以通过 EL 访问,但是 Spring 可以注入它的依赖项(因为,作为 spring 注释,@Autowired 不被 JSF 托管 bean 工具理解。
因此您可以选择:对所有内容使用 JSF 托管 bean 工具(我不推荐,因为它相当有限),对所有内容使用 CDI(这是一个选项,但不使用 Spring), 或者对所有事情使用 Spring (我通常这样做), 通过删除 @ManagedBean
注释, 并通过在 EL 中注册 SpringBeanFacesELResolver
使 Spring beans 可访问你的脸-config.xml。 Spring 参考手册在 section 19.3.1 中对此进行了描述。
我认为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 {
......
}
我有同样的问题,这是由于@ManagedBean 属性 的名称 annotation.My backing bean 看起来像这样
@Component
@ManagedBean(name="mainBean")
@SessionScoped
public class MainManagedBean{...}
如您所见,为 bean 指定的名称 (mainBean) 与支持 bean 应具有的默认名称 (mainManagedBean) 不同。
我已通过将 属性 名称设置为 "mainManagedBean" 解决了这个问题。我的bean变成这样:
@Component
@ManagedBean(name="mainManagedBean")
@SessionScoped
public class MainManagedBean{...}
希望对您有所帮助