当前位置: 首页 > 面试题库 >

使用CDI @Inject注入Spring bean

皇甫展
2023-03-14
问题内容

我试图将在Spring上下文中定义的bean注入到CDI托管组件中,但没有成功。不会注入Bean,而是在每次执行注入时都会创建一个新实例。我的环境是带有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>

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

问题答案:

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

但是您可以定义一个生产者,该生产者获取春豆并将其提供给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,而是可以通过反射获取注入点的通用类型,并在spring上下文中进行查找。



 类似资料:
  • 问题内容: 当前,我正在使用PersistenceContext注入EntityManager。EM被完美注入。 现在,我尝试装饰Bean,然后突然没有注入em。我得到一个NullPointerException。 我知道EJB和CDI是2个完全不同的管理器,所以一个都不知道另一个。我期望@PersistenceContext是EJB注入点,而@Inject是CDI。我应该怎么做才能解决这个问题并

  • 我在CDI条件注射中遇到了问题,无法在EJB的注射中使用一种策略。 我的实际情况是: 好吧,场景解释了。现在的问题是,我需要得到的值从返回一个,我的所必需的。但是此时有些Bean还没有被CDI注射。 我怎样才能让这条线起作用? 使用基于另一个注入的属性值的限定符动态注入bean的正确方法是什么?

  • (子资源)再次基于构造函数中传入的用户实现为普通的Jersey类。 但是,我的子资源也需要访问字段(如或)。根据Jersey文档,字段不会为子资源注入,因为它们的生命周期未知(文档似乎是真的)。 这对我来说是非常不可原谅的:我真的需要访问这些值。 作为一种解决办法,我目前将这些值作为额外的构造函数参数传递给我的子资源,我认为这一切都不舒服。 我能以某种方式创建这些映射吗? 问题是,我不知道如何在G

  • 使用 @Inject 注解可以向 Controller 以及 Interceptor 中注入依赖对象,使用注入功能需要如下配置: public void configConstant(Constants me) { // 开启对 jfinal web 项目组件 Controller、Interceptor、Validator 的注入 me.setInjectDependency(t

  • 问题内容: 我怎样才能像注入的依赖,,,,等的?在我的特定情况下,我需要通过以下方式注入Spring托管的: 但是,它没有注入,而是保留了null,导致。似乎,并且t也不起作用。 如何在验证器中注入服务依赖项,以便可以访问数据库? 问题答案: 在不被注入容器管理。你需要使其成为托管bean。使用Spring ,CDI @Named或JSF 代替,以便使其成为托管bean,从而有资格进行依赖项注入。

  • 我正在尝试使用JAX-RS(泽西岛)创建一个简单的REST服务,而不使用Spring。我想要有典型的结构:资源,使用服务(典型接口与方法,查找全部...),并且该服务注入到资源中。 似乎CDI会自动扫描豆子并注入它们(在项目中有一个空),但是......它不适合我。 这是我的资源类: 这是我的服务及其impl类(这是一个模拟...): 我在这个类中使用了“无web.xml”配置: 我发现的唯一解决