我正在尝试将在春季上下文中定义的bean注入CDI托管组件中,但我没有成功。未注入豆子,而是每次进行注射时都会创建一个新实例。我的环境是带有JBOSS WELD的Tomcat 7。

Spring ApplicationContext直截了当:

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

CDI托管豆看起来像这样:

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

<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 从弹簧上下文中定义的bean返回值。但是第二个输出清楚地表明,每次 getTest 方法 test 调用组件,一个新的 Test 创建和注入实例,而不是像我期望的那样从春季上下文中使用实例。

那么,这种行为的原因是什么?

如何将Bean从春季上下文注入CDI托管豆?

我还尝试使用春季上下文中定义的名称使用限定符,但是现在抛出了一个例外,表明找不到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;
有帮助吗?

解决方案

Pascal是正确的,您不能将Spring管理的东西注入焊接豆(或反之亦然)。

但是,您可以定义一个生产商,该生产商可以获取弹簧豆并将其焊接。这听起来像是一个极端的黑客,顺便说一句,我认为您不应该在一个项目中使用两个框架。选择一个并删除另一个。否则您将遇到多个问题。

这就是外观。

@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;

PS您可以使上述更具类型的安全性。您可以通过反射来获得注射点的通用类型,而不是通过名称获得豆子,并在春季上下文中查找。

其他提示

我认为焊缝不能注入未通过焊缝管理(实例化)的东西(在您的情况下是弹簧豆)。

还有JBOSS Snowdrop项目。我不知道它是否会在Tomcat上与JBoss Weld一起使用,该文档仅在JBOSS 5、6和7上描述。 http://docs.jboss.org/snowdrop/2.0.0.final/html/ch03.html#d0e618 它将在jboss-spring.xml中注入bean,以@spring而不是@Inject标记的位置。 YMMV,我没有经验。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top