2016-08-26 69 views
1

我正在为由多个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依赖项(除了它扩展的模块的依赖关系外),那么可以激活该扩展。

但这听起来不像是最好的方法。有没有更好的解决方案来解决这个问题?

回答

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(); 
} 

一旦你的可选依赖在类路径中,服务加载器将会找到它。

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

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

0

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

1

可以明确你所依赖的是这样的:

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

结帐从这个link

细节
相关问题