当前位置: 首页 > 知识库问答 >
问题:

在多模块环境中使用依赖注入(通过Guice)

姬承教
2023-03-14

我有一个小小的两难问题,涉及到Guice和避免非Guice单例。考虑一个多模块项目,其中有3个模块:共享前端后端前端后端都使用共享模块内的配置文件类的实例(该模块是times方法,并在整个项目中广泛使用)。

几乎每个类都需要使用这个profiling实例(包括在用户连接时动态创建的user对象)。

如果每个类都需要profiling类的一个实例,那么不同的方法都有缺点:

private final Profiling profiling;

@Inject
public User(Profiling profiling, String username)

解决方案2(仅作为实例字段):

@Inject
private Profiling profiling;

public User(String username)

缺点:与上面类似,您必须使用Guice的injector来实例化每个对象。这意味着要动态创建user对象,您需要在创建user对象的类中有一个注入器的实例。

解决方案3(作为一个(主)类中的静态字段,由我们手动创建)

public static final Profiling PROFILING; // Can also use a get method

public Application() {
    Application.PROFILING = injector.getInstance(Profiling.class)
}
@Inject
private static Profiling profiling;

// You need to request every single class:
// requestStaticInjection(XXXX.class)

谢谢!

共有1个答案

祝英博
2023-03-14

从实际意义上讲,我会使用一个普通的单例,也许是通过一个单字段枚举或类似的模式。

要了解原因,您应该问一个问题:Guice和依赖注入的目的是什么?其目的是将应用程序的各个部分解耦,以便它们能够独立开发和测试,并集中配置和重新排列。考虑到这一点,您需要权衡耦合的成本和解耦的成本。这取决于您选择耦合或解耦的对象。

在这里,耦合的代价是,如果没有一个真实的分析实例,就无法操作应用程序的任何部分,包括在测试中,包括像User这样的模型对象。因此,如果分析对其环境做出任何假设(例如,高分辨率系统定时调用的可用性),那么如果不允许禁用分析,您将无法使用像User这样的类。此外,如果您希望您的测试通过一个新的(非单例)分析实例进行分析,以实现测试隔离,那么您将需要单独实现它。但是,如果您的分析类足够轻量级,不会造成巨大的负担,那么您可能仍然会选择这种方式。

// Nested interface for your Factory:
public interface Factory { User get(String username); }

// Mark fields that the user provides:
@Inject public User(Profiling profiling, @Assisted String username) { ... }

// Wire up your Factory in a Module's configure:
install(new FactoryModuleBuilder().implement(User.Factory.class));

// Now you can create new Users on the fly:
@Inject User.Factory userFactory;
User myNewUser = userFactory.get("timothy");

解决方案3,请求静态注入主持有者近似于我的想法:对于不是通过依赖注入创建的对象,请求静态注入单个类,如profilingholder或其他类。为了灵活起见,您甚至可以赋予它no-op行为:

public class ProfilingHolder {
  // Populate with requestStaticInjection(ProfilingHolder.class).
  @Inject static Profiling profilingInstance;
  private ProfilingHolder() { /* static access only */ }
  public static Profiling getInstance() {
    if (profilingInstance == null) {
      // Run without profiling in isolation and tests.
      return new NoOpProfilingInstance();
    }
    return profilingInstance;
  }
}

当然,如果您依赖于对VM单例的调用,那么您实际上是在接受一个普通的VM全局静态单例模式,只是在可能的情况下使用了Guice。您可以很容易地改变这种模式,使Guice模块bind(Profiling.class).toInstance(Profiling.instance);获得相同的效果(假设可以在没有Guice的情况下实例化分析)。

解决方案4,每个类的requestStaticInjection是唯一我不会考虑的。类的列表太长,而且它们改变profiling的可能性太小。您会将一个模块变成一个高维护成本的杂货店列表,而不是任何有价值的配置,您会强迫自己破坏封装或使用Guice进行测试。

 类似资料:
  • 问题内容: 首先一些背景: 我正在研究一些基于Apache Sling的 webapp原型代码,该代码基于OSGI并在Apache Felix上运行。尽管我认为到目前为止我已经掌握了大多数概念,但我对OSGI还是比较陌生。但是,令我感到困惑的是,我找不到一个“完整的”依赖项注入(DI)框架。我已经使用声明式服务(DS)成功地使用了基本的DI。但是我的理解是DS可以用作参考- 我该如何处理?-OSG

  • 问题内容: 当前在app.js中,我有以下路线: 如您所见,我正在尝试注入Path依赖项。尽管我收到一条错误消息,说找不到该提供程序。我认为这是因为配置模块提供程序首先执行。以下是“ services.js”中我的路径提供程序定义 我怎样才能将此提供程序注入配置模块? 问题答案: 在中,只能使用提供程序(例如)。在你只能使用服务(如实例)。您有一家工厂,而不是供应商。请参阅具有以下三种创建方式的代

  • 让我们创建一个名为的新模块,并在那里定义CounterService。 app/shared/shared.module.ts 现在我们将引入 SharedModule 到AppModule 和中。 app/lazy/lazy.module.ts 使用此配置,两个模块的组件都可以访问CounterService。 我们将以完全相同的方式在EagerComponent和LazyComponent中使

  • 我需要ASP。Net核心依赖注入,将一些参数传递给实现ICardPaymentRepository接口的GlobalRepositoryClass的构造函数。 参数是用于配置的,来自配置文件和数据库,我不希望我的类去引用数据库和配置本身。 我认为工厂模式是实现这一点的最佳方式,但我想不出使用工厂类的最佳方式。工厂类本身依赖于配置和数据库。 我的创业公司目前看起来像这样: GlobalReposit

  • 问题内容: 在我的NestJS应用程序中- 我有TypeScript类,这些类中已经注入了其他类和值。唯一的是,我要导入带有语句的TypeScript类,并使用DI系统注入它们。有什么方法可以删除导入语句并让DI系统处理它? 问题答案: TL; DR ->类参考 DI->类实例化 可以通过字符串标记进行匹配,但最好使用类引用。 封装形式 依赖项注入系统主要处理类的实例化。这很好,因为您不必关心要注

  • 我想在使用guice实例化子类时,将依赖项注入父类。在下面的示例中,我试图创建的一个实例,同时希望能够在运行时使用Guice注入。我该怎么做?