2013-08-29 61 views
9

Tôi có một ứng dụng dòng lệnh có sử dụng một Spring bean được quản lý bởi đó là bao gồm một java ExecutorService tạo ra với:Làm cách nào để tắt dịch vụ thực thi đúng cách với Spring?

ExecutorService service = Executors.newFixedThreadPool(4); 

Bây giờ, tôi muốn dịch vụ của tôi để tắt máy khi ứng dụng của tôi tắt, vì vậy tôi đã đậu của tôi thực hiện các giao diện DisposableBean và có một phương pháp phá hủy như:

public void destroy(){ 
    service.shutdown(); 
} 

Sau đó, tôi có thể bị cám dỗ để làm một cái gì đó giống như đăng ký một cái móc shutdown vào bối cảnh mùa xuân. Tuy nhiên tôi phát hiện ra (một cách khó khăn, tức là, trong bản phát hành trước khi sản xuất) rằng điều này không hoạt động: hook tắt máy không được gọi trước khi phương thức ExecutorService.shutdown() được gọi, gây ra vấn đề bắt cổ điển 22 (nó nhận được được gọi là gián đoạn, tức là, nếu tôi nhấn Ctrl-C trong khi ứng dụng đang chạy). Điều này thoát khỏi các bài kiểm tra đơn vị của tôi bởi vì vì lý do nào đó nó có vẻ hoạt động tốt từ bên trong JUnit, điều này vẫn khiến tôi khó hiểu: JUnit làm gì khác?

Giải pháp mà tôi đã tìm thấy cho đến nay là gọi rõ ràng ApplicationContext.close() ngay trước khi tôi thoát khỏi chức năng chính của mình. Tôi đã tự hỏi nếu có một giải pháp tốt hơn cho điều này và thực hành tốt nhất để có hồ bơi thread linh hoạt được quản lý bởi mùa xuân là gì. Ngoài ra, nếu đậu của tôi là không phải do Spring quản lý trực tiếp nhưng được tạo ra bởi một bean do Spring quản lý? Tôi có nên xếp các cuộc gọi đến destroy() không? Điều này có dễ bị lỗi không?

Tôi đánh giá cao mọi nhận xét, đề xuất, đọc thêm, RTFM, công thức nấu ăn kỳ diệu.

Cảm ơn!

+0

PS: điều gì sẽ xảy ra nếu tôi muốn chuyển ứng dụng dòng lệnh của mình sang máy chủ ứng dụng như Tomcat? Có gì thay đổi không? –

+0

Bao gồm tiêu đề và số PS của bạn, tôi * 7 * (7!) Dấu chấm hỏi. :-) Có thể nhận được phản hồi tốt hơn nếu bạn chỉ hỏi một câu hỏi cụ thể. – Keith

Trả lời

24

Bạn có biết rằng đây:

ExecutorService service = Executors.newFixedThreadPool(4); 

có thể được thay thế bằng này:

<bean id="service" class="java.util.concurrent.Executors" 
     factory-method="newFixedThreadPool" destroy-method="shutdown"> 
    <constructor-arg value="4"/> 
</bean> 

Bối cảnh mùa xuân sau đó quản lý, trực tiếp hơn, việc đóng cửa dịch vụ thi hành di chúc của bạn - và nó có thể dễ dàng sử dụng lại.

+0

Tôi biết điều đó. Tuy nhiên, trong một số trường hợp, tôi muốn tạo bean của mình theo cách lập trình hơn là thông qua cấu hình, ví dụ, nếu tôi không biết có bao nhiêu hạt cần thiết cho đến khi chạy hoặc định nghĩa của một bean cụ thể sẽ đến từ một nguồn bên ngoài. hoặc hàng đợi tin nhắn. –

+0

Đếm số tiền tối đa của tôi xuống, nó không hợp lệ. Điều này không làm việc nhưng kết quả trong 'InvalidArgumentException' trong khi khởi tạo bối cảnh mùa xuân. – Powerslave

1

Xem xét sử dụng TaskExecutor của Spring, có thể được định cấu hình với một nhóm luồng. http://static.springsource.org/spring/docs/3.0.x/reference/scheduling.html

+0

Tôi không nghĩ rằng nó sẽ phù hợp với trường hợp sử dụng của tôi. Tôi có rất nhiều đồng bộ hóa liên công việc cần được thực hiện (ví dụ: các rào cản) và tôi muốn có nhiều quyền kiểm soát hơn bằng cách sử dụng rõ ràng các trình thực thi và tác vụ tùy chỉnh. –

1

mỗi tài liệu Xuân chính thức, khi sử dụng cấu hình chú thích dựa trên, cho destroyMethod lĩnh vực @Bean, hành vi mặc định của Spring là để tự động gọi, phương pháp không-arg công tên close hoặc shutdown khi bối cảnh ứng dụng đã được đóng lại.

Để thuận tiện cho người dùng, vùng chứa sẽ cố gắng suy ra phương pháp tiêu hủy đối với đối tượng được trả về từ phương pháp @Bean. Đối với ví dụ , cho phương thức @Bean trả về Apache Commons DBCP BasicDataSource, vùng chứa sẽ nhận thấy phương thức close() có sẵn trên đối tượng đó và tự động đăng ký nó làm destroyMethod. 'Suy luận phương pháp phá hủy' này hiện bị giới hạn ở chỉ phát hiện các phương thức công cộng, không có arg có tên 'đóng' hoặc 'tắt máy'. Phương thức có thể được khai báo ở mọi cấp độ của hệ thống phân cấp thừa kế và sẽ được phát hiện bất kể loại trả về của phương thức @Bean (tức là, phát hiện xảy ra phản ánh đối với trường hợp bean chính nó tại thời điểm tạo).

Để lặp lại, đây là hành vi mặc định cho định cấu hình theo hướng chú thích khi phương thức hủy không được đặt rõ ràng. Nếu hành vi này là không mong muốn một cách rõ ràng thiết phá hủy phương pháp để một chuỗi rỗng sẽ vô hiệu hóa tính năng này "":

Để vô hiệu hóa phá hủy phương pháp suy luận cho một @Bean Đặc biệt, chỉ định một chuỗi rỗng như giá trị, ví dụ @Bean (destroyMethod = ""). Lưu ý rằng giao diện DisposableBean và giao diện Closeable/AutoCloseable sẽ vẫn được phát hiện và phương pháp hủy/đóng tương ứng được gọi.

Mặt khác, khi sử dụng cấu hình XML, đây là không hành vi mặc định ... Để đạt được tính chẵn lẻ, destroy-method thể được thiết lập một cách rõ ràng để (inferred). Tham khảo các phần Destruction callbacksDefault initialization and destroy methods trong tài liệu chính thức để biết chi tiết.