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

Java依赖项注入——场景中是否可能进行基于注释的设置?

柳刚豪
2023-03-14

我正在用简单的JUnit测试和javax在Java中摆弄依赖注入。注入注释。

我有以下场景:有一个“顶级”类(SomeObject),它有两个依赖项(SomeObjDepA和SomeObjDepB)。SomeObjDepB也依赖于SomeObjDepA。这应该是SomeObjDepA的实例,与SomeObject实例中的实例相同。但是SomeObjDepA不能是单例,因为不同的SomeObj实例应该有不同的SomeObjDepA(和SomeObjDepB)实例。这就是我被困的地方。

更清楚地说,以下是一些没有任何配置的基本代码:

public class SomeObject {

  @Inject
  private SomeObjDepA someObjDepA;

  @Inject
  private SomeObjDepB someObjDepB;

  public SomeObjDepA getSomeObjDepA() {
    return someObjDepA;
  }

  public SomeObjDepB getSomeObjDepB() {
    return someObjDepB;
  }
}
public class SomeObjDepA {

}
public class SomeObjDepB {

  @Inject
  private SomeObjDepA someObjDepA;

  public SomeObjDepA getSomeObjDepA() {
    return someObjDepA;
  }
}
public class DependencyInjectionTest {

  @Inject
  private Provider<SomeObject> someObjProvider;

  @Test
  public void instancesTest() {
    final SomeObject someObjInst1 = this.someObjProvider.get();
    final SomeObject someObjInst2 = this.someObjProvider.get();

    Assertions.assertNotEquals(someObjInst1, someObjInst2);
    Assertions.assertNotEquals(someObjInst1.getSomeObjDepA(), someObjInst2.getSomeObjDepA());
    Assertions.assertNotEquals(someObjInst1.getSomeObjDepB(), someObjInst2.getSomeObjDepB());
    Assertions.assertEquals(someObjInst1.getSomeObjDepA(), someObjInst1.getSomeObjDepB().getSomeObjDepA());
    Assertions.assertEquals(someObjInst2.getSomeObjDepA(), someObjInst2.getSomeObjDepB().getSomeObjDepA());
  }
}

问题:如何设置依赖注入来构建这样的场景?我正在寻找一个注释或基于Java的配置(如果可能的话)

我目前使用CDI 2.0(焊接3.1.5)和JUnit 5进行测试。我更喜欢使用CDI的解决方案,但是任何其他使用Spring、Guice等的解决方案都很好。

非常感谢

共有1个答案

司空通
2023-03-14

根据您要查找的内容,您需要使用范围和/或限定符。

您可以将作用域视为生命周期。如果您没有指定作用域(您在上面的任何地方都没有指定),那么默认作用域是“每当需要时创建一个新作用域”,这就是所谓的依赖作用域(这是因为被注入的对象的生命周期取决于容纳它的对象)。)

正如@Glains在上面指出的,@ApplicationScoped是指示bean应该在“应用范围”中的一种方式,这基本上是具有额外优点的单例范围。因此,您可以将其放在任何满足要求的类上,以指示其生命周期应该是整个应用程序的生命周期。

接下来,您将讨论如何区分给定对象的两个不可区分的实例,这两个实例都可能是单例(SomeObjDepA)。限定符可以让你做到这一点。

假设您有一个生产者方法,它产生了一个黄色某物ObjDepA,另一个方法产生了一个红色某物ObjDepA。要在CDI中做到这一点,您需要表示“红色”和“黄色”位的限定符注释。然后在生产站点应用它们。例如:

@ApplicationScoped // producer methods need to be "housed" in a bean
public class Host {

  @Produces
  @Red // you define this annotation following the spec's rules for qualifier annotations
  @ApplicationScoped // ...or whatever scope is called for
  public SomeDepA produceRedDepA() {
    return new SomeDepA();
  }

  @Produces
  @Yellow // you define this annotation following the spec's rules for qualifier annotations
  @ApplicationScoped // ...or whatever scope is called for
  public SomeDepA produceYellowDepA() {
    return new SomeDepA();
  }

}

这里我们有两个生产者方法,容器将适当地调用它们,并在其他地方“满足”相关的注入点。例如,在SomeObject中,您可能有:

@Inject
@Red
private SomeDepA red;

@Inject
@Yellow
private SomeDepA yellow;
 类似资料:
  • 问题内容: 我在Android应用程序中将Dagger2用于DI。我发现我必须为使用@Inject字段的每个类编写注入方法。有没有一种方法可以只注入父类,而不必在每个子类上调用inject?以活动为例。我有一个“ 每个活动都从中延伸”的内容。有没有一种方法,我可以在BaseActivity的组件中创建一个注入方法,然后在BaseActivity的onCreate中调用inject,子活动中的@in

  • 我有一个Spring启动应用程序,我最近从v1.3.3. RELEASE升级到v1.4.2. RELEASE。 用于我在v1中的集成测试。3.3,我有一个豆子,我能够成功地监视它。我在运行测试时,配置文件,下面的被激活,而不是应用程序的。 我正在升级到v1。4.2.发布并希望使用spyBean注释模拟单个方法,而不依赖于概要文件。 我对我的测试方法做了以下改变,以尝试它- 然而,当我尝试上述方法时

  • 问题内容: 我认为许多专业人员不切换到注释驱动的依赖注入的主要原因是,它不支持在开发/测试/生产环境之间进行切换。在许多情况下,出于开发目的,您不仅可以使用不同的服务(及其连接),而且有时还需要模拟它们或创建Dummy实例。 昨天我想出了一种使用Spring注释的解决方案: …应该可以,但是不好。 对于您的解决方案或论点,我将非常感兴趣:为什么这不是一个真正的问题;-)欢迎Guice,Spring

  • 我想,对于一个可以注入的类来说,任何类都必须被注释。但是我看到一个示例演示了一个简单的REST服务,其中注入了一个没有任何注释的类。HelloService没有注释。是豆子吗?它的生命周期范围如何? 本例中还有一个问题是,为什么在web.xml中使用“hello”?项目中没有定义名为“Hello”的any类,也没有名为“Hello”的any目录。

  • 我试图在注释中创建一些信息树结构。经过一些尝试和帮助(请参阅java注释中的类型层次结构),我转向了以下模型。 该节点应允许我定义一级条件树。LogicalPression中的值定义子节点(属性和其他节点)之间的关系。问题是注释不允许递归依赖: 即使我在Node和NodeList包含节点列表中添加了一些NodeList注释,循环依赖也会再次被识别。 循环注释定义有什么解决方案吗?

  • 例如,Foos的资源可能如下所示: 对于酒吧: