Tùy thuộc vào các yêu cầu cụ thể của bạn, trong một số trường hợp, cơ chế trình tải dịch vụ của Java có thể đạt được những gì bạn đang theo đuổi.
Nói tóm lại, nó cho phép các nhà phát triển tuyên bố rõ ràng rằng một lớp con phân lớp một số lớp khác (hoặc thực hiện một số giao diện) bằng cách liệt kê nó trong một tệp trong thư mục của tệp JAR / WAR META-INF/services
. Sau đó, nó có thể được phát hiện bằng cách sử dụng java.util.ServiceLoader
lớp, khi được cung cấp một Class
đối tượng, sẽ tạo ra các thể hiện của tất cả các lớp con được khai báo của lớp đó (hoặc, nếu Class
đại diện cho một giao diện, tất cả các lớp thực hiện giao diện đó).
Ưu điểm chính của cách tiếp cận này là không cần quét thủ công toàn bộ đường dẫn cho các lớp con - tất cả logic khám phá được chứa trong ServiceLoader
lớp và nó chỉ tải các lớp được khai báo rõ ràng trong META-INF/services
thư mục (không phải mọi lớp trên đường dẫn lớp) .
Tuy nhiên, có một số nhược điểm:
- Nó sẽ không tìm thấy tất cả các lớp con, chỉ những lớp được khai báo rõ ràng. Như vậy, nếu bạn cần thực sự tìm thấy tất cả các lớp con, cách tiếp cận này có thể không đủ.
- Nó yêu cầu nhà phát triển khai báo rõ ràng lớp trong
META-INF/services
thư mục. Đây là một gánh nặng bổ sung cho nhà phát triển và có thể dễ bị lỗi.
- Các
ServiceLoader.iterator()
trường hợp tạo lớp con, không phải Class
đối tượng của họ . Điều này gây ra hai vấn đề:
- Bạn không có ý kiến gì về cách các lớp con được xây dựng - hàm tạo không có đối số được sử dụng để tạo các thể hiện.
- Như vậy, các lớp con phải có một hàm tạo mặc định hoặc phải khai báo một hàm tạo không có đối số.
Rõ ràng Java 9 sẽ giải quyết một số thiếu sót này (đặc biệt là những thiếu sót liên quan đến việc khởi tạo các lớp con).
Một ví dụ
Giả sử bạn quan tâm đến việc tìm các lớp thực hiện giao diện com.example.Example
:
package com.example;
public interface Example {
public String getStr();
}
Lớp com.example.ExampleImpl
thực hiện giao diện đó:
package com.example;
public class ExampleImpl implements Example {
public String getStr() {
return "ExampleImpl's string.";
}
}
Bạn sẽ khai báo lớp ExampleImpl
là một triển khai Example
bằng cách tạo một tệp META-INF/services/com.example.Example
có chứa văn bản com.example.ExampleImpl
.
Sau đó, bạn có thể có được một phiên bản của mỗi lần thực hiện Example
(bao gồm một thể hiện của ExampleImpl
) như sau:
ServiceLoader<Example> loader = ServiceLoader.load(Example.class)
for (Example example : loader) {
System.out.println(example.getStr());
}
// Prints "ExampleImpl's string.", plus whatever is returned
// by other declared implementations of com.example.Example.