gpt4 book ai didi

java - 使用 CDI @Inject 注入(inject) Spring bean

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:07:33 26 4
gpt4 key购买 nike

我试图将在 Spring 上下文中定义的 bean 注入(inject)到 CDI 托管组件中,但我没有成功。该 bean 没有被注入(inject),而是每次执行注入(inject)时都会创建一个新实例。我的环境是带有 JBoss Weld 的 Tomcat 7。

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>

但是,当我从 JSF 页面中访问 test 属性时,每次访问都会创建一个新的 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 都会返回 Spring 上下文中定义的 bean 的值。然而,第二个输出清楚地表明,每次调用 test 组件上的 getTest 方法时,都会创建并注入(inject)一个新的 Test 实例,而不是如我所料,使用 Spring 上下文中的实例。

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

如何将 Spring 上下文中的 bean 注入(inject)到 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;

最佳答案

Pascal 是对的,您不能将 spring 管理的东西注入(inject) weld 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;

附言您可以使上面的代码更加类型安全。您可以通过反射获取注入(inject)点的通用类型,并在 spring 上下文中查找它,而不是通过名称获取 bean。

关于java - 使用 CDI @Inject 注入(inject) Spring bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4144039/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com