복붙노트

[SPRING] AnnotationConfigApplicationContext 및 부모 컨텍스트

SPRING

AnnotationConfigApplicationContext 및 부모 컨텍스트

AnnotationConfigApplicationContext를 사용하여 컨텍스트 계층 구조를 정의하려고 할 때 문제가 있습니다.

문제는 beanRefContext.xml 안에 모듈 컨텍스트를 정의하고 다른 컨텍스트 (XML / Annotated 기반)로 'parent'속성을 설정할 때입니다.

예:

모듈 A의 beanRefContext.xml

<bean id="moduleA_ApplicationContext"  
      class="org.springframework.context.support.ClassPathXmlApplicationContext">
    <property name="configLocations">
        <list>
            <value>classpath:db-context.xml</value>
        </list>
    </property>
</bean>

db-context.xml

<bean id="dataSource" 
      class="org.apache.commons.dbcp.BasicDataSource" 
      destroy-method="close"
      p:driverClassName="org.h2.Driver"
      p:url="jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MODE=MySQL;TRACE_LEVEL_SYSTEM_OUT=2"/>

<!-- Hibernate Session Factory -->
<bean name="sessionFactory" 
      class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="useTransactionAwareDataSource" value="true"/>
        <property name="packagesToScan">
            <list>
                <value>com.example.model</value>
            </list>
        </property>
        <property name="hibernateProperties">
        <!-- hibernate props -->
        </property>
</bean>

모듈 B의 beanRefContext.xml

<bean id="moduleB_ApplicationContext" 
      class="org.springframework.context.annotation.AnnotationConfigApplicationContext" >
    <property name="parent" ref="moduleA_ApplicationContext"/>
        <constructor-arg>
            <list>
                <value>com.example.dao</value>
            </list>
        </constructor-arg>
</bean>

FooHibernateDao

class FooHibernateDao implements FooDao {
    @Autowired
    @Qualifier("sessionFactory")
    private SessionFactory sessionsFactory;

    // CRUD methods
}

모듈 B 응용 프로그램 컨텍스트가 모듈 A 응용 프로그램 컨텍스트에 정의 된 bean을 찾지 못합니다. AnnotationConfigApplicationContext의 코드를 살펴보면 스캐닝 프로세스가 부모를 참조로 사용하여 콩을 처리하지 못하는 것처럼 보입니다.

내가 틀린 일이 있거나 어노테이션 구성으로 계층 구조를 만들려는 시도가 불가능합니까?

해결법

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

    1.이 문제는 AnnotationConfigApplicationContext의 생성자가 검사를 수행한다는 사실에서 기인합니다. 따라서 부모는이 단계에서 설정되지 않습니다. 부모가 속성에 의해 설정되므로 검사가 완료된 후에 만 ​​설정됩니다. 따라서 빈을 찾지 못한 이유입니다.

    이 문제는 AnnotationConfigApplicationContext의 생성자가 검사를 수행한다는 사실에서 기인합니다. 따라서 부모는이 단계에서 설정되지 않습니다. 부모가 속성에 의해 설정되므로 검사가 완료된 후에 만 ​​설정됩니다. 따라서 빈을 찾지 못한 이유입니다.

    기본 AnnotationConfigApplicationContext 빈에는 부모 팩토리를 사용하는 생성자가 없습니다. 그 이유는 확실하지 않습니다.

    일반 xml 기반 응용 프로그램 컨텍스트를 사용하고 거기에서 주석 검색을 구성하거나 주석 응용 프로그램 컨텍스트를 만들 사용자 지정 fatory bean을 만들 수 있습니다. 그러면 부모 참조가 지정되고 검사가 수행됩니다.

    소스를 한번보세요 ...

    공장은 다음과 같이 보일 것이다.

    public class AnnotationContextFactory implements FactoryBean<ApplicationContext> {
    
    private String[] packages;
    private ApplicationContext parent;
    
    @Override
    public ApplicationContext getObject() throws Exception {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.setParent(parent);
        context.scan(packages);
        context.refresh();
        return context;
    }
    
    @Override
    public Class<ApplicationContext> getObjectType() {
        return ApplicationContext.class;
    }
    
    @Override
    public boolean isSingleton() {
        return true;
    }
    
    public void setPackages(String... args) {
        this.packages = args;
    }
    
    public void setParent(ApplicationContext parent) {
        this.parent = parent;
        }
    }
    

    그리고 당신의 bean 정의 :

    <bean id="moduleB_ApplicationContext" class="za.co.test2.AnnotationContextFactory">
        <property name="parent" ref="moduleA_ApplicationContext" />
        <property name="packages">
            <list>
                <value>za.co.test2</value>
            </list>
        </property>
    </bean>
    
  2. ==============================

    2.XML을 하위 컨텍스트에 사용하지 마십시오. ctx.setParent를 사용하고 ctx.register를 사용하십시오. 이렇게 :

    XML을 하위 컨텍스트에 사용하지 마십시오. ctx.setParent를 사용하고 ctx.register를 사용하십시오. 이렇게 :

    public class ParentForAnnotationContextExample {
    
        public static void main(String[] args) {
            ApplicationContext parentContext = new AnnotationConfigApplicationContext(ParentContext.class);
    
            AnnotationConfigApplicationContext childContext = new AnnotationConfigApplicationContext();
            childContext.setParent(parentContext);
            childContext.register(ChildContext.class); //don't add in the constructor, otherwise the @Inject won't work
            childContext.refresh();
    
            System.out.println(childContext.getBean(ParentBean.class));
            System.out.println(childContext.getBean(ChildBean.class));
    
            childContext.close();
        }
    
        @Configuration
        public static class ParentContext {
            @Bean ParentBean someParentBean() {
                return new ParentBean();
            }
        }
    
        @Configuration
        public static class ChildContext {
            @Bean ChildBean someChildBean() {
                return new ChildBean();
            }
        }
    
        public static class ParentBean {}
    
        public static class ChildBean {
            //this @Inject won't work if you use ChildContext.class in the child AnnotationConfigApplicationContext constructor
            @Inject private ParentBean injectedFromParentCtx;
        }
    }
    
  3. ==============================

    3.나는 같은 문제를 겪는다.

    나는 같은 문제를 겪는다.

    또 다른 가능성은 Java에서 AnnotationConfigApplicationContext를 인스턴스화하는 경우 AnnotationConfigApplicationContext를 확장하고 필요한 생성자 만 추가하거나 프로그램 적으로 컨텍스트를 빌드하는 것입니다.

  4. ==============================

    4.내가 한 일은 다음과 같다.

    내가 한 일은 다음과 같다.

    BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance("classpath:beanRefContext.xml");
    BeanFactoryReference parentContextRef = locator.useBeanFactory("ear.context");
    ApplicationContext parentContext = (ApplicationContext) parentContextRef.getFactory();
    childContext.setParent(parentContext);
    

    그리고 그것은 무엇일까요?

    추신 : 누구든지 classpath : beanRefContext.xml을 @Configuration 클래스로 대체하는 방법을 알고 있다면 알려주십시오.

  5. from https://stackoverflow.com/questions/4364221/annotationconfigapplicationcontext-and-parent-context by cc-by-sa and MIT license