我知道托管bean的工作方式类似于控制器,因为您的唯一任务是将View Layer与Model“链接”。
要将bean用作托管bean,我必须声明@ManagedBean
注释,这样做我可以直接与bean通信JSF。
如果我想在这个managedBean中注入一些组件(来自Spring),我有两种可能的方法:
在ManagedBean中选择属性(如“BasicDAO dao”)并在属性上方声明@ManagedProperty(#{"basicDAO"})
。这样做,我在ManagedBean中从Spring注入bean "basicDAO"
。
在ManagedBean Class中声明了@Controller,然后我将同时拥有@ManagedBean
和@Controller
注释。在属性"BasicDAO dao"
中,我必须使用Spring的@Autowired
。
我的理解是否正确?
答案 0 :(得分:75)
@ManagedBean
vs @Controller
首先,您应该选择一个框架来管理您的bean。您应该选择JSF或Spring(或CDI)来管理您的bean。虽然以下工作,但从根本上说是错误的:
@ManagedBean // JSF-managed.
@Controller // Spring-managed.
public class BadBean {}
你最终得到了同一个托管bean类的两个完全独立的实例,一个由JSF管理,另一个由Spring管理。当你将它作为#{someBean}
引用时,并不清楚哪一个实际在EL中使用。如果您在faces-config.xml
中注册SpringBeanFacesELResolver
,则它将由Spring管理,而不是由JSF管理的。{1}}。如果你没有,那就是JSF管理的那个。
此外,当您声明JSF托管bean特定范围时,例如@RequestScoped
包中的@ViewScoped
,@SessionScoped
,@ApplicationScoped
或javax.faces.*
只有@ManagedBean
才能识别和使用。 @Controller
不会理解它,因为它期望自己的@Scope
注释。缺席时,默认为单例(应用程序范围)。
@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.
}
@Component // Spring-managed.
@Scope("request") // Spring-managed scope.
public class GoodBean {
@Autowired
private SpringBeanClass springBeanName; // No setter required.
}
请注意,根据SpringBeanFacesELResolver
faces-config.xml
在<application>
...
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
注册javadoc时,
#{springBeanName}
因此您可以通过@ManagedProperty
在EL中引用Spring托管bean,然后您也可以在@Autowired
中引用它们,因为它基本上设置了给定EL表达式的评估结果。反过来说,通过@Autowired
注入JSF托管bean是不可支持的。但是,当您在Spring自动上传的上下文中手动注册JSF托管bean实例时,可以在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.
}
}
。另请参阅How to integrate JSF 2 and Spring 3 (or Spring 4) nicely了解诀窍。
@XxxScoped
@Scope
vs @Scope
Spring的@ViewScoped
对JSF范围的支持有限。 JSF的@FlowScoped
没有等价物。您基本上要么自己创建自己的作用域,要么坚持在Spring自动化上下文中手动注册JSF托管bean实例,如上所示。
而且,另一方面,Spring WebFlow通过新的@Named
注释在JSF 2.2中被接管。因此,如果您刚好使用JSF 2.2,那么如果您只想要流量范围,则不一定需要使用Spring WebFlow。
自Java EE 6起,CDI作为Spring DI的标准替代品提供。它分别有@Inject
和@Inject
注释以及它自己的范围集。我不确定它是如何与Spring交互的,因为我不使用Spring,但@ManagedBean
在@ManagedProperty
内部工作,而@ManagedBean
内的@Named
可以引用{ {1}} bean。另一方面,@ManagedProperty
在@Named
bean中不起作用。
CDI的目的是将所有不同的bean管理框架统一到一个规范/接口中。 Spring可能是一个完整的CDI实现,但他们选择只部分实现它(仅支持JSR-330 javax.inject.*
,但不支持JSR-299 javax.enterprise.context.*
)。另请参阅Will Spring support CDI?和this tutorial。
JSF将转向CDI进行bean管理,并在将来的版本中弃用@ManagedBean
和朋友。
答案 1 :(得分:6)
通过简单地从SpringBeanAutowiringSupport
扩展JSF bean,还有另一种方法可以在JSF管理的bean中使用Spring管理的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.
}
答案 2 :(得分:1)
这样做的简单方法是通过XML。我在已经创建的jsf托管bean中使用了.directive('scrollBottom', ['$timeout' , function ($timeout) {
return {
link: function (scope, element) {
$timeout(function () {
console.log($(element).scrollTop())
$(element).scrollTop($(element)[0].scrollHeight)
})
}
}
}
但是@Component
没有用,因为托管bean已经存在于faces-config.xml中。如果必须将该托管bean定义及其托管属性保留在xml文件中,则建议将spring bean添加为托管bean标记内的另一个托管属性。这里的spring bean是在spring-config.xml中定义的(可以在某处交替自动装配)。请参考
https://stackoverflow.com/a/19904591/5620851
由我编辑。我建议通过注释@Managed和@Component或通过xml完全实现它。