복붙노트

[SPRING] Java 구성으로 Autowire setter 재정의

SPRING

Java 구성으로 Autowire setter 재정의

다음 클래스를 고려하십시오.

public class MyBean {
    private A a;

    @Autowired(required=true)
    public void setA(A a) {
        this.a = a;
    }

    public A getA() {
        return a;
    }
}

예를 들어 Spring이 주사를위한 단일 후보를 찾을 수없는 경우와 같이 자동자가 주입을 무시할 필요가있는 경우가 있습니다. XML에서는 다음 예제를 사용할 수 있습니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="first" class="my.pkg.AImpl"/>
    <bean id="second" class="my.pkg.AImpl"/>
    <bean id="myBeanFirst" class="my.pkg.MyBean">
        <property name="a" ref="first"/>
    </bean>
    <bean id="myBeanSecond" class="my.pkg.MyBean">
        <property name="a" ref="second"/>
    </bean>

</beans>

Java Config에서 동일한 작업을 수행 할 수있는 방법이 있습니까? MyBean 메서드에서 반환 된 후 속성 autowire 시도하고 NoUniqueBeanDefinitionException 함께 실패합니다 때문에 다음 작동하지 않습니다 (및 이유를 이해합니다) :

@Configuration
public class MyConfig {
    @Bean
    public A first() {
        return new AImpl();
    }

    @Bean
    public A second() {
        return new AImpl();
    }

    @Bean
    public MyBean myBeanFirst(A first) {
        MyBean myBean = new MyBean();
        myBean.setA(first);
        return myBean;
    }

    @Bean
    public MyBean myBeanSecond(A second) {
        MyBean myBean = new MyBean();
        myBean.setA(first);
        return myBean;
    }
}

MyBean 클래스를 수정하는 것은 항상 옵션이되는 것은 아닙니다. 예를 들어, 외부 라이브러리에서 오는 것이기 때문입니다. XML 구성을 사용해야하는 경우입니까?

고마워, 안드레아 폴리시

최신 정보 두 가지 해결책에 대해 감사 드리며 (이름으로 주입하고 @Primary를 사용함) 사용 사례를 해결하지 못해서 더 구체적으로 생각해야합니다.

내 사용 사례에서 MyBean 클래스는 외부 라이브러리에서 가져온 것이므로 변경할 수 없습니다. 또한 MyBean 인스턴스가 두 개 이상 필요하며 각 인스턴스마다 A 인터페이스의 서로 다른 영역을 주입해야합니다. 나는 이것을 반영하기 위해 위의 코드를 업데이트했다 (xml과 java 모두).

자바 설정을 사용하는 솔루션이 있습니까? MyBean에 대한 종속성의 autowire를 피할 수 있습니까? (해당 클래스의 빈에서만, 컨텍스트에서 모든 빈에 대해 완전히 자동 연결되지 않음)

해결법

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

    1.자, 이제이 대답이 당신의 필요를 충족시킬 것입니다.

    자, 이제이 대답이 당신의 필요를 충족시킬 것입니다.

    우리가 필요로하는 것은 MyBean 클래스의 속성 a에 대한 올바른 값을 설정할 MergedBeanDefinitionPostProcessor의 구현입니다. 이것은 다음 클래스로 수행 할 수 있습니다.

    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
    import org.springframework.beans.factory.support.RootBeanDefinition;
    import org.springframework.stereotype.Component;
    
    
    @Component
    public class MyBeanPostProcessor implements MergedBeanDefinitionPostProcessor {
    
    
        @Override
        public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
            if(beanName.equals("myBeanFirst")) {
                beanDefinition.getPropertyValues().add("a", getMyBeanFirstAImpl());
            }
            else if(beanName.equals("myBeanSecond")) {
                beanDefinition.getPropertyValues().add("a", getMyBeanSecondAImpl());
            }
        }
    
        private Object getMyBeanFirstAImpl() {
            return new AImpl();
        }
    
        private Object getMyBeanSecondAImpl() {
            return new AImpl();
        }
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    }
    

    당신이 볼 수 있듯이 여기에있는 빈의 이름은 하드 코드되어 있지만 다음 코드의 @Bean 주석에 의해 사용되는 static final String으로 설정할 수 있습니다

    @Configuration
    public class Configuration {
    
    
    
        @Bean
        public MyBean myBeanFirst() {
            return new MyBean();
        }
    
        @Bean
        public MyBean myBeanSecond() {
            return new MyBean();
        }
    
    }
    

    Spring이 bean post processor를 실행할 때 우리가 설정 한 (또는이 경우 설정하지 않은) 값이 무시 되더라도 MyBean 생성 메소드에서는 setA가 호출되지 않는다는 것을 다음 코드에서 알 수 있습니다.

    A에 대한 기본값이 필요한 경우 (예를 들어 다른 빈에 주입하는 경우) 이전 구성에서 @Bean 정의로 진행합니다

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

    2.여러 가지 후보자가있는 경우 기본 AImpl이 될 빈에 @Primary를 사용하여 기본 후보를 지정할 수 있습니다. 그렇게하면 MyBean에 변경이 필요하지 않습니다.

    여러 가지 후보자가있는 경우 기본 AImpl이 될 빈에 @Primary를 사용하여 기본 후보를 지정할 수 있습니다. 그렇게하면 MyBean에 변경이 필요하지 않습니다.

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

    3.myBeanFirst를 먼저 사용하려면 first ()를 호출하십시오. myBeanSecond와 같고 초를 사용하려면 A를 설정할 때 second ()를 호출하십시오.

    myBeanFirst를 먼저 사용하려면 first ()를 호출하십시오. myBeanSecond와 같고 초를 사용하려면 A를 설정할 때 second ()를 호출하십시오.

    @Configuration
    public class MyConfig {
        @Bean
        public A first() {
            return new AImpl();
        }
    
        @Bean
        public A second() {
            return new AImpl();
        }
    
        @Bean
        public MyBean myBeanFirst() {
            MyBean myBean = new MyBean();
            myBean.setA(first());
            return myBean;
        }
    
        @Bean
        public MyBean myBeanSecond() {
            MyBean myBean = new MyBean();
            myBean.setA(second());
            return myBean;
        }
    }
    
  4. from https://stackoverflow.com/questions/22416140/autowire-setter-override-with-java-config by cc-by-sa and MIT license