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>
これを行うためのすぐに使える機能はありません。ただし、@ 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
がどこから来ているのかについての知識もありません。
古い質問であり、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";
}
}
コンテキストファイルを使用した@Autowiredの代替: http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-autowire
だからあなたは持っているでしょう:
<bean class="MenuManagementBean" autowire="byType" />
通常どおり、他のプロパティを指定できます。これにより、それらのプロパティに対してのみ自動配線が上書きされます。