使用CDI @Inject注入Spring bean

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

Spring ApplicationContext是直截了当的:

 ...  ...  

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

   org.springframework.web.jsf.el.SpringBeanFacesELResolver   

但是,当我从JSF页面访问test属性时,每次访问时都会创建一个新的Test实例。 这是一个简单的例子:

  ... 

1:

2:

...

我得到以下输出:

 1: test.Test@44d79c75 2: test.Test@53f336eb 

刷新后:

 1: test.Test@44d79c75 2: test.Test@89f2ac63 

我可以看到第一个输出是正确的。 无论我多久刷新一次页面, testFromSpring返回Spring上下文中定义的bean的值。 但是第二个输出清楚地表明,每次调用test组件上的getTest方法时,都会创建并注入一个新的Test实例,而不是像我期望的那样使用Spring上下文中的实例。

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

如何将Spring上下文中的bean注入CDI托管bean?

我也尝试使用在Spring上下文中定义的名称的限定符,但现在抛出一个exception,表明找不到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管理的东西注入焊接豆(反之亦然)。

但是你可以定义一个获取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; 

PS你可以使上面的类型更安全。 不是通过名称获取bean,而是通过reflection获得注入点的generics类型,并在spring上下文中查找它。

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

还有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。