使用CDI @Inject注入Spring bean [英] Injecting a Spring bean using CDI @Inject
问题描述
我正在尝试将Spring上下文中定义的bean注入CDI托管组件,但我没有成功。不注入bean,而是每次执行注入时都会创建一个新实例。我的环境是使用JBoss Weld的Tomcat 7.
I'm trying to inject a bean defined in a Spring context into a CDI managed component but I'm not successful. The bean is not injected, instead a new instance gets created each time the injection should be performed. My environment is Tomcat 7 with JBoss Weld.
Spring ApplicationContext是直接的:
The Spring ApplicationContext is straighforward:
<beans>
...
<bean id="testFromSpring" class="test.Test" />
...
</bean>
CDI托管bean如下所示:
The CDI managed bean looks like this:
@javax.inject.Named("testA")
public class TestA {
@javax.inject.Inject
private Test myTest = null;
...
public Test getTest() {
return this.myTest;
}
}
这是我的 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>
但是,当我访问 test
属性时在JSF页面中,每次访问时都会创建一个新的 Test
实例。这是一个简单的例子:
However, when I access the test
property from within a JSF page, a new Test
instance is being created each time the access occurs. This is a simple example:
<html>
...
<p>1: <h:outputText value="#{testFromSpring}" /></p>
<p>2: <h:outputText value="#{testA.test}" /></p>
...
我得到以下输出:
1: test.Test@44d79c75
2: test.Test@53f336eb
刷新后:
1: test.Test@44d79c75
2: test.Test@89f2ac63
我可以看到第一个输出是正确的。无论我多久刷新一次页面, testFromSpring
都会返回Spring上下文中定义的bean的值。但是第二个输出清楚地表明每次调用 test
组件上的 getTest
方法时,新的 Test
实例被创建并注入,而不是像我期望的那样使用Spring上下文中的实例。
I can see that the first output is correct. No matter how often I refresh the page, the testFromSpring
returns the value from the bean defined in the Spring context. However the second output clearly shows that each time the getTest
method on the test
components is invoked, a new Test
instance is created and injected instead of using the instance from the Spring context as I would expect.
那么,是什么原因对于这种行为?
So, what's the reason for this behaviour?
如何将Spring上下文中的bean注入CDI托管bean?
How can I inject the bean from the Spring context into the CDI managed bean?
我也尝试过使用使用Spring上下文中定义的名称的限定符,但现在抛出一个异常,表明找不到bean:
I also tried using a qualifier using the name defined in the Spring context, but now an exception is thrown indicating, that the bean cannot be found:
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Injection point has unsatisfied dependencies. Injection point: field test.TestA.myTest; Qualifiers: [@javax.inject.Named(value=testFromSpring)]
代码
@javax.inject.Named("testA")
public class TestA {
@javax.inject.Inject
@javax.inject.Named("testFromSpring")
private Test myTest = null;
推荐答案
Pascal是对的,你不能注入管理的东西通过spring进入焊接bean(反之亦然)。
Pascal is right that you can't inject something managed by spring into a weld bean (or vice-versa).
但是你可以定义一个生成器来获取spring bean并将它们提供给Weld。这听起来像一个极端的黑客,顺便说一句,我不认为你应该在一个项目中使用这两个框架。选择一个并删除另一个。否则你会遇到多个问题。
But you can define a producer that gets spring beans and gives them to Weld. This sounds like an extreme hack, btw, and I don't think you are supposed to use both frameworks in one project. Choose one and remove the other. Otherwise you'll get in multiple problems.
这是它的样子。
@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);
}
}
然后你可以:
@Inject @SpringBean("fooBean")
private Foo yourObject;
P.S。您可以使上述类型更安全。您可以通过反射获得注入点的泛型类型,并在弹簧上下文中查找它,而不是按名称获取bean。
P.S. You can make the above more type-safe. Instead of getting the bean by name, you can get, through reflection, the generic type of the injection point, and look it up in the spring context.
这篇关于使用CDI @Inject注入Spring bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!