Özel gereksinimlerinize bağlı olarak, bazı durumlarda Java'nın hizmet yükleyici mekanizması peşinde olduğunuz şeyi başarabilir.
Kısacası, geliştiricilerin bir sınıfın JAR / WAR dosyasının META-INF/services
dizinindeki bir dosyada listelenerek başka bir sınıfın alt sınıflarını (veya bazı arabirimleri uyguladığını) açıkça bildirmesine izin verir . Daha sonra java.util.ServiceLoader
, bir Class
nesne verildiğinde , o sınıfın bildirilen tüm alt sınıflarının (ya da Class
bir arabirimi temsil ediyorsa, o arabirimi uygulayan tüm sınıfların) örneklerini oluşturacak sınıf kullanılarak keşfedilebilir .
Bu yaklaşımın temel avantajı, tüm sınıfyolunu alt sınıflar için manuel olarak taramaya gerek olmamasıdır - tüm keşif mantığı ServiceLoader
sınıf içinde bulunur ve yalnızca META-INF/services
dizinde açıkça belirtilen sınıfları yükler (sınıf yolundaki her sınıf değil) .
Bununla birlikte, bazı dezavantajlar vardır:
- Tüm alt sınıfları bulamaz , yalnızca açıkça beyan edilenleri bulur . Bu nedenle, tüm alt sınıfları gerçekten bulmanız gerekiyorsa, bu yaklaşım yetersiz olabilir.
- Geliştiricinin sınıfı
META-INF/services
dizinin altında açıkça belirtmesini gerektirir . Bu geliştirici üzerinde ek bir yüktür ve hataya açık olabilir.
ServiceLoader.iterator()
Alt sınıf örneklerini değil onların oluşturduğu Class
nesneler. Bu iki soruna neden olur:
- Alt sınıfların nasıl oluşturulduğu hakkında herhangi bir söz almazsınız - argüman oluşturucu örnekleri oluşturmak için kullanılır.
- Bu nedenle, alt sınıfların varsayılan bir kurucuya sahip olması ya da açıklamanın arg olmayan bir kurucu bildirmesi gerekir.
Görünüşe göre Java 9 bu eksikliklerin bazılarını (özellikle alt sınıfların somutlaştırılmasıyla ilgili) ele alacaktır.
Bir örnek
Bir arayüz uygulayan sınıflar bulmakla ilgilendiğinizi varsayalım com.example.Example
:
package com.example;
public interface Example {
public String getStr();
}
Sınıf com.example.ExampleImpl
bu arayüzü uygular:
package com.example;
public class ExampleImpl implements Example {
public String getStr() {
return "ExampleImpl's string.";
}
}
Metni içeren bir dosya oluşturarak sınıfın ExampleImpl
bir uygulaması olduğunu beyan edersiniz .Example
META-INF/services/com.example.Example
com.example.ExampleImpl
Ardından, her uygulamasının Example
bir örneğini (bir örneği dahil ExampleImpl
) aşağıdaki gibi alabilirsiniz:
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.