[SPRING] Java 구성으로 Autowire setter 재정의
SPRINGJava 구성으로 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.자, 이제이 대답이 당신의 필요를 충족시킬 것입니다.
자, 이제이 대답이 당신의 필요를 충족시킬 것입니다.
우리가 필요로하는 것은 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.여러 가지 후보자가있는 경우 기본 AImpl이 될 빈에 @Primary를 사용하여 기본 후보를 지정할 수 있습니다. 그렇게하면 MyBean에 변경이 필요하지 않습니다.
여러 가지 후보자가있는 경우 기본 AImpl이 될 빈에 @Primary를 사용하여 기본 후보를 지정할 수 있습니다. 그렇게하면 MyBean에 변경이 필요하지 않습니다.
-
==============================
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; } }
from https://stackoverflow.com/questions/22416140/autowire-setter-override-with-java-config by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring Boot에서 MySql Database 쿼리를 사용하는 방법? (0) | 2019.04.30 |
---|---|
[SPRING] 스프링 컬렉션 병합 (0) | 2019.04.30 |
[SPRING] Oauth2 클라이언트 로그 아웃이 작동하지 않습니다. (0) | 2019.04.30 |
[SPRING] Spring 트랜잭션 전파 필수, REQUIRES_NEW (0) | 2019.04.30 |
[SPRING] 스프링 부트 매핑 검증 코드와 MessageSource 메시지 비교 (0) | 2019.04.30 |