2012-02-24 13 views
7

Paralel çalışma yapmak için çalışma zamanında bir çift görev (java.util.concurrent.Callable 's) oluşturan tek bir Spring Bean var. Şu anda, Callable 'lar, tek tabakalı fasülyede iç sınıflar olarak tanımlanmıştır ve tekli fasülye, new Task(in) ile eşzamanlı olarak yaratır, burada in sadece çalışma zamanında bilinen bir parametredir.Spring: Çalışma zamanı parametresini alan bir Spring bean'ı nasıl örneklendirirsiniz?

Şimdi Task'ın call() yöntemini işlemsel yapmak istediğim için iç Görev sınıfını düzenli bir üst düzey sınıfa çıkarmak istiyorum, bu yüzden bir Spring Bean olması gerekiyor.

Tek bir kerelik fabrikamıza Task s ürününü vermem gerekiyor, ancak görevlerin bir constructor parametresi olarak çalışma zamanı değerini alan prototip Spring çekirdekleri olması gerekiyor. Bunu nasıl başarabilirim?

+0

@BorisTreukhov: Bu, çok iş parçacıklı uygulamaların sınanmasıyla ilgili bir soru değil, bu Bahar hakkında bir sorudur. Aslında, sorudan # 2 nedenini kaldıracağım çünkü gerçek sorundan uzaklaşıyor. –

+0

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

+0

@Bossie benim yorumunu kaldırıldı tamam btw basit yolu ayrı hizmet oluşturmak için olduğunu düşünüyorum fasulyeleri, kendi yöntemlerini işlemsel olarak dekore eder, bunları tekilinize enjekte eder ve "in" parametresini servis yöntemlerine geçirir. KISS için –

cevap

2

Spring'in fasülye fabrikası ve yenisi birbirini dışlayanlardır. Yeni diyemezsiniz ve bu nesnenin Spring'in kontrolü altında olmasını bekleyemezsiniz.

Benim önerim, bu Görevleri Singleton'a enjekte etmektir. Onları da bahar fasulyesi yap.

Görevin kendisinin işlem olmayacağını kabul etmelisiniz, ancak bağımlılıkları olabilir. Bunları Görevlere enjekte edin ve Spring'in işlemleri yönetmesini sağlayın.

+0

+1. İşleri olması gerekenden daha zor hale getirmek için bir sebep yok, sadece işlem servisleri yaratın ve bunları görevlere enjekte edin. – pap

+0

"Spring'in fasülye fabrikası ve yenisi, birbirini dışlayanlardır." Çoğu için açık görünebilir, ama bir bahar acemi için bu benim duymak için çok önemliydi. İlkbaharın gerçekte ne yaptığını anlamama yardımcı oldu. –

+0

Ama ne görevlerin sayısını bilmiyorsam? Yani Biri bir sayı ile bir iş gönderir, 10 deyin ve ben 10 görevi başlatalım? Böyle bir durumda Görevlerin Singleton'a nasıl enjekte edileceğini söyleyebilir misiniz? –

3

Tek tabakalı fasülyeniz, BeanFactoryAware ürününü ve içerdiği bahar fabrikalarındaki bakla çekirdeklerini uygulayabilir.

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

diğer yaklaşım yükleme zamanı dokuma ile Spring'in @Configurable ek açıklama kullanmayı olabilir, çalışma zamanında kablolu Callable en oluşturmak için (yerine bir fasulye fabrikasının) new kullanabilirsiniz bu şekilde:

@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); 

bakın Daha fazla bilgi için this article. Not, @Configurable and @Transactional in the same bean'u kullanamazsınız, dolayısıyla iki sınıf için gereksinim duymazsınız. Bu nedenle, Callable'ın birçok farklı uygulamasında (her biri için 2 sınıfa ihtiyaç duyacağınız için) bu ideal çözüm olmayabilir.