SpringJSF集成:如何在JSF托管bean中注入Spring组件/服务?
我知道托管bean的工作方式类似于控制器,因为您唯一的任务是将视图层与模型“链接” 要将bean用作托管bean,我必须声明SpringJSF集成:如何在JSF托管bean中注入Spring组件/服务?,spring,jsf,dependency-injection,integration,managed-bean,Spring,Jsf,Dependency Injection,Integration,Managed Bean,我知道托管bean的工作方式类似于控制器,因为您唯一的任务是将视图层与模型“链接” 要将bean用作托管bean,我必须声明@ManagedBean注释,这样我就可以直接将JSF与bean通信 如果我想在这个managedBean中注入一些组件(来自Spring),我有两种可能的方法: 选择ManagedBean中的属性(如“BasicDAO”)并在属性上方声明@ManagedProperty(#{“BasicDAO”})。为此,我在ManagedBean中注入了Spring中的bean“bas
@ManagedBean
注释,这样我就可以直接将JSF与bean通信
如果我想在这个managedBean中注入一些组件(来自Spring),我有两种可能的方法:
@ManagedProperty(#{“BasicDAO”})
。为此,我在ManagedBean中注入了Spring中的bean“basicDAO”
@ManagedBean
和@Controller
注释,所有注释都在一起。在属性“BasicDAO”
中,我必须使用Spring的@Autowired
@ManagedBean
vs@Controller
首先,您应该选择one框架来管理bean。您应该选择JSF或Spring(或CDI)来管理bean。虽然以下方法可行,但它从根本上是错误的:
@ManagedBean // JSF-managed.
@Controller // Spring-managed.
public class BadBean {}
最后,您将得到同一托管bean类的两个完全独立的实例,一个由JSF管理,另一个由Spring管理。当您将EL引用为{someBean}
时,并不直接清楚在EL中实际使用的是哪一个。如果您在faces config.xml
中注册了,那么它将是Spring管理的,而不是JSF管理的。如果没有,那么它将是JSF管理的
另外,当您从javax.faces.*
包中声明JSF托管bean特定的作用域时,例如@RequestScoped
、@ViewScoped
、@SessionScoped
或@ApplicationScoped
,它将只被@ManagedBean
识别和使用。它不会被@Controller
理解,因为它需要自己的@Scope
注释。如果不存在,则默认为singleton(应用程序范围)
@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
@Controller // Spring-managed (without own scope, so actually becomes a singleton).
public class BadBean {}
当您通过{someBean}
引用上述bean时,它将返回Spring管理的应用程序范围bean,而不是JSF管理的视图范围bean
@ManagedProperty
vs@Autowired
特定于JSF的@ManagedProperty
仅在JSF托管bean中有效,即当您使用@ManagedBean
时。特定于Spring的@Autowired
仅在Spring管理的bean中工作,即当您使用@Controller
时。以下方法的等效性较小或较大,不能混合使用:
@ManagedBean // JSF-managed.
@RequestScoped // JSF-managed scope.
public class GoodBean {
@ManagedProperty("#{springBeanName}")
private SpringBeanClass springBeanName; // Setter required.
}
请注意,当您按照
或者,当您的体系结构不允许从不同的基类扩展bean时,您可以始终在Spring Autowiable上下文中手动注册JSF托管bean实例,如下所示。有关技巧,请参见
@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {
@Autowired
private SpringBeanClass springBeanName; // No setter required.
@PostConstruct
private void init() {
FacesContextUtils
.getRequiredWebApplicationContext(FacesContext.getCurrentInstance())
.getAutowireCapableBeanFactory().autowireBean(this);
// springBeanName is now available.
}
}
@XxxScoped
vs@Scope
Spring的@Scope
对JSF作用域的支持有限。JSF的@ViewScoped
没有等价物。基本上,您要么自行扩展自己的作用域,要么坚持在Spring Autowiable上下文中手动注册JSF托管bean实例,如上所示
另一方面,SpringWebFlow在JSF2.2中通过新的@FlowScoped
注释被接管。因此,如果您碰巧已经使用了JSF2.2,那么如果您只想使用流范围,就不一定需要使用SpringWebFlow
CDI-试图将其统一起来 自JavaEE6以来,CDI作为SpringDI的标准替代品提供。它分别有
@命名的
和@注入的
注释以及自己的作用域集。我不确定它是如何与Spring交互的,因为我没有使用Spring,但是@Inject
在@ManagedBean
中工作,而@ManagedBean
中的@ManagedProperty
可以引用@命名的bean。另一方面,@ManagedProperty
在名为@的bean中不起作用
CDI的目的是将所有不同的bean管理框架统一到一个规范/接口中。Spring本可以是一个完整的CDI实现,但他们选择只部分实现它(只支持JSR-330javax.inject.
,但不支持JSR-299javax.enterprise.context.
)。另见和
JSF将转向CDI进行bean管理,并在将来的版本中弃用@ManagedBean
和friends
@Named // CDI-managed.
@ViewScoped // CDI-managed scope.
public class BetterBean implements Serializable {
@Inject
private SpringBeanClass springBeanName; // No setter required.
@PostConstruct
private void init() {
// springBeanName is now available.
}
}
另见:
实现这一点的简单方法是通过XML。我在已经制作好的jsf托管bean中使用了
@Component
,但是@Autowired
不起作用,因为托管bean已经存在于faces-config.xml中。如果必须在xml文件中保留该托管bean定义及其托管属性,则建议在托管bean标记中添加Springbean作为另一个托管属性。这里Springbean在spring config.xml中定义(可以在其他地方自动连接)。请参阅
由我编辑。我建议要么通过注释@Managed和@Component来实现它,要么通过xml来实现两者。在JSF托管bean中使用Spring托管bean还有另一种方法,只需从SpringBeanAutowiringSupport
扩展JSF bean,Spring就会处理依赖注入
@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport {
@Autowired
private SpringBeanClass springBeanName; // No setter required.
// springBeanName is now available.
}
您说过:“特定于JSF的@ManagedProperty只在JSF托管bean中起作用,即当您使用@ManagedBean时”。但是我使用@ManagedProperty引用了一个Springbean,这很好用。我是怎么说的:我正在使用@ManagedProperty(#{'basicDAO'),bean'basicDAO'是@Repository bean。@ManagedProperty是集成sp的方法(我遇到过)
@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {
@Autowired
private SpringBeanClass springBeanName; // No setter required.
@PostConstruct
private void init() {
FacesContextUtils
.getRequiredWebApplicationContext(FacesContext.getCurrentInstance())
.getAutowireCapableBeanFactory().autowireBean(this);
// springBeanName is now available.
}
}
@Named // CDI-managed.
@ViewScoped // CDI-managed scope.
public class BetterBean implements Serializable {
@Inject
private SpringBeanClass springBeanName; // No setter required.
@PostConstruct
private void init() {
// springBeanName is now available.
}
}
@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport {
@Autowired
private SpringBeanClass springBeanName; // No setter required.
// springBeanName is now available.
}