Java Language
ServiceLoader
수색…
비고
ServiceLoader
는 .jar
파일로 압축 된 파일에 지정된 유형 (= 서비스)을 확장하는 클래스의 인스턴스를 가져 오는 데 사용할 수 있습니다. 확장 / 구현되는 서비스는 종종 인터페이스이지만 필수 사항은 아닙니다.
확장 / 구현 클래스는 ServiceLoader
가 인스턴스화하기 위해 0 인수 생성자를 제공해야합니다.
ServiceLoader
의해 발견 되려면 구현 된 서비스의 완전한 유형 이름의 이름을 가진 텍스트 파일을 jar 파일의 META-INF/services
디렉토리에 저장해야합니다. 이 파일에는 한 줄에 서비스를 구현하는 클래스의 정규화 된 이름 하나가 들어 있습니다.
로거 서비스
다음 예제는 ServiceLoader
를 통한 로깅을 위해 클래스를 인스턴스화하는 방법을 보여줍니다.
서비스
package servicetest;
import java.io.IOException;
public interface Logger extends AutoCloseable {
void log(String message) throws IOException;
}
서비스 구현
다음 구현은 단순히 System.err
메시지를 씁니다.
package servicetest.logger;
import servicetest.Logger;
public class ConsoleLogger implements Logger {
@Override
public void log(String message) {
System.err.println(message);
}
@Override
public void close() {
}
}
다음 구현은 메시지를 텍스트 파일에 씁니다.
package servicetest.logger;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import servicetest.Logger;
public class FileLogger implements Logger {
private final BufferedWriter writer;
public FileLogger() throws IOException {
writer = new BufferedWriter(new FileWriter("log.txt"));
}
@Override
public void log(String message) throws IOException {
writer.append(message);
writer.newLine();
}
@Override
public void close() throws IOException {
writer.close();
}
}
META-INF / services / servicetest.Logger
META-INF/services/servicetest.Logger
파일은 Logger
구현의 이름을 나열합니다.
servicetest.logger.ConsoleLogger
servicetest.logger.FileLogger
용법
다음 main
방법은 사용 가능한 모든 로거에 메시지를 씁니다. 로거는 ServiceLoader
사용하여 인스턴스화됩니다.
public static void main(String[] args) throws Exception {
final String message = "Hello World!";
// get ServiceLoader for Logger
ServiceLoader<Logger> loader = ServiceLoader.load(servicetest.Logger.class);
// iterate through instances of available loggers, writing the message to each one
Iterator<Logger> iterator = loader.iterator();
while (iterator.hasNext()) {
try (Logger logger = iterator.next()) {
logger.log(message);
}
}
}
간단한 ServiceLoader 예제
ServiceLoader는 인터페이스 구현의 동적로드를위한 간단하고 사용하기 쉬운 내장 메커니즘입니다. 서비스 로더 - 인스턴스화를위한 수단 제공 (배선은 아님) - Java SE에서 간단한 종속성 주입 메커니즘을 구축 할 수 있습니다. ServiceLoader 인터페이스와 구현 분리로 자연 스러우며 프로그램을 편리하게 확장 할 수 있습니다. 사실 많은 Java API는 ServiceLoader를 기반으로합니다.
기본 개념은 다음과 같습니다.
- 서비스 인터페이스 에서 작동
-
ServiceLoader
를 통해ServiceLoader
구현 구현하기 - 서비 스 구현 제공
인터페이스로 시작하여 예를 들어 accounting-api.jar
이라는 jar 파일에 넣을 수 있습니다.
package example;
public interface AccountingService {
long getBalance();
}
이제 서비스의 구현을 포함하는 accounting-impl.jar
이라는 항아리에 해당 서비스의 구현을 제공합니다.
package example.impl;
import example.AccountingService;
public interface DefaultAccountingService implements AccouningService {
public long getBalance() {
return balanceFromDB();
}
private long balanceFromDB(){
...
}
}
또한, accounting-impl.jar
에는이 jar가 AccountingService
구현을 제공한다는 것을 선언하는 파일이 들어 있습니다. 파일은 META-INF/services/
로 시작하는 경로가 있어야하며 인터페이스의 완전한 이름과 동일한 이름을 가져야합니다.
-
META-INF/services/example.AccountingService
파일의 내용은 구현의 완전한 자격을 갖춘 이름입니다.
example.impl.DefaultAccountingService
두 jar가 프로그램의 classpath에 있고 AccountingService
를 사용하면 서비스의 인스턴스는 ServiceLauncher를 사용하여 얻을 수 있습니다
ServiceLoader<AccountingService> loader = ServiceLoader.load(AccountingService.class)
AccountingService service = loader.next();
long balance = service.getBalance();
ServiceLoader
는 Iterable
이므로 여러 구현 공급자를 지원하며 프로그램에서 선택할 수 있습니다.
ServiceLoader<AccountingService> loader = ServiceLoader.load(AccountingService.class)
for(AccountingService service : loader) {
//...
}
next()
를 호출 할 때 새로운 인스턴스가 항상 생성된다는 점에 유의하십시오. 인스턴스를 다시 사용하려면 위에 표시된 것처럼 ServiceLoader 또는 for-each 루프의 iterator()
메서드를 사용해야합니다.