Spring @Configuration @Bean - 如何获得更多关于创建 bean 的上下文信息?

Spring @Configuration @Bean - How can I get more context information for bean creation?

我想创建一个基于“字段属于哪个 class 的实例(或者甚至只是 class 该字段属于哪个实例)的 bean。类似于:

@Configuration
@ComponentScan
public class MyConfiguration {
    @Bean
    SomeClass getTheRightInstance(SomeContext someContext) {
        if(someContext.getinjectedFieldHostInstance.getId() == 7) {
            return new SpecificSomeClassImplForId7();
        } else {
            return new SomeClass();
        }
    }

Bean 将被注入以下 field:

public class A {
   private int final id;
   @Inject private SomeClass field;
   int getId();
   public A() {
     id = SerialIdGenerator.getNextID();
   }
}

Select bean 基于 A 实例的 id

注入 Afield
public staitc void main(String[] args) {
    A a1 = new A();  // has id '1', gets field injected with SimpleClass 
    A a2 = new A();  // has id '2', gets field injected with SimpleClass
    ...
    A a7 = new A();  // gets field injected with SpecificSomeClassImplForId7
    ...
    A last= new A();  // has id!=7, gets field injected with SimpleClass

}

总体思路是决定将哪个实现注入哪个字段,其中 class 在代码中定义。

我可以将不同的 bean 实例注入到相同 class 的不同实例的相同字段吗?如何通过代码配置它?

我不确定你为什么要这样做,但这似乎是个坏主意。

类 永远不应该围绕调用者配置它们的行为,这会导致代码紧密耦合且可移植性差。

相反,您应该找出是什么让这 2 个字段不同,并重构它们以使用 2 个不同的接口(在共享功能的情况下,它们甚至可能有一个通用的超级接口)。然后您可以轻松地为这些接口提供 2 种不同的实现。在您的情况下,您还可以编写一个 class 来处理 id == 7 的特定情况和其他情况(可能通过委托),并在将实例注入 A 之后或同时使用另一种方式配置实例。

我不知道有任何可能直接做你想做的事。

编辑:在评论中进一步讨论并进一步了解您想要完成的任务后,我认为最好有一个工厂来创建 A 实例:

@Service
class AFactory {

    @Autowired
    private SpecificSomeClassImplForId7 specificSomeClassImplForId7;

    @Autowired
    private SomeClass someClass;

    public A makeA() {
        if(isSpecialA()) {
            return new A(specificSomeClassImplForId7);
        } else {
            return new A(someClass);
    }
}

然后您可以在您的应用程序中的其他 Spring 个 Bean 中使用此工厂来制作 As。

您定义的 bean 是单例,因此它是在 Context-Initialization 创建的,然后应用程序知道任何人都可能自动装配该值。您必须将 Bean 创建为 Prototype 才能仅在自动装配上请求实例。

仍然无法获取有关 autowire-target 的信息。您可以使用 *Aware 接口来获取

  • 自己独特的Beanname
  • Beanfactory
  • 应用程序上下文

但是自动装配的 target 和目标的 class 都不是。

注意:如果 autowire-field 被标记为 @Lazy 并且 Bean 的范围是 Prototype 您可以详细说明 bean 使用 bean 的 [=16= 自动装配的确切时间].