代码之家  ›  专栏  ›  技术社区  ›  Vinz243

spring如何在不传递参数的情况下实例化@Autowired构造函数

  •  0
  • Vinz243  · 技术社区  · 7 年前

    假设我有这门课

    class Foo implements IFoo { Foo() {} }
    class Fooz implements IFoo { Fooz() {}}
    
    class Foobar implement IFoobar {
      @Autowired
      Foobar (Foo foo) {}
    }
    
    class Foobarz implement IFoobar {
      @Autowired
      Foobarz (Bar bar) {}
    }
    

    class Bar {
      @Autowired 
      Bar (IFoo foo) {
        this.foo = foo;
      }
    }
    

    但是,如果我想根据配置文件选择IFoo和IFoobar实例,我需要执行以下操作:

    @Configuration
    class Configuration {
      @Bean
      foo () {
        return this.isZ() ? new Fooz() : new Foo ();
      }
      @Bean
      foobar () {
        return this.isZ() ? new Foobarz(/* ??????? */) : new Foobar (/* ??????? */);
      }
    }
    

    如您所见,我无法实例化Foobar,因为我需要另一个bean。我知道存在ApplicationContext.getBean,但我不能确定它是否会在我的应用程序中初始化 Configuration 什么时候上课 foobar()

    this.foo() 或者,因为这会创建另一个对象引用,而且我不确定执行和初始化的顺序

    1 回复  |  直到 7 年前
        1
  •  1
  •   Nikolai Shevchenko    7 年前

    在你的情况下,以下应该做的把戏

    @Configuration
    class Configuration {
      @Bean
      IFoo foo() {
        return this.isZ() ? new Fooz() : new Foo ();
      }
      @Bean
      IFoobar foobar(IFoo foo) { // IFoo bean declared above will be injected here by Spring
        return this.isZ() ? new Foobarz(foo) : new Foobar(foo);
      }
    }
    

    但更优雅的方法是 @Service @Component 你班上的注解( @Bean 声明应 但从配置来看。。。

    package com.foobarpkg.maybeanotherpkg;
    
    @Service 
    class Foobar implement IFoobar {
      @Autowired
      Foobar (IFoo foo) { // not that interface should be used here instead of concrete class (Foo/Fooz)
      } 
    }
    

    ... 让Spring知道它的包位于

    @Configuration
    @ComponentScan(basePackages = {"com.foobarpkg"})
    class Configuration { 
     @Bean
      IFoo foo() {
        return this.isZ() ? new Fooz() : new Foo ();
      }
      // foobar bean is no longer declared here
    }