如何提供库中的组件,供多个 DI 框架使用



我的团队拥有一个库,该库提供的组件必须由使用该库的代码引用。我们的一些消费者使用 Spring 来实例化他们的应用程序;其他人使用Guice。我们希望获得有关如何提供这些组件的最佳做法的一些反馈。出现的两个选项是:

  1. 让我们的图书馆提供消费者可以@Import的春季Configuration,以及他们可以install的GuiceModule
  2. 让我们的库提供一个ComponentProvider单例,它提供了获取库提供的相关组件的方法。

这些外观的快速草图:

两种方法中都存在

// In their code
@AllArgsConstructor(onConstructor = @__(@Inject))
public class ConsumingClass {
private final FooDependency foo;
...
}

第一种方法

// In our code
@Configuration
public class LibraryConfiguration {
@Bean public FooDependency foo() {...}
...
}
---
public class LibraryModule extends AbstractModule {
@Provides FooDependency foo() {...}
...
}
========================
========================
// In their code
@Configuration
@Import(LibraryConfiguration.java)
public class ConsumerConfiguration {
// Whatever initiation logic they want - but, crucially, does
// *not* need to define a FooDependency
...
}
---
// *OR*
public class ConsumerModule extends AbstractModule {
@Override
public void configure() {
// Or, simply specify LibraryModule when creating the injector
install(new LibraryModule());
...
// As above, no requirement to define a FooDependency
}
}

第二种方法

// In our code
public class LibraryProvider {
public static final INSTANCE = buildInstance();
private static LibraryProvider buildInstance() {...}
private static LibraryProvider getInstance() {return INSTANCE;}
}
========================
========================
// In their code
@Configuration
public class ConsumerConfiguration {
@Bean public FooDependency foo() {
return LibraryProvider.getInstance().getFoo();
}
...
}
// or equivalent for Guice

对于这种情况,是否有公认的最佳实践?如果没有,每种选择或我尚未想到的其他选项的优缺点是什么?第一种方法的优点是消费者不需要编写任何代码来初始化依赖项,并且 DI 框架可以覆盖依赖项(例如,使用模拟依赖项进行测试(;而第二种方法的优点是与DI框架无关(例如,如果新消费者想要使用Dagger来实例化他们的应用程序,我们根本不需要更改库(

我认为第一个选项更好。如果你的库在 bean 之间有相互依赖关系,那么@Configuration在第二种方法中 spring 的情况下(的代码将是:

  1. 脆弱(如果应用程序不知道应该创建某个 bean 怎么办(
  2. 重复 - 此代码将出现在每个消费者的模块中
  3. 当新版本的库发布并且消费者想要升级时 - 消费者的配置可能会发生变化(库可能会公开一个新的 bean,弃用甚至删除一些旧的东西,等等(

一个小建议:

您可以使用 Spring 工厂,然后您甚至不需要在 Spring 启动的情况下制作@Import。 只需添加一个 Maven 依赖项,它就会自动加载配置。

现在,请确保在采用该方法的情况下正确使用依赖项。 由于您的代码将同时包含 spring 和 Juice 依赖代码,因此您将为库的 maven/gradle 模块添加对两者的依赖。这意味着,使用guice的消费者将因为你的图书馆而获得所有春天的东西。有很多方法可以克服这个问题,具体取决于您选择的构建系统,只是想提出来

最新更新