2010-11-10 14 views
5

Próbuję wstrzyknąć komponent bean zdefiniowany w kontekście Spring do komponentu zarządzanego przez CDI, ale nie udaje mi się. Ziarno nie jest wstrzykiwane, zamiast tego tworzone jest nowe wystąpienie za każdym razem, gdy należy wykonać iniekcję. Moje środowisko to Tomcat 7 z JBoss Weld.Wstrzyknięcie fasoli Spring za pomocą CDI @ Inject

The Spring ApplicationContext jest straighforward:

<beans> 
    ... 
    <bean id="testFromSpring" class="test.Test" /> 
    ... 
</bean> 

CDI udało fasola wygląda następująco:

@javax.inject.Named("testA") 
public class TestA { 

    @javax.inject.Inject 
    private Test myTest = null; 

    ... 

    public Test getTest() { 
    return this.myTest; 
    } 

} 

To jest mój 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> 

Jednak, kiedy dostęp do test właściwość ze strony JSF, nowaInstancjajest tworzona za każdym razem, gdy pojawia się dostęp. To jest prosty przykład:

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

uzyskać następujące dane wyjściowe:

1: [email protected] 
2: [email protected] 

Po odświeżeniu:

1: [email protected] 
2: [email protected] 

widzę, że pierwsze wyjście jest prawidłowe. Bez względu na częstotliwość odświeżania strony, testFromSpring zwraca wartość z komponentu bean zdefiniowanego w kontekście Spring. Jednak drugie wyjście wyraźnie pokazuje, że za każdym razem, gdy wywoływana jest metoda getTest na komponentach test, tworzona jest nowa instancja Test i wstrzykiwana zamiast użycia instancji z kontekstu Spring, jak można się spodziewać.

Jaki jest powód takiego zachowania?

Jak wstrzyknąć fasolę z kontekstu sprężyny do komponentu zarządzanego przez komponent CDI?

Próbowałem też za pomocą kwalifikatora przy użyciu nazwy zdefiniowanej w kontekście wiosennej, ale teraz jest wyjątek wskazuje, że fasola nie można znaleźć:

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

kodu

@javax.inject.Named("testA") 
public class TestA { 

    @javax.inject.Inject 
    @javax.inject.Named("testFromSpring") 
    private Test myTest = null; 
+0

To może być brak kawy tutaj, ale po co wstrzykiwać prywatnego członka twojej klasy (która jest już ustawiona na zero). Czy nie byłoby prostsze udostępnienie testu myTest jako części konstruktora TestA (np. Iniektora Constructor)? –

+0

Zastrzyk jest tylko przykładem, a nie punktem pytania. – perdian

Odpowiedz

12

Pascal ma rację, że nie można wstrzyknąć czegoś, co zostało opanowane przez sprężynę do fasoli spawalniczej (lub odwrotnie).

Ale możesz zdefiniować producenta, który otrzyma fasolę szparagową i przekaże go do Spawania. To brzmi jak ekstremalny hack, btw, i nie sądzę, że powinieneś używać obu frameworków w jednym projekcie. Wybierz jedną i usuń drugą. W przeciwnym razie pojawi się wiele problemów.

Oto jak to będzie wyglądać.

@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); 
    } 
} 

Wtedy można mieć:

@Inject @SpringBean("fooBean") 
private Foo yourObject; 

PS: Możesz sprawić, że powyższe będzie bardziej bezpieczne dla użytkowników. Zamiast otrzymywać fasolę po imieniu, można uzyskać, poprzez odbicie, ogólny rodzaj punktu wtrysku i sprawdzić go w kontekście wiosny.

+0

Nie można utworzyć obiektu i dopasować za pomocą punktu wtrysku Foo w CDI – kaos

4

Nie sądzę, że Weld może wstrzykiwać coś, co nie jest zarządzane (tworzone) przez Weld (Spring bean w twoim przypadku).

2

Jest także projekt Przebiśnieg JBoss. Nie wiem, czy będzie działać z JBoss Weld na Tomcat, dokumentacja opisuje tylko JBoss 5, 6 i 7. Zgodnie z http://docs.jboss.org/snowdrop/2.0.0.Final/html/ch03.html#d0e618 będzie wstrzykiwać fasole zadeklarowane w jboss-spring.xml w lokalizacjach oznaczonych @Spring zamiast @Wstrzykiwać. Nie mam jednak doświadczenia, YMMV.