2009-05-06 1 views
22

私は、別の(新しい)プロトタイプのBeanへの参照を返す関数の呼び出しのたびに必要なシングルトンBeanを持っています。私がこれを行うことを考える唯一の方法は、getBean()メソッドを呼び出すことによってBeanFactory/ApplicatioContextから新しいプロトタイプBeanインスタンスをプログラムで取得することです。コードサンプルが続きます...シングルトンBeanと依存性注入と組み合わせたSpringプロトタイプBean。構成のみのアプローチがありますか?

もっと良い方法がありますか?うまくいけば、設定を介してのみ?

<bean id="protoBean" scope="prototype" 
     class="com.blahblah.ProtoBean" /> 

<bean id="singletonBean" 
     class="com.blahblah.SingletonBean" /> 

public class ProtoBean { 

    .... 
} 

public class SingletonBean { 

    private BeanFactory factory; 

    public ProtoBean dispense() { 
     return (ProtoBean) factory.getBean("protoBean"); 
    } 

    .... 
} 

答えて

14

は、メソッドインジェクションを使用してMethod Injection

+1

この回答はChristopher氏によると、Spring 3.0では ' '要素が正しい方法であるため、古くなっています。また、shrini1000によって指摘されているように、メソッドインジェクションはクラスを不器用にしてテストします。 –

4

を見てみましょう(個人的に、私は...そこにある疑問)あなたが実装するサブクラスを作成する必要があります(ユニットテストに困難シングルトン-Beanクラスを作ります依存関係を出す方法)。さらに、インスタンスを直接インスタンス化できないため、再利用が容易ではないため、Springを使用していない場合にこのクラスを使用する場合は、Beanを返すメソッドをサブクラス化して提供する必要があります。

より良いアプローチIMHOは、次のように、プロキシ、プロトタイプターゲットソース、およびプロトタイプターゲットビーンを使用することです。このようなシングルトンBeanクラスは、単体テストが容易で、再利用が容易です。

<bean id="targetPooledObject" class="pool.PooledObject" scope="prototype"> 
    <constructor-arg value="42" /> 
</bean> 

<bean id="prototypeTargetSource" class="org.springframework.aop.target.PrototypeTargetSource"> 
    <property name="targetBeanName" value="targetPooledObject" /> 
</bean> 

<bean id="pooledObject" class="org.springframework.aop.framework.ProxyFactoryBean"> 
    <property name="targetSource" ref="prototypeTargetSource" />   
</bean> 

<bean id="poolConsumer" class="pool.PoolConsumer"> 
    <property name="pooledObject" ref="pooledObject" /> 
</bean> 
(上図のように poolConsumer)今

私たちはシングルトンBeanにpooledObjectを注入することができ、私たちはそのシングルトンBeanで作るすべてのメソッド呼び出し、(私たちは順番にpooledObject.foo()を呼び出しpoolConsumer.callPooledObjectMethod()呼び出すなど、すべての時間)のために、私たち新しいPooledObject beanを取得します。

public class PooledObject 
{ 
    private int x; 

    public PooledObject(int x) 
    { 
     this.x = x; 
    } 

    public void foo() 
    { 
     System.out.println("foo called"); 
    } 
} 

public class PoolConsumer 
{ 
    private PooledObject pooledObject; 

    public PooledObject getPooledObject() 
    { 
     return pooledObject; 
    } 

    public void setPooledObject(PooledObject pooledObject) 
    { 
     this.pooledObject = pooledObject; 
    } 

    public void callPooledObjectMethod() 
    { 
     pooledObject.foo(); 
    } 
} 
+1

興味深いですが、詳細を教えてください(つまり、Javaコードを追加してください) – Yaneeve

+1

@ Yaneeveはコードを追加し、設定を少し変更して反映しました。私のコードの不潔さを許してください。 – shrini1000

+0

@ Yaneeve SpringでBeanプールを作成することもできます。上記と同様の設定を使用しますが、 'PrototypeTargetSource'ではなく 'CommonsPoolTargetSource'を使用してください。これは有用であり得る。 Springを介してJMSメッセージをMDB形式で処理するときに使用します。以下はいくつかの詳細です:http://stackoverflow.com/a/12668538/266103 – shrini1000

10

春3.0から、我々は適切な範囲の依存性注入のための<aop:scoped-proxy>を使用することができます。

後には、対応するコードです。シーンの背後では、Springはプロキシされたオブジェクトを注入し、適切なスコープコンテキストを見つける責任があります。プロトタイプ、セッション、リクエストなどがあります。公式ドキュメントhereを参照してください。

また、Springでは@ScopeのproxyMode属性も導入されているため、XML宣言だけに限定されるものではありません。たとえば:

@Scope(value = "prototype", proxyMode = ScopedProxyMode.INTERFACES) 

が明確に注入された豆を文書化することを確認してくださいすることはgetClass()と鋳造が期待される結果が得られないかもしれない他の人に警告するプロキシです。また、プロキシされたクラスのequals()とhashCode()がクラス変数に直接アクセスするのではなくアクセスメソッドを使用するようにしてください。

関連する問題