4.7 Using @EachBean to Drive Configuration

The @EachProperty is a great way to drive dynamic configuration, but typically you want to inject that configuration into another bean that depends on it. Injecting a single instance with a hard coded qualifier is not a great solution, hence @EachProperty is typically used in combination with @EachBean:

Using @EachBean

  1. @Factory (1)
  2. public class DataSourceFactory {
  3. @EachBean(DataSourceConfiguration.class) (2)
  4. DataSource dataSource(DataSourceConfiguration configuration) { (3)
  5. URI url = configuration.getUrl();
  6. return new DataSource(url);
  7. }

Using @EachBean

  1. @Factory (1)
  2. class DataSourceFactory {
  3. @EachBean(DataSourceConfiguration.class) (2)
  4. DataSource dataSource(DataSourceConfiguration configuration) { (3)
  5. URI url = configuration.getUrl()
  6. return new DataSource(url)
  7. }

Using @EachBean

  1. @Factory (1)
  2. class DataSourceFactory {
  3. @EachBean(DataSourceConfiguration::class) (2)
  4. internal fun dataSource(configuration: DataSourceConfiguration): DataSource { (3)
  5. val url = configuration.url
  6. return DataSource(url)
  7. }
1The above example defines a bean Factory that will create instances of javax.sql.DataSource.
2The @EachBean annotation is used to indicate that a new DataSource bean should be created for each DataSourceConfiguration defined in the previous section.
3The DataSourceConfiguration instance is injected as a method argument and used to drive the configuration of each javax.sql.DataSource

Note that @EachBean requires that the parent bean has a @Named qualifier, since the qualifier is inherited by each bean created by @EachBean.

In other words, to retrieve the DataSource created by test.datasource.one you can do:

Using a Qualifier

  1. Collection<DataSource> beansOfType = applicationContext.getBeansOfType(DataSource.class);
  2. assertEquals(2, beansOfType.size()); (1)
  3. DataSource firstConfig = applicationContext.getBean(
  4. DataSource.class,
  5. Qualifiers.byName("one") (2)
  6. );

Using a Qualifier

  1. when:
  2. Collection<DataSource> beansOfType = applicationContext.getBeansOfType(DataSource.class)
  3. assertEquals(2, beansOfType.size()) (1)
  4. DataSource firstConfig = applicationContext.getBean(
  5. DataSource.class,
  6. Qualifiers.byName("one") (2)
  7. )

Using a Qualifier

  1. val beansOfType = applicationContext.getBeansOfType(DataSource::class.java)
  2. assertEquals(2, beansOfType.size.toLong()) (1)
  3. val firstConfig = applicationContext.getBean(
  4. DataSource::class.java,
  5. Qualifiers.byName("one") (2)
  6. )
1We demonstrate here that there are indeed two data sources. How can we get one in particular?
2By using Qualifiers.byName(“one”), we can select which of the two beans we’d like to reference.