2012-02-24 9 views
7

私は、実行時に2つのタスク(java.util.concurrent.Callable 's)を作成して並列処理を行うシングルトンSpring Beanを持っています。現在、CallableはシングルトンBeanの内部クラスとして定義されており、シングルトンBeanはnew Task(in)でインスタンス化するだけでシンプトンを作成します。inは実行時にのみ既知のパラメータです。Spring:実行時パラメータをとるSpring Beanをインスタンス化する方法は?

私はタスクのcall()メソッドをトランザクションにしたいので、標準のトップレベルクラスに内部タスククラスを抽出したいので、私はそれをSpring Beanにする必要があります。

私は自分のシングルトンにTaskの工場を与える必要がありますが、タスクはコンストラクタパラメータとしてランタイム値をとるプロトタイプのSpring Beanでなければなりません。どうすればこれを達成できますか?

+0

@BorisTreukhov:これはマルチスレッドアプリケーションのテストに関する質問ではありませんが、これはSpringに関する質問です。実際の問題から気をそらすので、私は理由2を私の質問から取り除くつもりです。 –

+0

参照: http://stackoverflow.com/questions/8772585/spring-bean-with-dynamic-constructor-value – quaylar

+0

@Bossie私は私のコメントを削除し、[OK]、ところで私は、最も簡単な方法は、個別のサービスを作成することだと思いますそれらのメソッドをトランザクションとしてデコレートし、シングルトンに挿入し、サービスメソッドに "in"パラメータを渡します。キスの場合は –

答えて

2

春の豆工場と新は相互排他的です。あなたはnewを呼び出すことはできませんし、そのオブジェクトがSpringのコントロール下にあることを期待することはできません。

私の提案は、これらのタスクをシングルトンに注入することです。彼らにも豆を作る。

タスク自体はトランザクションにはなりませんが、その依存関係はトランザクションになります。それらをタスクに注入し、Springがトランザクションを管理できるようにします。

+0

+1。必要以上に難しくする理由はなく、トランザクションサービスを作成してタスクに注入するだけです。 – pap

+0

"Springのbean factoryとnewは互いに排他的です。"ほとんどの人にとっては明らかなように思えるかもしれませんが、春の初心者にとっては、これは私にとっては非常に重要でした。それは私が春が実際に何を理解するのを助けました。 –

+0

しかし、何が私は仕事の数を知らないのですか?私。誰かが10という数字のジョブを提出し、10のタスクをインスタンス化しますか?このような場合にTasksをSingletonに注入する方法を教えてください。 –

3

シングルトンBeanは、含まれるSpring FactoryからBeanFactoryAwareとLookup Beanを実装できます。

import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.BeanFactory; 
import org.springframework.beans.factory.BeanFactoryAware; 

public class MyBeanFactory implements BeanFactoryAware { 

    private BeanFactory beanFactory; 

    public void setBeanFactory(BeanFactory beanFactory) 
      throws BeansException { 
     this.beanFactory = beanFactory;  
    } 

    public Task createTask(Task in) { 
     return beanFactory.getBean("task",in); 
    } 

} 
/////////////// 

import java.util.concurrent.Callable; 
import org.springframework.beans.factory.annotation.Configurable; 
import org.springframework.context.annotation.Scope; 
import org.springframework.transaction.annotation.Transactional; 

@Configurable // unless using xml based config 
@Scope(value="prototype") // tell bean factory to create new instance each time 
public class Task implements Callable<Object> { 

    private Object in; 

    public Task(Object in) { 
     super(); 
     this.in = in; 
    } 

    @Transactional 
    public Object call() throws Exception { 
     //do real work 
     return in; 
    } 
} 
/// 
4

別のアプローチは、ロード時ウィービングとSpringの@Configurableアノテーションを使用するかもしれない、あなたは実行時に有線呼び出し可能なのを作成するために、(代わりに豆工場の)newを使用することができますこの方法:

@Configurable 
public class WiredTask implements Callable<Result> { 

    @Autowired 
    private TaskExecutor executor; 

    public WiredTask(String in) { 
     this.in = in; 
    } 

    public Result call() { 
     return executor.run(in); 
    } 
} 

@Bean @Scope("prototype") 
public class TaskExecutor() { 

    @Transactional 
    public Result run(String in) { 
     ... 
    } 
} 

// Example of how you might then use it in your singleton... 
ExecutorService pool = Executors.newFixedThreadPool(3); 
WiredTask task = new WiredTask("payload"); 
Future<Result> result = pool.submit(task); 

参照してください。詳細はthis articleをご覧ください。注:@Configurable and @Transactional in the same beanは使用できないため、2つのクラスが必要です。その理由から、Callableの実装がたくさんある場合は、理想的なソリューションではないかもしれません(それぞれに2つのクラスが必要です)。

関連する問題