per*_*ian 10 java jsf spring cdi jboss-weld
我正在尝试将Spring上下文中定义的bean注入CDI托管组件,但我没有成功.不注入bean,而是每次执行注入时都会创建一个新实例.我的环境是使用JBoss Weld的Tomcat 7.
Spring ApplicationContext是直截了当的:
<beans>
...
<bean id="testFromSpring" class="test.Test" />
...
</bean>
Run Code Online (Sandbox Code Playgroud)
CDI托管bean看起来像这样:
@javax.inject.Named("testA")
public class TestA {
@javax.inject.Inject
private Test myTest = null;
...
public Test getTest() {
return this.myTest;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的 faces-config.xml
<faces-config xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd" version="2.0">
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
</faces-config>
Run Code Online (Sandbox Code Playgroud)
但是,当我test从JSF页面访问该属性时,Test每次访问时都会创建一个新实例.这是一个简单的例子:
<html>
...
<p>1: <h:outputText value="#{testFromSpring}" /></p>
<p>2: <h:outputText value="#{testA.test}" /></p>
...
Run Code Online (Sandbox Code Playgroud)
我得到以下输出:
1: test.Test@44d79c75
2: test.Test@53f336eb
Run Code Online (Sandbox Code Playgroud)
刷新后:
1: test.Test@44d79c75
2: test.Test@89f2ac63
Run Code Online (Sandbox Code Playgroud)
我可以看到第一个输出是正确的.无论我多久刷新一次页面,都会testFromSpring返回Spring上下文中定义的bean的值.但是第二个输出清楚地表明,每次调用组件getTest上的方法时test,Test都会创建并注入一个新实例,而不是像我期望的那样使用Spring上下文中的实例.
那么,这种行为的原因是什么?
如何将Spring上下文中的bean注入CDI托管bean?
我也尝试使用在Spring上下文中定义的名称的限定符,但现在抛出一个异常,表明找不到bean:
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Injection point has unsatisfied dependencies. Injection point: field test.TestA.myTest; Qualifiers: [@javax.inject.Named(value=testFromSpring)]
Run Code Online (Sandbox Code Playgroud)
代码
@javax.inject.Named("testA")
public class TestA {
@javax.inject.Inject
@javax.inject.Named("testFromSpring")
private Test myTest = null;
Run Code Online (Sandbox Code Playgroud)
Boz*_*zho 15
Pascal是对的,你不能将由spring管理的东西注入焊接豆(反之亦然).
但是你可以定义一个生成器来获取spring bean并将它们提供给Weld.这听起来像一个极端的黑客,顺便说一句,我不认为你应该在一个项目中使用这两个框架.选择一个并删除另一个.否则你会遇到很多问题.
这是它的样子.
@Qualifier
@Retention(Runtime)
public @interface SpringBean {
@NonBinding String name();
}
public class SpringBeanProducer {
@Produces @SpringBean
public Object create(InjectionPoint ip) {
// get the name() from the annotation on the injection point
String springBeanName = ip.getAnnotations()....
//get the ServletContext from the FacesContext
ServletContext ctx = FacesContext.getCurrentInstance()...
return WebApplicationContextUtils
.getRequiredWebApplication(ctx).getBean(springBeanName);
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以:
@Inject @SpringBean("fooBean")
private Foo yourObject;
Run Code Online (Sandbox Code Playgroud)
PS你可以使上面的类型更安全.您可以通过反射获得注入点的泛型类型,并在spring上下文中查找,而不是通过名称获取bean.
| 归档时间: |
|
| 查看次数: |
14464 次 |
| 最近记录: |