[SPRING] Spring 어노테이션으로 같은 클래스의 여러 빈 인스턴스화하기
SPRINGSpring 어노테이션으로 같은 클래스의 여러 빈 인스턴스화하기
XML로 구성된 스프링 빈 팩토리를 사용하면 동일한 클래스의 여러 인스턴스를 다른 매개 변수로 쉽게 인스턴스화 할 수 있습니다. 특수 효과를 사용하여 동일한 작업을 수행하려면 어떻게해야합니까? 나는 이런 것을 원한다.
@Component(firstName="joe", lastName="smith")
@Component(firstName="mary", lastName="Williams")
public class Person { /* blah blah */ }
해결법
-
==============================
1.예, 사용자 정의 BeanFactoryPostProcessor 구현의 도움으로이 작업을 수행 할 수 있습니다.
예, 사용자 정의 BeanFactoryPostProcessor 구현의 도움으로이 작업을 수행 할 수 있습니다.
다음은 간단한 예입니다.
두 가지 구성 요소가 있다고 가정 해보십시오. 하나는 다른 것에 대한 의존성입니다.
첫 번째 구성 요소 :
import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; public class MyFirstComponent implements InitializingBean{ private MySecondComponent asd; private MySecondComponent qwe; public void afterPropertiesSet() throws Exception { Assert.notNull(asd); Assert.notNull(qwe); } public void setAsd(MySecondComponent asd) { this.asd = asd; } public void setQwe(MySecondComponent qwe) { this.qwe = qwe; } }
보시다시피이 구성 요소에는 특별한 것이 없습니다. MySecondComponent의 두 개의 다른 인스턴스에 종속됩니다.
두 번째 구성 요소 :
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.annotation.Qualifier; @Qualifier(value = "qwe, asd") public class MySecondComponent implements FactoryBean { public Object getObject() throws Exception { return new MySecondComponent(); } public Class getObjectType() { return MySecondComponent.class; } public boolean isSingleton() { return true; } }
좀 더 까다 롭습니다. 설명 할 두 가지 사항이 있습니다. 첫 번째 - @Qualifier - MySecondComponent Bean의 이름을 포함하는 주석. 그것은 표준적인 것이지만, 직접 구현할 수 있습니다. 나중에 조금 볼 수 있습니다.
두 번째 언급해야 할 것은 FactoryBean 구현입니다. Bean이이 인터페이스를 구현하면 다른 인스턴스를 생성하기위한 것입니다. 여기서는 MySecondComponent 유형으로 인스턴스를 작성합니다.
가장 까다로운 부분은 BeanFactoryPostProcessor 구현입니다.
import java.util.Map; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { Map<String, Object> map = configurableListableBeanFactory.getBeansWithAnnotation(Qualifier.class); for(Map.Entry<String,Object> entry : map.entrySet()){ createInstances(configurableListableBeanFactory, entry.getKey(), entry.getValue()); } } private void createInstances( ConfigurableListableBeanFactory configurableListableBeanFactory, String beanName, Object bean){ Qualifier qualifier = bean.getClass().getAnnotation(Qualifier.class); for(String name : extractNames(qualifier)){ Object newBean = configurableListableBeanFactory.getBean(beanName); configurableListableBeanFactory.registerSingleton(name.trim(), newBean); } } private String[] extractNames(Qualifier qualifier){ return qualifier.value().split(","); } }
그것은 무엇을합니까? @Qualifier로 주석 된 모든 빈을 거치고 주석에서 이름을 추출한 다음 지정된 이름으로이 유형의 빈을 수동으로 작성합니다.
다음은 Spring 설정입니다.
<?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 class="MyBeanFactoryPostProcessor"/> <bean class="MySecondComponent"/> <bean name="test" class="MyFirstComponent"> <property name="asd" ref="asd"/> <property name="qwe" ref="qwe"/> </bean> </beans>
마지막으로주의해야 할 점은 필수적인 경우가 아니라면 그렇게 할 수는 있지만 그렇게 할 수는 없다는 것입니다. 이는 실제로 자연스러운 구성 방식이기 때문입니다. 클래스 인스턴스가 두 개 이상인 경우 XML 구성을 사용하는 것이 좋습니다.
-
==============================
2.그것은 불가능합니다. 중복 예외가 발생합니다.
그것은 불가능합니다. 중복 예외가 발생합니다.
또한 구현 클래스에서 이와 같은 구성 데이터를 사용하는 것이 최적이 아닙니다.
주석을 사용하려면 Java 구성을 사용하여 클래스를 구성 할 수 있습니다.
@Configuration public class PersonConfig { @Bean public Person personOne() { return new Person("Joe", "Smith"); } @Bean public Person personTwo() { return new Person("Mary", "Williams"); } }
-
==============================
3.나는 비슷한 사건을 해결해야만했다. 클래스를 재정의 할 수 있으면이 방법이 효과가있을 수 있습니다.
나는 비슷한 사건을 해결해야만했다. 클래스를 재정의 할 수 있으면이 방법이 효과가있을 수 있습니다.
// This is not a @Component public class Person { } @Component public PersonOne extends Person { public PersonOne() { super("Joe", "Smith"); } } @Component public PersonTwo extends Person { public PersonTwo() { super("Mary","Williams"); } }
그런 다음 PersonOne 또는 PersonTwo를 사용하면 특정 인스턴스를 autowire 할 필요가있을 때마다 Person을 사용할 수 있습니다.
-
==============================
4.왁스의 대답에 영감을 얻은 구현은보다 안전 할 수 있으며 정의가 추가 된 경우가 아닌 추가 된 후 처리를 건너 뛰지 않습니다.
왁스의 대답에 영감을 얻은 구현은보다 안전 할 수 있으며 정의가 추가 된 경우가 아닌 추가 된 후 처리를 건너 뛰지 않습니다.
public interface MultiBeanFactory<T> { // N.B. should not implement FactoryBean T getObject(String name) throws Exception; Class<?> getObjectType(); Collection<String> getNames(); } public class MultiBeanFactoryPostProcessor implements BeanFactoryPostProcessor { public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; Map<String, MultiBeanFactory> factories = beanFactory.getBeansOfType(MultiBeanFactory.class); for (Map.Entry<String, MultiBeanFactory> entry : factories.entrySet()) { MultiBeanFactory factoryBean = entry.getValue(); for (String name : factoryBean.getNames()) { BeanDefinition definition = BeanDefinitionBuilder .genericBeanDefinition(factoryBean.getObjectType()) .setScope(BeanDefinition.SCOPE_SINGLETON) .setFactoryMethod("getObject") .addConstructorArgValue(name) .getBeanDefinition(); definition.setFactoryBeanName(entry.getKey()); registry.registerBeanDefinition(entry.getKey() + "_" + name, definition); } } } } @Configuration public class Config { @Bean public static MultiBeanFactoryPostProcessor() { return new MultiBeanFactoryPostProcessor(); } @Bean public MultiBeanFactory<Person> personFactory() { return new MultiBeanFactory<Person>() { public Person getObject(String name) throws Exception { // ... } public Class<?> getObjectType() { return Person.class; } public Collection<String> getNames() { return Arrays.asList("Joe Smith", "Mary Williams"); } }; } }
Bean 이름은 여전히 wax의 @Qualifier 예제와 같이 어디서나 올 수 있습니다. Bean 정의에는 공장 자체에서 상속하는 기능을 포함하여 다양한 속성이 있습니다.
from https://stackoverflow.com/questions/2902335/instantiating-multiple-beans-of-the-same-class-with-spring-annotations by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 2-legged (클라이언트 자격 증명) OAuth2 서버에 대한 스프링 보안 컨텍스트 설정 (0) | 2019.01.09 |
---|---|
[SPRING] Spring의 WebApproot (0) | 2019.01.09 |
[SPRING] 어떻게하면 로깅을 얻을 수 있도록 Spring과 SLF4J를 구성 할 수 있습니까? (0) | 2019.01.09 |
[SPRING] 봄에 다른 xml 파일의 빈을 참조하는 법 (0) | 2019.01.09 |
[SPRING] 봄 시작 성능 문제 (0) | 2019.01.09 |