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

时间:2016-01-25 12:10:11

标签: java spring dependency-injection configuration

我想创建一个基于“该字段属于哪个类的实例(或者甚至是该字段属于哪个类)的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();
   }
}

根据A实例的field

选择注入A的{​​{1}}的bean
id

一般的想法是决定将哪个实现注入到代码中定义哪个类的字段。

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

2 个答案:

答案 0 :(得分:1)

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

类不应该围绕调用者配置它们的行为,它会导致代码紧密耦合而不是非常便携。

相反,您应该找出是什么使这两个字段不同并重构它们以使用2个不同的接口(在共享功能的情况下甚至可能有一个共同的超级接口)。然后,您可以轻松地为这些接口提供2种不同的实现。在您的情况下,您还可以编写一个处理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 Beans中使用此工厂来制作As。

答案 1 :(得分:1)

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

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

  • 非常独特的Beanname
  • 的BeanFactory
  • 的ApplicationContext

但无论是自动线的target还是目标的class

请注意:如果autowire-field已标记为@Lazy而Bean的范围为Prototype,则可以详细说明bean使用bean自动连接的确切时间@PostConstruct