복붙노트

[SPRING] Spring XML 설정에서 주어진 타입의 모든 빈을 수집하고 삽입하는 법

SPRING

Spring XML 설정에서 주어진 타입의 모든 빈을 수집하고 삽입하는 법

Spring 프레임 워크의 가장 강력한 액센트 중 하나는 Dependency Injection 개념입니다. 그 뒤에있는 조언 중 하나는 일반적인 상위 수준 메커니즘과 하위 수준 세부 정보를 분리하는 것입니다 (종속성 반전 원리에 의해 발표 됨).

기술적으로는 bean이 의존성으로 주입되는 것을 가능한 한 적게 알기 위해 bean 구현을하는 것으로 귀결됩니다.

public class PrintOutBean {
    private LogicBean logicBean;
    public void action() {
        System.out.println(logicBean.humanReadableDetails());
    }
    //...
}

<bean class="PrintOutBean">
    <property name="loginBean" ref="ShoppingCartBean"/>
</bean>

하지만 여러 종속 콩에서 작동하는 높은 수준의 메커니즘을 원한다면 어떻게해야할까요?

  public class MenuManagementBean {
       private Collection<Option> options;
       public void printOut() {
            for (Option option:options) {
              // do something for option
            }
            //...
       }
  }

싱글 톤 빈에서 @Autowired 어노테이션을 사용하는 것이 하나의 해결책이라는 것을 알고있다.

  @Autowired
  private Collection<Option> options;

그러나 분리 원칙을 위반하지 않는가? 내가 사용하는 곳 (예 : MenuManagementBean 클래스)에서 사용하는 부양 가족을 지정해야하는 이유는 무엇입니까? Mbean 클래스에 주석을 추가하지 않고 XML 구성에서 빈 컬렉션을 삽입하는 방법이 있습니까?

<bean class="MenuManagementBean">
    <property name="options">
       <xxx:autowire by-type="MyOptionImpl"/>
    </property>
 </bean>

해결법

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

    1.이 작업을 수행 할 수있는 즉시 사용 가능한 기능은 없습니다. 그러나 @Autowired리스트를 사용하지 않고 주어진 타입의 모든 bean을 콜렉션으로 모으고 싶다면 커스텀 FactoryBean을 작성하여 쉽게 할 수있다.

    이 작업을 수행 할 수있는 즉시 사용 가능한 기능은 없습니다. 그러나 @Autowired리스트를 사용하지 않고 주어진 타입의 모든 bean을 콜렉션으로 모으고 싶다면 커스텀 FactoryBean을 작성하여 쉽게 할 수있다.

    public class BeanListFactoryBean<T> extends AbstractFactoryBean<Collection<T>> {
    
        private Class<T> beanType;
        private @Autowired ListableBeanFactory beanFactory;
    
        @Required
        public void setBeanType(Class<T> beanType) {
            this.beanType = beanType;
        }
    
        @Override
        protected Collection<T> createInstance() throws Exception {
            return beanFactory.getBeansOfType(beanType).values();
        }
    
        @Override
        public Class<?> getObjectType() {
            return Collection.class;
        }    
    }
    

    그리고

     <bean class="MenuManagementBean">
        <property name="options">
           <bean class="BeanListFactoryBean">
              <property name="beanType" class="MyOptionImpl.class"/>
           </bean>
        </property>
     </bean>
    

    그러나이 모든 것은 @Autowired를 원래 클래스에 넣는 것을 피하기위한 많은 노력처럼 보입니다. SoC 위반이 아니라면 컴파일 시간 의존성이없고 옵션의 출처에 대한 지식도 없습니다.

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

    2.이전 질문과 Spring 3.1에서 가능하다 :

    이전 질문과 Spring 3.1에서 가능하다 :

    public class PluginPrototypeTest extends ASpringWebTest {
      @Autowired
      Collection<IDummyRepo> repos;
    
      @Test
      public void cacheTest() {
        assertNotNull(repos);
        assertEquals(2, repos.size());
        for(IDummyRepo r: repos){
          System.out.println(r.getName());
        }
      }
    }
    
    @Repository
    public class DummyRepo implements IDummyRepo {
      @Override
      public String getName(){
        return "DummyRepo";
      }
    }
    @Repository
    public class DummyRepo2 implements IDummyRepo {
      @Override
      public String getName(){
        return "DummyRepo2";
      }
    }
    
  3. ==============================

    3.@Autowired 대신 컨텍스트 파일을 사용합니다. http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-autowire

    @Autowired 대신 컨텍스트 파일을 사용합니다. http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-autowire

    그래서 당신은 :

    <bean class="MenuManagementBean" autowire="byType" />
    

    다른 속성은 정상적으로 지정 될 수 있으며 이는 해당 속성에 대해서만 autowiring을 재정의합니다.

  4. from https://stackoverflow.com/questions/2799316/how-to-collect-and-inject-all-beans-of-a-given-type-in-spring-xml-configuration by cc-by-sa and MIT license