簡體   English   中英

如何在Spring XML配置中收集和注入給定類型的所有bean

[英]How to collect and inject all beans of a given type in Spring XML configuration

Spring框架最強大的一個重點是依賴注入概念。 我理解其中的一個建議是將一般的高級機制與低級細節分開(如依賴性倒置原則所宣布的那樣)。

從技術上講,這可以歸結為讓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>

但是,如果我想要一個在多個依賴bean上運行的高級機制呢?

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

我知道一個解決方案是在單例bean中使用@Autowired注釋,即......

  @Autowired
  private Collection<Option> options;

但它不違反分離原則嗎? 為什么我必須在我使用它們的同一個地方指定依賴項(即我的示例中的MenuManagementBean類)? 有沒有辦法像這樣在XML配置中注入bean集合(在MMB類中沒有任何注釋)?

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

舊問題,在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";
  }
}

沒有開箱即用的設施可以做到這一點,沒有。 但是,如果您想要一種將給定類型的所有bean收集到一個集合中而不使用@Autowired列表的方法,那么可以輕松編寫自定義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的話 - 沒有編譯時間依賴性,並且不知道options的來源。

@Autowired的替代方案,使用上下文文件: http//static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-autowire

所以你有:

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

其他屬性可以像往常一樣指定,並且只會覆蓋那些屬性的自動裝配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM