1

この Q/A から: Spring で List Bean を定義する方法は? List<Foo> fooListBean インスタンスで満たされたものを定義できることはわかっていFooますが、XML 構成を使用しています。次に例を示します。

public interface Foo {
    //methods here...
    void fooMethod();
}

@Service("foo")
@Scope("prototype")
public class FooImpl implements Foo {
    //fields and methods...
    @Override
    public void fooMethod() {
        //...
    }
}

@Service("fooCache")
@Scope
public class FooCacheImpl implements Foo {
    //fields and methods...
    @Override
    public void fooMethod() {
        //retrieves data from some cache
        //...
    }
}

@Service("fooWS")
@Scope("prototype")
public class FooWSImpl implements Foo {
    //fields and methods...
    @Override
    public void fooMethod() {
        //retrieves data from web service
        //...
    }
}

XML を使用してクライアントを構成できます。

<bean id="fooClient" class="some.package.FooClient">
    <property name="fooList">
        <list>
            <bean ... /> <!-- This may be fooImpl -->
            <bean ... /> <!-- This may be fooCacheImpl -->
            <bean ... /> <!-- This may be fooWSImpl -->
            <!-- I can have more beans here -->
        </list>
    </property>
</bean>

これが注釈のみで実行できるかどうかを知りたいのですが、XML で Bean を定義する必要はありません。このようなもの:

@Component
@Scope("prototype")
public class FooClient {
    //which annotation(s) to use here to fill this list with FooImpl instances?
    //I understand that if I have two implementations of Foo I may use a @Qualifier
    //or use another list to note the different implementations.
    private List<Foo> fooList;

    public void bar() {
        for (Foo foo : fooList) {
            foo.fooMethod();
        }
    }
}

の注入を伴わないソリューションの方が良いと思いますApplicationContextのでBeanFactoryFooClientSpring クラスに密接に結合されていません。また、私の場合、javax.inject.Provider次のブログ投稿に示されているような Java EEクラスを使用することはできません。

4

4 に答える 4

1

Factory Bean の使用についてはどうでしょうか。

春にあまり結合したくないとおっしゃっていたことは知っています.factory Beanを使用すると、リストを含むBeanはあまり結合されません.factoryだけです.

何かのようなもの

@Component("fooList")
class ListFactory<List<Foo>> implements FactoryBean, ApplicationContextAware {

     ApplicationContext context;
     public List<Foo>> getObject() {
           List<Foo> list = new ArrayList();
           list.add(context.getBean("foo");
           list.add(context.getBean("foo");
           return list;
     }

     public void setApplicationContext(ApplicationContext context) {
             this.context = context;
     }

     public boolean isSingleton() {
           return false;
     }
}

@Component
@Scope("prototype")
class FooClient {

    @Inject
    @Named("footList")
    private List<Foo> fooList;

    public void bar() {
        for (Foo foo : fooList) {
            foo.fooMethod();
        }
    }
}

自分で試したことがないか、必要なシナリオがあったため、うまくいくかどうかわかりません。

于 2013-10-14T20:37:32.193 に答える
0

prototypeこれは、スコープの制限 (または機能) です。ドキュメントはこう言っています

他のスコープとは対照的に、Spring はプロトタイプ Bean の完全なライフサイクルを管理しません。コンテナーはプロトタイプ オブジェクトをインスタンス化し、構成し、その他の方法でアセンブルし、それをクライアントに渡します。そのプロトタイプ インスタンスのそれ以上の記録はありません。

したがって、Spring がそれをあなたに渡した後、それへの参照は保持されないため、それらのいずれもあなたの に自動配線できませんfooList。追加した場合@Autowired

@Autowired 
private List<Foo> fooList;

新しいFooImplオブジェクトを作成し、それを の単一要素として自動配線するだけListです。

作成されたすべてのインスタンスの参照を保持しようとしているFoo場合は、ほとんどの場合、自分で行う必要があります。

于 2013-10-14T20:27:07.120 に答える
0

メソッドインジェクションを次のように使用できます。

public class PrototypeClient {

    protected abstract PrototypeBean createPrototype();

    private List<PrototypeBean> createPrototypeList() {
        int listSize = calculateListSize();

        List<Prototype> result = new ArrayList<Prototype(listSize);

        for (int i = 0; i < listSize; i++) {
            result.add(createPrototype());
        }
        return result;
    } 

    private int calculateListSize() {
       // do your stuff here
    }

    // ...
}

そしてSpring構成を次のように持っています:

<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 id="prototypeBean"
          class="fully.qualified.class.name.of.Prototype"
          scope="prototype" />

    <bean id="prototyeClient"
          class="fully.qualified.class.name.of.PrototypeClient">
         <lookup-method name="createPrototype" bean="prototypeBean"/>
    </bean>
</beans>                                 
于 2013-10-18T09:36:35.870 に答える
0

PostConstructコードで直接実行している場合は、注釈を使用するのが最善の方法だと思います。

@Component
@Scope("prototype")
public class FooClient {

....

    @PostConstruct
    public void init() throws Exception {
        fooList = new ArrayList<Foo>();
        fooList.add(new FooImpl());
    }

FooImplオブジェクト自体に追加の構成が必要な場合にのみ注釈に苦労すると思うので、このアプローチを使用するとより柔軟になると思います。

于 2013-10-14T20:20:03.147 に答える