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

Java依赖项注入-场景中是否可能进行基于注释的设置?,java,dependency-injection,cdi,Java,Dependency Injection,Cdi,我正在使用简单的JUnit测试和javax.inject-Annotations在Java中处理依赖项注入 我有以下场景:有一个“顶级”类(SomeObject),它有两个依赖项(SomeObjDepA和SomeObjDepB)。SomeObjDepB也依赖于SomeObjDepA。这应该与SomeObjectInstance中的SomeObjDepA实例相同。但是SomeObjDepA不能是单例,因为不同的SomeObj实例应该有不同的SomeObjDepA(和SomeObjDepB)实例。这

我正在使用简单的JUnit测试和javax.inject-Annotations在Java中处理依赖项注入

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

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

公共类SomeObject{
@注入
私人SomeObjDepA SomeObjDepA;
@注入
私有SomeObjDepB SomeObjDepB;
公共SomeObjDepA getSomeObjDepA(){
返回someObjDepA;
}
公共SomeObjDepB getSomeObjDepB(){
返回someObjDepB;
}
}
公共类SomeObjDepA{
}
公共类SomeObjDepB{
@注入
私人SomeObjDepA SomeObjDepA;
公共SomeObjDepA getSomeObjDepA(){
返回someObjDepA;
}
}
公共类依赖注入测试{
@注入
私人提供商someObjProvider;
@试验
public void instancetest(){
final SomeObject someObjInst1=this.someObjProvider.get();
final SomeObject someObjInst2=this.someObjProvider.get();
assertNotEquals(someObjInst1,someObjInst2);
assertNotEquals(someObjInst1.getSomeObjDepA(),someObjInst2.getSomeObjDepA());
assertNotEquals(someObjInst1.getSomeObjDepB(),someObjInst2.getSomeObjDepB());
Assertions.assertEquals(someObjInst1.getSomeObjDepA(),someObjInst1.getSomeObjDepB().getSomeObjDepA());
Assertions.assertEquals(someObjInst2.getSomeObjDepA(),someObjInst2.getSomeObjDepB().getSomeObjDepA());
}
}
问题:如何设置依赖项注入来构建这样的场景?我正在寻找注释或基于Java的配置(如果可能)

我目前正在使用CDI2.0(Weld 3.1.5)和JUnit5进行测试。我更喜欢使用CDI的解决方案,但任何其他使用Spring、Guice等的解决方案都可以


提前多谢

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

你可以把范围看作是一个生命周期。如果您没有指定范围(您在上面的任何地方都没有指定),那么默认范围是“每当调用一个范围时创建一个新的范围”,这就是所谓的依赖范围。(这是因为被注射的物体的寿命取决于容纳它的物体。)

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

接下来,您将讨论如何区分给定对象的两个不可区分的实例,这两个实例都可能是单例(
SomeObjDepA
)。限定符允许您这样做

让我们假设您有一个使SomeObjDepA变成“黄色”的,另一个使SomeObjDepA变成“红色”的。要在CDI中实现这一点,您需要表示“红色”和“黄色”位。然后在生产现场使用。例如:

@ApplicationScoped//producer方法需要“封装”在bean中
公共类主机{
@产生
@红色//您可以按照规范的限定符注释规则定义此注释
@应用程序范围//…或任何需要的范围
公共部分产品EPA(){
返回新的SomeDepA();
}
@产生
@黄色//您可以按照规范的限定符注释规则定义此注释
@应用程序范围//…或任何需要的范围
公共SomeDepA produceYellowDepA(){
返回新的SomeDepA();
}
}
这里我们有两个生产者方法,容器将适当地调用它们,并在其他地方“满足”相关的注入点。例如,在
SomeObject
中,您可能有:

@Inject
@红色的
二等兵萨默德帕红;
@注入
@黄色的
二等兵萨默德帕黄;

如果适用,您可以在
SomeObjDepA
上使用
@ApplicationScoped
为应用程序重用同一实例。谢谢Glains,但这不起作用,由于SomeObject实例应具有不同的SomeObjDepA实例作为其依赖项。SomeObject.class是否始终具有SomeObjDepA.class和SomeObjDepB.class的有效实例?如果是这样的话,您能否省略SomeObjDepA上SomeObject类的直接依赖项,并通过依赖项SomeObjDepB访问它。是的,如果我更改SomeObject上的公共SomeObjDepA getSomeObjDepA()以返回此值。SomeObjDepB.getSomeObjDepA()而不是其本地字段this.SomeObjDepA,则所有断言都是真的。这将是这种情况的解决方案。非常感谢。但在我看来,这不是“真正的”DI。如果我需要某个对象的实例作为依赖项,我希望通过将其注入而自动获得它,而不需要知道它被注入的位置。