2010-11-10 228 views
5

我想将一个在Spring上下文中定义的bean注入CDI托管组件,但是我不成功。该bean没有被注入,而是每次执行注入时创建一个新的实例。我的环境是JBoss Weld的Tomcat 7。使用CDI注入Spring bean @Inject

Spring的ApplicationContext是简单明了:

<beans> 
    ... 
    <bean id="testFromSpring" class="test.Test" /> 
    ... 
</bean> 

的CDI托管bean看起来是这样的:

@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页面的财产,新的每次访问发生时都会创建实例。这是一个简单的例子:

<html> 
    ... 
    <p>1: <h:outputText value="#{testFromSpring}" /></p> 
    <p>2: <h:outputText value="#{testA.test}" /></p> 
    ... 

我得到以下输出:

1: [email protected] 
2: [email protected] 

刷新后:

1: [email protected] 
2: [email protected] 

我可以看到第一个输出是正确的。无论刷新页面的频率如何,testFromSpring都会返回Spring上下文中定义的bean的值。然而,第二个输出清楚地表明,每当test组件的getTest方法被调用时,就会创建一个新的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)] 

的代码

@javax.inject.Named("testA") 
public class TestA { 

    @javax.inject.Inject 
    @javax.inject.Named("testFromSpring") 
    private Test myTest = null; 
+0

这可能是缺少咖啡的原因,但为什么要注入一个私人成员(已经设置为空)。将myTest作为TestA构造函数的一部分提供(例如构造函数注入)并不简单吗? – 2010-11-10 12:07:57

+0

注入仅仅是一个例子,而不是问题的要点。 – perdian 2010-11-10 15:06:10

回答

12

帕斯卡是正确的,你不能注入一些由弹簧管理的东西到焊接bean(反之亦然)。

但是你可以定义一个生产者,获取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); 
    } 
} 

然后,你可以有:

@Inject @SpringBean("fooBean") 
private Foo yourObject; 

附:你可以使上面的类型更安全。您可以通过反射来获取注入点的通用类型,而不是通过名称获取该bean,并在春季环境中查找它。

+0

您无法生成Object并与CDI中的Foo注入点匹配 – kaos 2017-11-14 13:06:59

4

我不认为Weld可以注入Weld没有管理(实例化)的东西(在你的情况下是一个Spring bean)。