【问题标题】:Is it possible to avoid compile-time dependency using spring Java @Configuration?是否可以使用spring Java @Configuration避免编译时依赖?
【发布时间】:2017-09-27 16:49:25
【问题描述】:

有没有办法在没有编译时检查的情况下使用基于 Spring Java 的配置来声明 bean,以便我可以在运行时提供接口实现?

例如,当我编写 JAX-RS 客户端时,我使用 JAX-RS API 而不参考特定的 API 实现。然后,在我的 spring XML 配置中,我声明了我想要使用的 JAX-RS API 的实际实现,例如Jersey,在设置客户端 bean 时。因为在运行时使用(和验证)基于 XML 的配置,所以我不需要对 Jersey 的编译时依赖。这允许我对 Jersey 有一个 <scope>runtime</scope> Maven 依赖项,而我必须对 JAX-RS API 有一个 <scope>compile</scope> 依赖项。这种方法的好处是,如果我不小心使用了该实现,我的应用程序将无法使用 Maven 进行编译。

另一方面,如果我使用基于 Java 的 spring 配置(使用@Configuration)来声明我的 bean,我必须对 API 的实现有编译时依赖,因为配置本身是编译的。

如果这无法通过基于 Java 的配置来实现,是否有任何替代方案(除了使用我知道可能的 XML 和基于 Java 的配置的组合)?

【问题讨论】:

  • 你可以通过反射手动做同样的事情,我想,但强类型的优点之一是提前检查。实现 bean 的 Spring Boot 自动配置可能适合您想要的。
  • 只需将依赖项标记为<optional>true</optional>。对于使用您的库的任何内容,它仍然需要手动声明依赖项。这基本上是 Spring Boot 使用事物的方式(将很多事物标记为可选并使用条件规则来包含所需的基于 java 的配置)。

标签: java spring maven


【解决方案1】:

简答

是的,有可能:)

长答案

除了描述的方式之外,Spring Boot 开箱即用。

这是 Spring Boot 的自动配置魔法。许多选项仅在编译时才在核心 Spring Boot Starter 库中提供。但是当运行时类路径上有必要的库(或者准确地说是类)时,它会在实际实现中变得活跃。

Spring Boot 为此提供了专门的注解:@ConditionalOnClass。 我建议阅读 Spring Boots 文档的this section 以熟悉该主题。

【讨论】:

    【解决方案2】:

    要编译您的 java 配置,其中包含的所有类都必须在编译时可访问。

    您可以将该 @Configuration 根类移动到另一个 maven 模块,分别编译您的主模块和该特定模块,并且在您的主模块中没有您不想拥有的依赖项;然后引用加载 Spring 上下文的特定 @Configuration 根类(例如,通过 contextConfigLocation 上下文参数)。

    或者你可以在你的@Configuration 中使用肮脏的Class.forName()+newInstance() 技术。

    当然,您提到的选项(@Configuration + 基于 XML 的配置的混合)也是可能的。

    【讨论】:

      猜你喜欢
      • 2013-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多