我在服务中有以下依赖层次结构:
Service A
-> Lib A
-> Lib B
-> Lib A
-> Lib C
-> Lib A
-> Lib D
-> Lib A
"->"表示取决于.
由于上述结构,出现了许多问题。需要付出大部分努力的是在所有模块之间保持LibA同步,以避免类冲突和其他问题
我使用maven进行依赖项管理,但它并不能解决问题,因为我必须更新所有依赖项以避免冲突(语义和功能)
有没有更好的方法来管理这些依赖关系?
编辑1:
场景1:向Lib A添加新代码,该代码只供Lib B使用。
在这种情况下,仅仅更改Lib B是不够的。我必须在服务A中添加Lib A的最新版本,以便maven选择正确的版本。
场景2:A.中的非向后兼容更改
如果我只是在服务A中更新库A,这将导致问题,因为其他库(B、C和D)不知道这个新更改,它可能会中断(例如,在现有方法方法中添加新参数)。我将不得不更新所有的。
场景3:更改Lib A.中的现有方法
这会很好用的。如果我在服务A中更新此Lib A,maven将获取最新的Lib A并且所有的Lib(B、C和D)都将使用最新版本的Lib A.
不确定我是否正确理解这个问题,您是否提到了库之间的依赖冲突。
如果您在库之间有相同的依赖项,则排序的一种方法可能是使用排除,即添加一个依赖项并排除其他依赖项(https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html)
您可能会研究OSGi或Java 9模块(当然还没有完成)。我不是专家,但我相信这些框架允许模块/捆绑包的概念,其中每个模块都有自己的类加载器。这意味着,如果lib B和lib C是模块,它们可以有不同版本的lib A,一切都会顺利进行。它确实阻止了lib B和lib C直接通信,但给定了所需的依赖树。
--更新以匹配您的更新--
场景1:
仅在模块B中更新库A版本。模块C/D可以保持不变。
场景2:
当模块B/C/D中的每个模块都准备好使用新版本的库A时,您可以独立地更新库A。
场景3:
没有问题。
思考域驱动设计,更具体地说,有界上下文模式。它允许在一定程度上进行代码复制。灵活性将允许您非常容易地将"jar A"与其他部分解耦。
什么是有界上下文
让我们假设我们有User。该用户在一个上下文中可以是UserAdmin,在另一个上下文下可以是PowerUser或在另一上下文中可以只是User。
现在让我们想象一下,我们有3个服务,根据历史记录类型处理用户的三个不同功能。每个服务代表术语"用户"的不同上下文。现在的重点是,在你的情况下,它将进入全能的"libA",而不是创建一个全能的"用户",我们将根据上下文创建3个用户,并为这3个用户提供不同的功能。最终,我们将得到服务1的3个域对象AdminUser服务2的PowerUser和服务3的User。这三个服务将不会相互依赖,除非它适合我们,即使它们有,在任何时候将它们解耦都是小菜一碟。
如果我们开始把服务看作洋葱在第一层我们会有持久性。在第二层,我们将开始展开我们的领域模型。在下一层,我们将开始构建我们的服务。然后我们的网络表示等等。
根据有界上下文进行思考将允许您在每个服务的基础上创建一个唯一的有界上下文,这将使您在不同的Jar之间不存在这种相互依赖性。这是因为您的服务不一定会与其他服务共享代码。
Service A
-> Project Commons
-> Lib B_A (functional dependency, commons B no functional dependency with C and D)
-> Lib C_A (functional dependency, commons C no functional dependency with B and D)
-> Lib D_A (functional dependency, commons C no functional dependency with B and C)
-> Lib A (technical dependencies , commons in B C D)
-> pom_parent
-> Lib B
-> Lib A and Lib B_A
-> Lib C
-> Lib A and Lib C_A
-> Lib D
-> Lib A and Lib D_A
pom_parent (SNAPSHOT)