我一直想用我们的应用程序 + 构建系统在更大范围内尝试这个,但更高的优先级一直把它推到次要位置。这似乎是加载 Guice 模块的好方法,并且避免了关于“硬编码配置”的常见抱怨。单个配置属性很少自行更改,但您几乎总是有一组配置文件,通常用于不同的环境(调试、生产等)。
ServiceLoader 允许您提取定义为给定类型的服务的所有实现的列表。把它和 Guice 放在一起,你最终得到:
import java.util.ServiceLoader;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
public class ModuleLoader<M extends Module> extends AbstractModule {
private final Class<M> type;
public ModuleLoader(Class<M> type) {
this.type = type;
}
public static <M extends Module> ModuleLoader<M> of(Class<M> type) {
return new ModuleLoader<M>(type);
}
@Override
protected void configure() {
ServiceLoader<M> modules = ServiceLoader.load(type);
for (Module module : modules) {
install(module);
}
}
}
使用示例(作为 guice-servlet 项目中的动态 servlet 加载器):
import com.google.inject.servlet.ServletModule;
public class ServletLoader extends GuiceServletContextListener {
@Override
protected final Injector getInjector() {
return Guice.createInjector(ModuleLoader.of(ServletModule.class);
}
}
服务(打包为模块)将打包在单独的 jar 文件中。在每一个中,您将在元数据中定义类:
Within servlets.jar: META-INF/services/com.google.inject.Module
com.example.webapps.MyServletModuleA
com.example.webapps.MyServletModuleB
由于我们使用 Maven,我们认为这将是理想的,因为我们可以在运行时通过配置文件依赖项引入不同的实现。有人像这样使用Guice吗?
如果没有,请随意使用这个例子,看看它是如何为你工作的。(ServiceLoader 仅在 JDK6+ 中支持)