【问题标题】:maven - separate modules for interfaces and implementation with Springmaven - 用于 Spring 接口和实现的独立模块
【发布时间】:2013-01-29 03:45:55
【问题描述】:

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

 +commons 
  +commons-api 
  +commons-impl 

模块的 POM 将被配置为没有模块依赖于 impl 子模块。这样,一个模块中的任何代码都无法“看到”另一个模块的实现细节。

我们遇到的问题是把 spring XMLs 放在哪里。 在我们的项目中,我们使用通配符导入自动导入 spring XML 文件,例如

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

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

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

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

我们考虑创建第三个子模块来保存 Spring XML(也许还有 hibernate xml)。例如:

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

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

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

【问题讨论】:

  • 问得好,但还没有答案?真可惜..
  • @cirit 同意 - 开始赏金

标签: java spring maven


【解决方案1】:

你需要的是一个运行时依赖范围:

runtime - 这个范围表示依赖项不是编译所必需的,而是执行所必需的。它在运行时和测试类路径中,但不在编译类路径中。

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

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

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

【讨论】:

    【解决方案2】:

    你可以像这样实现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>
    

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

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

    【讨论】:

    • external-project 应该直接依赖于 commons-api,你不能依赖于你明确调用的类的传递性。甚至 Maven 也会告诉你修复它。有些类加载器根本不允许这样做
    【解决方案3】:

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

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

    【讨论】:

    • 我不想完全覆盖图表,我只想让 Spring XML 文件在不存在依赖关系的 maven 项目中可见...
    【解决方案4】:

    想到两个想法:

    1. 您将拥有一个(或多个)模块,其中所有模块 (api+impl) 都是依赖项,您可以将 spring 配置文件放在那里。
    2. 将 spring 配置文件放在 api 模块中,并声明对 impl 模块的依赖,范围为 provided,这样就可以知道实现,而部署时不依赖 api。

    【讨论】:

      【解决方案5】:
      • commons-impl 在外部模块的运行时范围内

        1. commons (pom 依赖管理) =>

          +commons-api(编译)

          +commons-impl (编译)

          +commons-config(编译)

        2. commons-impl (pom 依赖) =>

          +commons-api(编译)

          +commons-config(编译)

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

          +commons-impl (运行时)

          +commons-api(编译)

          +commons-config(编译)

      【讨论】:

        【解决方案6】:
        1. 尽量减少模块数量;

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

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

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

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

        1. 仅在需要时向运行时模块提供运行时范围的依赖项;

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

        2. 将您的 api spring 上下文保留在 api 模块中,将您的公共 bean 定义为抽象 bean + 接口;

        3. 在运行时模块中保留你的实现上下文,通过 spring 配置文件用你的实现覆盖 api bean(使用

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-08-31
          • 1970-01-01
          • 2019-03-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-18
          • 1970-01-01
          相关资源
          最近更新 更多