Saturday, October 11, 2014

Spring @Configuration and injecting bean dependencies as method parameters

One of the ways Spring recommends injecting inter-dependencies between beans is shown in the following sample copied from the Spring's reference guide here:

@Configuration
public class AppConfig {

 @Bean
 public Foo foo() {
  return new Foo(bar());
 }

 @Bean
 public Bar bar() {
  return new Bar("bar1");
 }

}
So here, bean `foo` is being injected with a `bar` dependency.

However, there is one alternate way to inject dependency that is not documented well, it is to just take the dependency as a `@Bean` method parameter this way:

@Configuration
public class AppConfig {

 @Bean
 public Foo foo(Bar bar) {
  return new Foo(bar);
 }

 @Bean
 public Bar bar() {
  return new Bar("bar1");
 }

}

There is a catch here though, the injection is now by type, the `bar` dependency would be resolved by type first and if duplicates are found, then by name:

@Configuration
public static class AppConfig {

 @Bean
 public Foo foo(Bar bar1) {
  return new Foo(bar1);
 }

 @Bean
 public Bar bar1() {
  return new Bar("bar1");
 }

 @Bean
 public Bar bar2() {
  return new Bar("bar2");
 }
}

In the above sample dependency `bar1` will be correctly injected. If you want to be more explicit about it, an @Qualifer annotation can be added in:

@Configuration
public class AppConfig {

 @Bean
 public Foo foo(@Qualifier("bar1") Bar bar1) {
  return new Foo(bar1);
 }

 @Bean
 public Bar bar1() {
  return new Bar("bar1");
 }

 @Bean
 public Bar bar2() {
  return new Bar("bar2");
 }
}


So now the question of whether this is recommended at all, I would say yes for certain cases. For eg, had the bar bean been defined in a different @Configuration class , the way to inject the dependency then is along these lines:

@Configuration
public class AppConfig {

 @Autowired
 @Qualifier("bar1")
 private Bar bar1;

 @Bean
 public Foo foo() {
  return new Foo(bar1);
 }

}

I find the method parameter approach simpler here:

@Configuration
public class AppConfig {

 @Bean
 public Foo foo(@Qualifier("bar1") Bar bar1) {
  return new Foo(bar1);
 }

}


Thoughts?

5 comments: