如何在另一个模块上添加运行时依赖?

时间:2016-08-26 18:02:35

标签: java maven dependencies

我正在编写一个包含多个Maven模块的库的扩展。我需要在一个模块的顶部添加一些功能,但不希望添加不必要的依赖项,以防有人想使用这个模块而没有我的扩展(典型用例)。

我能想到的一个解决方案是使用我的扩展创建另一个模块,并尝试使用反射从其类中调用方法。会有这样的检查:

try {
    Class.forName("my.package.Foo", false, getClass().getClassLoader());
    // extension will be enabled and some method will be called using reflection
} catch(ClassNotFoundException e) {
    // extension will be disabled
}

该类的方法只有在类路径上才会被调用。如果您在其模块上添加Maven依赖项(除了对其扩展的模块的依赖性),则可以激活扩展。

但这听起来不是最好的方法。这个问题还有更优雅的解决方案吗?

3 个答案:

答案 0 :(得分:1)

一种方法是使用内置Service provider interface (SPI)

基本思想是让你的可选库提供一些接口(一个"服务")的实现,这些接口可以很容易地被你的主应用程序找到。看一下这个例子

// scan classpath for all registered 
// implementations of Module interface
ServiceLoader<Module> loader = ServiceLoader.load(Module.class);
for (Module module : loader) {
    module.doSomething();
}

一旦你的可选依赖项在classpath中,服务加载器就会找到它。

您可以在Oracle的"Creating Extensible Applications"教程中找到很多关于如何制作它的例子。

另一种方法是使用依赖注入框架,例如springgoogle guice。这些框架还提供了用于自动组件发现的类路径扫描机制。此解决方案比SPI更灵活但更重。

答案 1 :(得分:1)

你可以这样确定你的依赖:

<dependency>
   <groupId>com.thoughtworks.paranamer</groupId>
   <artifactId>paranamer</artifactId>
   <version>2.6</version>
   <optional>true</optional>
</dependency>

结帐此link

的详细信息

答案 2 :(得分:0)

最简单的方法是按照您的提法创建一个新模块。在这个新的项目A中,您对这个现有模块的依赖关系,您正在谈论项目B. 因此,现在任何想要在没有扩展名的情况下使用的机构都会使用项目B.任何需要扩展的人都会使用项目A. 只需确保在构建路径中添加Maven依赖项以避免ClassNotFound冲突。