Tergantung pada persyaratan khusus Anda, dalam beberapa kasus mekanisme loader layanan Java mungkin mencapai apa yang Anda cari.
Singkatnya, ini memungkinkan pengembang untuk secara eksplisit menyatakan bahwa suatu kelas mensubklasifikasikan beberapa kelas lain (atau mengimplementasikan beberapa antarmuka) dengan mendaftarkannya dalam file di direktori file JAR / WAR META-INF/services
. Kemudian dapat ditemukan menggunakan java.util.ServiceLoader
kelas yang, ketika diberi Class
objek, akan menghasilkan instance dari semua subclass yang dideklarasikan dari kelas itu (atau, jika Class
mewakili antarmuka, semua kelas yang mengimplementasikan antarmuka itu).
Keuntungan utama dari pendekatan ini adalah bahwa tidak perlu secara manual memindai seluruh classpath untuk subclass - semua logika penemuan terkandung dalam ServiceLoader
kelas, dan itu hanya memuat kelas yang secara eksplisit dinyatakan dalam META-INF/services
direktori (tidak setiap kelas di classpath) .
Namun, ada beberapa kelemahan:
- Itu tidak akan menemukan semua subclass, hanya yang subclass dinyatakan secara eksplisit. Dengan demikian, jika Anda harus benar-benar menemukan semua subclass, pendekatan ini mungkin tidak cukup.
- Ini mengharuskan pengembang untuk secara eksplisit mendeklarasikan kelas di bawah
META-INF/services
direktori. Ini merupakan beban tambahan bagi pengembang, dan bisa rawan kesalahan.
- The
ServiceLoader.iterator()
menghasilkan contoh subclass, bukan mereka Class
objek. Ini menyebabkan dua masalah:
- Anda tidak bisa mengatakan bagaimana subkelas dikonstruksi - konstruktor no-arg digunakan untuk membuat instance.
- Dengan demikian, subclass harus memiliki konstruktor default, atau harus eksplisit menyatakan konstruktor no-arg.
Rupanya Java 9 akan mengatasi beberapa kekurangan ini (khususnya, yang berkaitan dengan instantiasi subkelas).
Sebuah contoh
Misalkan Anda tertarik menemukan kelas yang mengimplementasikan antarmuka com.example.Example
:
package com.example;
public interface Example {
public String getStr();
}
Kelas com.example.ExampleImpl
mengimplementasikan antarmuka itu:
package com.example;
public class ExampleImpl implements Example {
public String getStr() {
return "ExampleImpl's string.";
}
}
Anda akan mendeklarasikan kelas ExampleImpl
adalah implementasi Example
dengan membuat file yang META-INF/services/com.example.Example
berisi teks com.example.ExampleImpl
.
Kemudian, Anda dapat memperoleh instance dari setiap implementasi Example
(termasuk instance dari ExampleImpl
) sebagai berikut:
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.