web-dev-qa-db-ja.com

SpringXML構成で特定のタイプのすべてのBeanを収集して注入する方法

Springフレームワークの最も強力なアクセントの1つは、 依存性注入 の概念です。その背後にあるアドバイスの1つは、一般的な高レベルのメカニズムを低レベルの詳細から分離することであると理解しています( 依存性逆転の原則 によって発表されたとおり)。

技術的には、これは、依存関係として注入されている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
            }
            //...
       }
  }

1つの解決策は、シングルトンBeanで@Autowiredアノテーションを使用することです。つまり...

  @Autowired
  private Collection<Option> options;

しかし、それは分離の原則に違反していませんか?使用するのとまったく同じ場所(つまり、私の例ではMenuManagementBeanクラス)でどの依存関係を取得するかを指定する必要があるのはなぜですか?このようなXML構成でBeanのコレクションを挿入する方法はありますか(MMBクラスにアノテーションなしで)?

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

これを行うためのすぐに使える機能はありません。ただし、@ 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に違反しているとしても、それほど多くはありません。コンパイル時の依存関係はなく、optionsがどこから来ているのかについての知識もありません。

27
skaffman

古い質問であり、Spring3.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";
  }
}
35
takacsot

コンテキストファイルを使用した@Autowiredの代替: http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-autowire

だからあなたは持っているでしょう:

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

通常どおり、他のプロパティを指定できます。これにより、それらのプロパティに対してのみ自動配線が上書きされます。

6
Johanna