java.util.serviceloader不能与模块一起工作-至少对我来说不是

aiazj4mn  于 2021-06-30  发布在  Java
关注(0)|答案(0)|浏览(224)

我正在使用Java15,我正在尝试将一些软件迁移到模块中。
我有一个模块 base 定义接口的 StringConverter 基本上是这样的(为了简洁起见,省略了注解和错误处理):

public interface StringProvider<T>
{
    public T fromString( final CharSequence source );
    public String toString( final T source );
    public Class<T> retrieveSubjectClass();

    public static final <S extends Object> Optional<StringConverter<S>> forClass( final Class<S> subjectClass )
    {
        StringConverter<?> result = null;
        if( nonNull( subjectClass ) )
        {
            final var serviceLoader = ServiceLoader.load( StringConverter.class );
            final Map<Class<?>,StringConverter<?>> registry = new HashMap<>();
            for( final var converter : serviceLoader )
            {
                registry.put( retrieveSubjectClass( converter ), converter );
            }

            result = registry.get( subjectClass );
        }

        final var retValue = Optional.ofNullable( (StringConverter<S>) result );

        //---* Done *----------------------------------------------------------
        return retValue;
    }  //  forClass()
}

这个 module-info.java 文件 base 模块如下所示:

module base
{
    requires java.base;

    exports services; // <-- The package containing the interface

    uses services.StringConverter;
}

接下来我有另外两个模块,请将它们命名为 mod1 以及 mod2 . 每个实现 services.StringConverter 接口并将这些实现作为服务提供。我不认为这些实现是相关的,因此在这里我将省略它们。我会给你看看 module-info.java 两个模块的文件。
模块 mod1 :

module mod1
{
    requires java.base;
    requires base;

    exports mod1; // <-- required as there are also other classes in there!

    provides services.StringConverter
        with mod1.BooleanStringConverter, mod1.BigIntegerStringConverter;
}

模块 mod2 :

module mod2
{
    requires java.base;
    requires base;

    exports mod2; // <-- required as there are also other classes in there!

    provides services.StringConverter
        with mod2.InstantStringConverter, mod1.URLStringConverter;
}

我的 main() ,放置在单独模块的类中 app ,如下所示:

public static final void main( final String... args )
{
    try
    {
        final var stringConverter = StringConverter.forClass( BigInteger.class );
        stringConverter.ifPresentOrElse( $ -> out.println( "Success!" ), () -> out.println( "Failure!" ) );
    }
    catch( final Throwable t )
    {
        //---* Handle previously unhandled exceptions *------------------------
        t.printStackTrace( err );
    }
}

对于那个模块 module-info.java 文件如下所示:

module app
{
    requires java.base;
    requires base;
    requires mod1;
    requires mod2;
}

这个 Optional 退回人 StringConverter.forClass() 总是空的。
对我来说,我的代码看起来非常类似于我能找到的关于这个主题的所有示例和教程代码,整个过程运行顺利,直到Java8(通过配置) META-INF/services/services.StringConverter ,当然!)。
任何想法都非常感谢!!
由于junit没有模块化运行,我提供了 META-INF/services/services.StringConverter 作为两个模块的测试资源, mod1 以及 mod2 . 然后测试将至少为一个模块运行,但不为另一个模块运行…

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题