繁体   English   中英

maven - 用于接口和Spring实现的独立模块

[英]maven - separate modules for interfaces and implementation with Spring

我们正在研究Mavenizing我们的java项目,我们希望在每个模块的接口和实现之间建立一个清晰的分离。 为了做到这一点,我们希望将每个模块分成两个子模块,一个用于它们使用的接口和数据对象,另一个用于实现。 例如:

 +commons 
  +commons-api 
  +commons-impl 

将配置模块的POM,使得没有模块依赖于impl子模块。 这样,来自一个模块的代码就无法“看到”另一个模块的实现细节。

我们遇到麻烦的是,将Spring XML放在哪里。 在我们的项目中,我们使用通配符导入自动导入spring XML文件

<import resource="classpath*:**/*-beans.xml"/>

这样,Spring XML的位置在运行时并不重要,因为所有模块都被加载到同一个类加载器中,并且POM中严格的单向依赖规则不适用。

但是,在开发过程中,我们希望IDE(我们使用Intellij IDEA)识别从spring XML引用的实现类。 我们还希望IDEA识别其他模块中定义的bean。

如果我们将spring XML放在API子模块中 - 它们将不会“看到”impl子模块中的实现类。 如果我们将它们放在impl子模块中,它们的bean将不会从其他模块中“看到”。 可能可以将IDEA项目配置为从没有依赖项的模块中识别spring XML,但我们更喜欢POM保存所有项目结构信息而不依赖于IDEA项目文件。

我们考虑创建第三个子模块只是为了保存Spring XML(也许还有hibernate xmls)。 例如:

 +commons 
  +commons-api 
  +commons-impl 
  +commons-config

外部模块将依赖于commons-apicommons-configcommons-config将依赖于commons-apicommons-impl ,并且依赖于commons-impl标记为“提供”(以防止传递解析)。

然而,这似乎是一个复杂而笨拙的解决方案,我们认为必须有一个更好 - 更简单的方法来实现与Maven和Spring的接口/ impl分离。

您需要的是运行时依赖范围:

runtime - 此范围指示编译不需要依赖项,但是用于执行。 它位于运行时和测试类路径中,但不是编译类路径。

https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

定义从一个impl模块到另一个impl模块的运行时依赖关系,您可以在其中使用* -beans.xml配置中的impl类。 Intellij会在spring配置文件中正确识别它,但不会在代码中自动完成它们(但它会在测试代码中完成)。

此外,如果有人在代码中使用这些类,则通过maven进行编译会失败,因为运行时依赖性不在编译类路径上。

你可以像这样实现api和impl的解耦:

+ commons (pom)
  + pom.xml         <--- serves as a parent aggregator (see below)
  + commons-api (jar)  <--- contains models, interfaces and abstract classes only
  + commons-impl (jar)  <--- depends on commons-api
  + commons-config (jar) <--- depends on commons-impl only (no need to depend on commons-api as it is brought in transitively)

 + external-project (war or jar) <--- has commons-config as a dependency

父聚合器pom(指定构建顺序):

<modules>
  <module>commons-api</module>
  <module>commons-impl</module>
  <module>commons-config</module>
</modules>

如果配置模块仅包含spring应用程序上下文配置,则可以省略它。 应用程序配置xml应位于包含要部署的工件的模块的类路径和文件夹结构中。 因此,如果您正在构建战争工件,应用程序上下文应该在那里。

应该在commons模块中的唯一配置是在impl模块的测试包中。

简而言之,您希望Idea覆盖maven依赖关系图,但避免将此配置保留在想法项目文件中?

一种选择是在maven配置文件中对实现依赖性进行分组。 默认情况下不会启用此配置文件,但您应该能够在想法下将其标记为活动状态。

想到两个想法:

  1. 您将拥有一个(或多个)模块,其中所有模块(api + impl)都是依赖项,您可以将弹簧配置文件放在那里。
  2. 将弹簧配置文件在API模块和声明与范围IMPL模块的依赖关系provided这样的实施方式将是已知的,而没有该API为部署的依赖性。
  • commons-impl在外部模块的运行时范围内

    1. 公共(pom dependencyManagement)=>

      + commons-api(编译)

      + commons-impl(编译)

      + commons-config(编译)

    2. commons-impl(pom dependencies)=>

      + commons-api(编译)

      + commons-config(编译)

    3. 外部模块(pom依赖)=>

      + commons-impl( 运行时

      + commons-api(编译)

      + commons-config(编译)

  1. 保持模块数量尽可能少;

    这加快了项目构建时间并简化了布局。

  2. 保持模块结构尽可能简单:单根+同一文件夹中的所有子模块,例如:

     pom.xml commons-api/ commons-runtime/ module-a-api/ module-a-runtime/ ... 

当模块数量非常高(> 50)时,这简化了项目的导航

  1. 仅在需要时为运行时模块提供运行时范围的依赖关系;

    这可以保持您的架构清晰。 使用mocks而不是显式依赖于另一个运行时模块。

  2. 在api模块中保存api spring上下文,将公共bean定义为abstract bean + interface;

  3. 将您的实现上下文保留在运行时模块中,通过spring配置文件覆盖api bean(使用<beans profile =“default”)。

结果:简单,透明的布局和设计; 全力支持; 没有对运行时模块内部的显式依赖。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM