2012-02-24 19 views
7

Tôi đã có một bean Spring đơn lẻ tạo ra một vài tác vụ (java.util.concurrent.Callable) khi chạy để thực hiện công việc song song. Ngay bây giờ, các Callable được định nghĩa là lớp bên trong trong hạt đơn, và đậu đơn tạo ra chúng đơn giản bằng cách khởi tạo chúng với new Task(in), trong đó in là một tham số chỉ được biết khi chạy.Mùa xuân: làm thế nào để khởi tạo một bean Spring có tham số thời gian chạy?

Bây giờ tôi muốn giải nén lớp Task bên trong thành một lớp cấp cao thông thường vì tôi muốn thực hiện giao dịch phương thức call() của Task, vì vậy tôi cần nó là bean Spring.

Tôi đoán tôi cần phải cung cấp cho nhà máy của tôi một số loại nhà máy Task s, nhưng nhiệm vụ phải là nguyên mẫu Hạt đậu mùa xuân có giá trị thời gian chạy làm tham số hàm tạo. Làm thế nào tôi có thể thực hiện điều này?

+0

@BorisTreukhov: đây không phải là câu hỏi về thử nghiệm các ứng dụng đa luồng, đây là câu hỏi về Spring. Trong thực tế, tôi sẽ loại bỏ lý do # 2 khỏi câu hỏi của tôi bởi vì nó phân tâm từ vấn đề thực sự. –

+0

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

+0

@Bossie ok Tôi đã gỡ bỏ nhận xét của tôi, btw Tôi nghĩ rằng cách đơn giản nhất là để tạo ra dịch vụ riêng biệt đậu, trang trí phương pháp của họ như là giao dịch, tiêm chúng vào singleton của bạn và vượt qua "trong" tham số để các phương pháp dịch vụ. –

Trả lời

2

Nhà máy đậu mùa xuân và mới là loại trừ lẫn nhau. Bạn không thể gọi mới và mong đợi đối tượng đó nằm dưới sự kiểm soát của Spring.

Đề xuất của tôi là đưa những Nhiệm vụ đó vào Singleton. Làm cho họ đậu mùa xuân, quá.

Bạn nên nhận ra rằng Nhiệm vụ chính nó sẽ không giao dịch, nhưng phụ thuộc của nó có thể là. Tiêm những người đó vào Nhiệm vụ và để Spring quản lý các giao dịch.

+0

+1 cho KISS. Không có lý do để làm cho mọi thứ khó khăn hơn họ phải, chỉ cần tạo ra các dịch vụ giao dịch và tiêm những người vào các nhiệm vụ. – pap

+0

"Nhà máy đậu mùa xuân và mới là loại trừ lẫn nhau". Nó có vẻ hiển nhiên đối với hầu hết, nhưng đối với một newbie mùa xuân, điều này rất quan trọng đối với tôi khi nghe. Nó giúp tôi hiểu mùa xuân thực sự là gì. –

+0

Nhưng nếu tôi không biết số nhiệm vụ thì sao? I E. ai đó gửi một công việc với một số, nói 10, và tôi nhanh chóng 10 nhiệm vụ? Bạn có thể vui lòng cho biết cách tiêm Nhiệm vụ vào Singleton trong trường hợp này không? –

3

Đậu đơn của bạn có thể triển khai BeanFactoryAware và các hạt tra cứu từ nhà máy có chứa lò xo.

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

cách tiếp cận khác có thể được sử dụng @Configurable chú thích mùa xuân với thời gian nạp dệt, bằng cách này bạn có thể sử dụng new (thay vì một bean factory) để tạo dây Callable tại runtime:

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

Xem this article để biết thêm thông tin. Lưu ý, bạn không thể sử dụng @Configurable and @Transactional in the same bean, do đó cần hai lớp. Vì lý do đó, điều này có thể không phải là giải pháp lý tưởng nếu bạn có nhiều triển khai khác nhau của Callable (vì bạn sẽ cần 2 lớp cho mỗi cái).

Các vấn đề liên quan