java 运行 依赖_java – 运行时中的依赖项确定

我怀疑如何在存在多个相同接口的实现时使用guice实现依赖注入,并且这种依赖是在运行时根据参数定义的,所以我将举一个例子来轻松解释我的问题:

想象一下,您有一个模块可以加载多种格式的文件,基本上您有一个定义合同的接口,以及每种格式的多个实现:

public interface FileLoader {

void load(File file);

}

public class YMLFileLoader{

void load(File file){

System.out.println("Loading YML");

}

}

public class XMLFileLoader{

void load(File file){

System.out.println("Loading XML");

}

}

现在,在运行时,guice必须根据文件扩展名定义必须用于加载它的实现.

我保持代码清洁的想法是使用注释,因为每个实现都指定了她通过@FileLoaderType注释加载的内容.

@Singleton

@FileLoaderType("yml")

public class YMLFileLoader{

void load(File file)

{

System.out.println("Loading YML");

}

}

@Singleton

@FileLoaderType("xml")

public class XMLFileLoader{

void load(File file)

{

System.out.println("Loading XML");

}

}

我的第一个问题是如果可以实施?

作为第一个问题是积极的,有任何方法可以实现这个解决方案,其中FileLoader的每个新实现都不需要在支持解决方案的AbstractModule的实现中进行重构?

换句话说,基本上每个FileLoader的新实现都只需要注释@FileLoaderType的存在才能知道如果扩展与她匹配,它应该注入什么依赖.

解决方法:

Guice无法做的一件事是它无法扫描你的类路径并找到你所拥有的类,所以你需要一些方法来告诉你有哪些类可用.因此,让我们将您的问题分成两半:获取FileLoader实现类的列表,并将这些类绑定到Guice中.

让我先解决下半场问题.我假设你的AbstractModule子类中有一个带有签名的getFileLoaderClasses方法:

private List> getFileLoaderClasses() { ... }

在这种情况下,我建议绑定FileLoader实现的是这样的:

private void bindFileLoaders() {

MapBinder mapBinder

= MapBinder.newMapBinder(binder(), String.class, FileLoader.class);

for (Class extends FileLoader> implClass : getFileLoaderClasses()) {

FileLoaderType annotation = implClass.getAnnotation(FileLoaderType.class);

if (annotation == null) {

addError("Missing FileLoaderType annotation on " + implClass.getClass());

continue;

}

mapBinder.addBinding(annotation.getValue()).to(implClass);

}

}

这需要guice-multibindings扩展.绑定这样的实现后,您可以将其用作:

public class MyLoader {

@Inject Map fileLoaderMap;

public void load(File file, String type) {

FileLoader fileLoader = fileLoaderMap.get(type);

if (fileLoader == null) {

throw new IllegalArgumentException("No file loader for files of type " + type);

}

fileLoader.load(file);

}

}

那么现在,我们如何获得完整的实现类列表?有几种方法可以做到这一点:

>让一个类具有所有实现类的静态列表:

public class FileLoaderRegistry {

public static final List> impls =

ImmutableList.of(

YMLFileLoader.class,

XMLFileLoader.class,

JsonFileLoader.class

);

}

这样做的好处是它可能是最简单的解决方案.

它的缺点是您需要使用每个新实现更新这个文件,然后重新编译它.

>在其中包含所有类名的文本文件,并在读取文件的所有行后使用Class.forName()加载类.

>如果你在不同的jar文件中有FileLoader实现,你可以有一个文本文件列出公共位置中每个jar中的类的名称,然后使用System.getResources()来获取指向每个jar的URL的枚举文本文件.然后读取每个文件并使用Class.forName()加载类对象.

>最复杂的选项是使用annotation processing tool作为编译过程的一部分,并使用它来生成文本文件或注册表类.这是一个单独的问题.

标签:java,dependency-injection,guice

来源: https://codeday.me/bug/20190630/1334680.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值