Я думаю, вы не понимаете, для чего нужен ServiceLoader.
Смысл serviceloader - предоставить ему интерфейс, а затем serviceloader возвращает экземпляр (созданный путем вызова publi c no- конструктор args) каждого типа, «зарегистрированного» как поставщик услуг для этого интерфейса.
Это выполняется путем сканирования всего пути к классам для файла META-INF / services / io.grp c .netty. NettyChannelProvider (и вы никогда не должны использовать Class.forName для этого; вы должны просто использовать: ServiceLoader.load(ThatInterface.class)
; если это ошибка времени компиляции, потому что интерфейс не находится в вашем пути к классам, то исправьте это; serviceloader не имеет ничего общего с волшебное исправление проблем с classpath).
Такие файлы (можно найти любое число) состоят из текста; одно полное имя класса в строке. Сервисный загрузчик загружает каждый указанный класс, вызывая его конструктор publi c (и если он не существует, это будет ошибкой; они должны быть там, чтобы использовать сервисный загрузчик).
NettyChannelProvider
не интерфейс, это реализация; у вас все получилось.
Если вы действительно пытаетесь трактовать NCP как базовый интерфейс и ищете его реализации, то эти реализации должны [A] находиться в пути к классам выполнения поскольку этот код выполняется или не будет найден, и [B] эти реализации должны быть в jar-файлах или других записях пути к классам, которые имеют этот файл META-INF / services / io.grp c .netty.NettyChannelProvider. Если этого нет, serviceloader ничего не делает.
Вот что такое serviceloader: удобный читатель для META-INF/services/fully.qualified.name.of.the.base.Interface
файлов.