복붙노트

[SPRING] CDI @Inject를 사용하여 Spring 빈 삽입하기

SPRING

CDI @Inject를 사용하여 Spring 빈 삽입하기

Spring 컨텍스트에 정의 된 Bean을 CDI 관리 구성 요소에 주입하려고하는데 성공하지 못했습니다. 빈은 주입되지 않고 대신 주입이 수행 될 때마다 새로운 인스턴스가 생성됩니다. 내 환경은 JBoss Weld가있는 Tomcat 7입니다.

Spring ApplicationContext는 매우 어렵다.

<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>

그러나 JSF 페이지 내에서 테스트 특성에 액세스하면 액세스가 발생할 때마다 새 테스트 인스턴스가 작성됩니다. 이것은 간단한 예입니다.

<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 메서드가 호출 될 때마다 예상대로 Spring 컨텍스트의 인스턴스를 사용하는 대신 새 테스트 인스턴스가 만들어지고 주입된다는 것을 분명하게 보여줍니다.

그래서,이 행동의 이유는 무엇입니까?

Spring 컨텍스트의 빈을 CDI 관리 빈에 삽입하려면 어떻게해야합니까?

또한 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;

해결법

  1. ==============================

    1.파스칼은 용접 콩에 스프링으로 관리되는 것을 주입 할 수 없다는 것입니다 (또는 그 반대).

    파스칼은 용접 콩에 스프링으로 관리되는 것을 주입 할 수 없다는 것입니다 (또는 그 반대).

    그러나 스프링 콩을 가져 와서 용접하게하는 제작자를 정의 할 수 있습니다. 이것은 극단적 인 해킹, btw처럼 들리지만 한 프로젝트에서 두 프레임 워크를 모두 사용하지 않아도된다고 생각합니다. 하나를 선택하고 다른 하나를 제거하십시오. 그렇지 않으면 여러 가지 문제가 발생할 것입니다.

    다음과 같이 보입니다.

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

    추신 위의 내용을 더 안전하게 만들 수 있습니다. bean을 이름으로 얻는 대신, 주입 지점의 일반적인 유형을 반사를 통해 얻을 수 있으며, 봄 문맥에서 찾아 볼 수 있습니다.

  2. ==============================

    2.나는 Weld가 Weld (귀하의 경우에는 Spring bean)에 의해 관리되지 않는 (인스턴스화 된) 것을 주입 할 수 있다고 생각하지 않습니다.

    나는 Weld가 Weld (귀하의 경우에는 Spring bean)에 의해 관리되지 않는 (인스턴스화 된) 것을 주입 할 수 있다고 생각하지 않습니다.

  3. ==============================

    3.JBoss Snowdrop 프로젝트도 있습니다. Tomcat에서 JBoss Weld와 함께 작동하는지 모르겠습니다. 설명서는 JBoss 5, 6 및 7에서만 설명합니다. http://docs.jboss.org/snowdrop/2.0.0.Final/html/에 따르면 ch03.html # d0e618 @Inject 대신 @Spring으로 표시된 위치에 jboss-spring.xml에 선언 된 bean을 삽입합니다. 경험이 없습니다. YMMV.

    JBoss Snowdrop 프로젝트도 있습니다. Tomcat에서 JBoss Weld와 함께 작동하는지 모르겠습니다. 설명서는 JBoss 5, 6 및 7에서만 설명합니다. http://docs.jboss.org/snowdrop/2.0.0.Final/html/에 따르면 ch03.html # d0e618 @Inject 대신 @Spring으로 표시된 위치에 jboss-spring.xml에 선언 된 bean을 삽입합니다. 경험이 없습니다. YMMV.

  4. from https://stackoverflow.com/questions/4144039/injecting-a-spring-bean-using-cdi-inject by cc-by-sa and MIT license