Eu gosto de serviços. Eu também gosto do sistema de módulos. Infelizmente para mim, antes que eu usei Java 9 Eu tenho o hábito de ficar prestadores de serviços de frascos carregados em tempo de execução via URLClassLoader
, algo como isto (vou usar Java 10 de var
para brevidade):
var url = new File("myjar.jar").toURI().toURL();
var cl = new URLClassLoader(new URL[] {url}, getClass().getClassLoader());
var services = ServiceLoader.load(MyService.class, cl);
for (var service : services) {
...
}
Esta multa funciona, mesmo em Java 9 e além, mas ele carrega o jar no classpath, o que significa que ele usa o velho META-INF\services
método para encontrar prestadores de serviços. Eu prefiro usar o module-info
método, mas que requer o frasco para ser carregado no caminho do módulo em vez disso, mas eu não poderia encontrar nenhuma maneira que eu poderia fazer sobre isso. Então aqui estou eu, esperando que alguém aqui que entende o sistema de módulos mais profundamente vai me dizer como isso pode ser feito (ou que não pode, se for o caso).
O exemplo de trabalho menor, eu poderia montar, é
var path = Path.of("myjar.jar");
var cl = new URLClassLoader(new URL[]{path.toUri().toURL()});
var mf = ModuleFinder.of(path);
var cfg = Configuration.resolve(mf, List.of(ModuleLayer.boot().configuration()), mf, Set.of());
var ml = ModuleLayer.defineModulesWithOneLoader(cfg, List.of(ModuleLayer.boot()), cl).layer();
var services = ServiceLoader.load(ml, MyService.class);
services.forEach(System.out::println);
Assumindo que myjar.jar
é um frasco modular declarar para fornecer MyService
implementações.