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

时间:2018-10-23 13:55:08

标签: java spring

假设我有这堂课

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 个答案:

答案 0 :(得分:1)

在您的情况下,以下方法可以解决问题

@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
}