특정 요구 사항에 따라 경우에 따라 Java의 서비스 로더 메커니즘으로 원하는 결과를 얻을 수 있습니다.
즉, 개발자는 클래스가 JAR / WAR 파일의 META-INF/services
디렉토리 에있는 파일에 나열하여 클래스가 다른 클래스를 서브 클래 싱하거나 인터페이스를 구현 함을 명시 적으로 선언 할 수 있습니다 . 그런 다음 객체를 java.util.ServiceLoader
제공 할 때 해당 Class
클래스의 선언 된 모든 서브 클래스의 인스턴스를 생성 하는 클래스를 사용하여 발견 할 수 있습니다 .Class
인터페이스를 나타내는 해당 인터페이스를 구현하는 모든 .
이 접근법의 주요 장점은 서브 클래스에 대해 전체 클래스 경로를 수동으로 스캔 할 필요가 없다는 것입니다. 모든 발견 논리가 ServiceLoader
클래스 내에 포함되어 있으며 클래스에 명시 적으로 선언 된 클래스 만로드합니다.META-INF/services
디렉토리에 경로의 모든 클래스는 아님) .
그러나 몇 가지 단점이 있습니다.
- 모든 서브 클래스를 찾을 수 없으며 명시 적으로 선언 된 서브 클래스 만 찾을 수 있습니다. 따라서 모든 서브 클래스를 실제로 찾아야하는 경우이 방법으로는 충분하지 않을 수 있습니다.
- 개발자는
META-INF/services
디렉토리 아래에 클래스를 명시 적으로 선언해야합니다 . 이는 개발자에게 추가적인 부담이며 오류가 발생하기 쉽습니다.
- 는
ServiceLoader.iterator()
서브 클래스 인스턴스가 아니라 자신의 생성 Class
객체. 이로 인해 두 가지 문제가 발생합니다.
- 서브 클래스가 어떻게 구성되는지에 대해서는 아무 말도하지 않습니다. 인수를 생성하지 않는 생성자가 인스턴스를 만드는 데 사용됩니다.
- 따라서 서브 클래스에는 기본 생성자가 있거나 인수가없는 생성자를 명시 적으로 선언해야합니다.
분명히 Java 9는 이러한 단점 중 일부 (특히 서브 클래스 인스턴스화 관련 문제)를 해결합니다.
예
인터페이스를 구현하는 클래스를 찾는 데 관심이 있다고 가정하십시오 com.example.Example
.
package com.example;
public interface Example {
public String getStr();
}
클래스 com.example.ExampleImpl
는 해당 인터페이스를 구현합니다.
package com.example;
public class ExampleImpl implements Example {
public String getStr() {
return "ExampleImpl's string.";
}
}
텍스트가 포함 된 파일을 만들어 클래스 ExampleImpl
를 구현 한 Example
것으로 선언합니다 .META-INF/services/com.example.Example
com.example.ExampleImpl
그런 다음 다음과 같이 Example
(의 인스턴스를 포함하여) 각 구현의 인스턴스를 얻을 수 있습니다 ExampleImpl
.
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.