拥有这个maven项目结构
root pom
---> ModuleCore/pom.xml
---> ModuleA/pom.xml
---> ModuleB/pom.xml
---> ModuleC/pom.xml
---> ModuleD/pom.xml
模块A, B, C and D
与模块Core
有依赖关系,并且说ModuleA
与ModuleB
有依赖关系,ModuleB
有依赖关系与ModuleC
。
通过这种依赖性分配,我们同意:
如果我修改
ModuleCore
必须版本
ModuleA/pom.xml
ModuleB/pom.xml
ModuleC/pom.xml
ModuleD/pom.xml
如果我更新ModuleD
,则无需更新版本。
如果我更新ModuleC
必须版本
ModuleA/pom.xml
ModuleB/pom.xml
在整个解释之后,我想要实现的是,没有模块之间存在依赖关系,只有ModuleCore
我的第一个建议是创建接口作为模块间通信的契约,并将该契约放在moduleCore
中,然后通过reflection
调用classpath
实现的实现接口和调用。但是我对反思看起来很不舒服,
有人可以给我一些建议如何在不将所有代码移入ModuleCore的情况下应用通用闭包原理并制作一个整体?
使用Reflection的第一种方法的代码示例。
@Test
void dependencyWithModuleA() {
Reflections reflections = new Reflections("com.modularization.ccp");
Optional<Optional<?>> any = reflections.getSubTypesOf(MainA.class)
.stream()
.map(clazz -> {
try {
MainA mainA = clazz.newInstance();
return Optional.of(mainA.main());
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return Optional.empty();
}).findAny();
if (any.isPresent() && any.get().isPresent()) {
System.out.println(any.get().get());
}
}
重要的是要澄清它将在服务启动时完成的反射调用,以及实例引用它将使用Singleton模式进行保存,以避免性能问题。
请对所有关于这种方法的批评非常欢迎。
问候。
答案 0 :(得分:1)
从问题的标签看,这个问题似乎仅限于Java 8.使用这个假设...
查看JDK中内置的ServiceLoader类。您可以在每个MainA
个jar中声明META-INF/package.MainA
文件中ModuleA-D
的实现。然后找到这些实现:
ServiceLoader.load(MainA.class).iterator()
使用Java 9,事情会有所改变。现在JDK9模块可以直接声明它的服务,但它们仍然可以通过ServiceLoader
发现,所以这种方法也有一定程度的未来验证。
显然,JDK之外还有更多解决方案,例如Spring有自动装配,或者ApplicationContext.getBeansOfType(Class)
,Java EE有javax.enterprise.inject.Instance
,还有OSGi等......