java – 使用CDI @Inject注入Spring bean

前端之家收集整理的这篇文章主要介绍了java – 使用CDI @Inject注入Spring bean前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试将 Spring上下文中定义的bean注入CDI托管组件,但我没有成功.不注入bean,而是每次执行注入时都会创建一个新实例.我的环境是使用JBoss Weld的Tomcat 7.

Spring ApplicationContext是直截了当的:

  1. <beans>
  2. ...
  3. <bean id="testFromSpring" class="test.Test" />
  4. ...
  5. </bean>

CDI托管bean看起来像这样:

  1. @javax.inject.Named("testA")
  2. public class TestA {
  3.  
  4. @javax.inject.Inject
  5. private Test myTest = null;
  6.  
  7. ...
  8.  
  9. public Test getTest() {
  10. return this.myTest;
  11. }
  12.  
  13. }

这是我的faces-config.xml

  1. <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">
  2. <application>
  3. <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
  4. </application>
  5. </faces-config>

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

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

我得到以下输出

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

刷新后:

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

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

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

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

我也尝试使用在Spring上下文中定义的名称的限定符,但现在抛出一个异常,表明找不到bean:

  1. org.jboss.weld.exceptions.DeploymentException: WELD-001408 Injection point has unsatisfied dependencies. Injection point: field test.TestA.myTest; Qualifiers: [@javax.inject.Named(value=testFromSpring)]

代码

  1. @javax.inject.Named("testA")
  2. public class TestA {
  3.  
  4. @javax.inject.Inject
  5. @javax.inject.Named("testFromSpring")
  6. private Test myTest = null;

解决方法

Pascal是对的,你不能将由spring管理的东西注入焊接豆(反之亦然).

但是你可以定义一个生成器来获取spring bean并将它们提供给Weld.这听起来像一个极端的黑客,顺便说一句,我不认为你应该在一个项目中使用这两个框架.选择一个并删除另一个.否则你会遇到很多问题.

这是它的样子.

  1. @Qualifier
  2. @Retention(Runtime)
  3. public @interface SpringBean {
  4. @NonBinding String name();
  5. }
  6.  
  7.  
  8. public class SpringBeanProducer {
  9.  
  10. @Produces @SpringBean
  11. public Object create(InjectionPoint ip) {
  12. // get the name() from the annotation on the injection point
  13. String springBeanName = ip.getAnnotations()....
  14.  
  15. //get the ServletContext from the FacesContext
  16. ServletContext ctx = FacesContext.getCurrentInstance()...
  17.  
  18. return WebApplicationContextUtils
  19. .getrequiredWebApplication(ctx).getBean(springBeanName);
  20. }
  21. }

然后你可以:

  1. @Inject @SpringBean("fooBean")
  2. private Foo yourObject;

附:您可以使上述类型更安全.不是通过名称获取bean,而是通过反射获得注入点的泛型类型,并在spring上下文中查找它.

猜你在找的Java相关文章