Инъекция Spring bean с использованием CDI @Inject - PullRequest
9 голосов
/ 10 ноября 2010

Я пытаюсь внедрить bean-компонент, определенный в контексте Spring, в управляемый компонент CDI, но мне это не удается.Бин не внедряется, вместо этого создается новый экземпляр каждый раз, когда необходимо выполнить внедрение.Моя среда - Tomcat 7 с JBoss Weld.

SpringConContext является простым:

<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 возвращает значение из компонента, определенного в контексте Spring.Однако второй вывод ясно показывает, что каждый раз, когда вызывается метод getTest для компонентов test, создается и внедряется новый экземпляр Test вместо использования экземпляра из контекста Spring, как я и ожидал.

Итак, в чем причина такого поведения?

Как я могу внедрить bean-компонент из контекста Spring в управляемый bean-компонент CDI?

Я также пытался использовать квалификатор, используя имя, определенное в контексте Spring, но теперь выдается исключение, указывающее, что бин не может быть найден:

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;

Ответы [ 3 ]

14 голосов
/ 10 ноября 2010

Паскаль прав, что вы не можете внедрить что-то, управляемое пружиной, в сварочный бин (или наоборот).

Но вы можете определить производителя, который получает бобы весны и передает их в 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. Вы можете сделатьвыше, более безопасный тип.Вместо того, чтобы получить бин по имени, вы можете, используя отражение, получить общий тип точки внедрения и посмотреть его в контексте весны.

5 голосов
/ 10 ноября 2010

Я не думаю, что Weld может внедрить что-то, что не управляется (не создается) Weld (Spring bean в вашем случае).

2 голосов
/ 07 ноября 2011

Есть также проект JBoss Snowdrop. Я не знаю, будет ли он работать с JBoss Weld на Tomcat, документация описана только на JBoss 5, 6 и 7. Согласно http://docs.jboss.org/snowdrop/2.0.0.Final/html/ch03.html#d0e618 он будет вводить бины, объявленные в jboss-spring.xml, в отмеченные места с @Spring вместо @Inject. Впрочем, опыта нет, YMMV.

...