我正在编写一个包含多个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依赖项(除了对其扩展的模块的依赖性),则可以激活扩展。
但这听起来不是最好的方法。这个问题还有更优雅的解决方案吗?
答案 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"教程中找到很多关于如何制作它的例子。
另一种方法是使用依赖注入框架,例如spring或google 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冲突。