수색…


비고

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();

ServiceLoaderIterable 이므로 여러 구현 공급자를 지원하며 프로그램에서 선택할 수 있습니다.

ServiceLoader<AccountingService> loader = ServiceLoader.load(AccountingService.class)
for(AccountingService service : loader) {
   //...
}

next() 를 호출 할 때 새로운 인스턴스가 항상 생성된다는 점에 유의하십시오. 인스턴스를 다시 사용하려면 위에 표시된 것처럼 ServiceLoader 또는 for-each 루프의 iterator() 메서드를 사용해야합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow