How to use Spring ObjectProvider with more than one bean definition

Viewed 5352

I am using an ObjectProvider to create instances of a prototype scope bean using the getObject() method. Something like this

  @Configuration
  class Config {
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    SomeType typeOne() {
      return new SomeType();
    }
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    SomeType typeTwo(String param) {
      return new SomeType(param);
    }
  }

  @Service
  class Service {

    private ObjectProvider<SomeType> objectProvider;

    public Service(
      ObjectProvider<SomeType> objectProvider) {
      this.objectProvider = objectProvider;
    }

    @Override
    public String performAction() {
      return getSomeType().doAction();
    }

    private SomeType getSomeType() {
      return objectProvider.getObject();
    }
  }

But since there are two beans of the type that the ObjectProvider is trying to get (SomeType), I get a NoUniqueBeanDefinitionException. (And I do need the other bean of the same type, because that one I need to provide parameters using objectProvider.getObject(Object... params) )

Playing around and debugging Spring I saw that if you name your ObjectProvider exactly like your bean then it works, something like:

private ObjectProvider<SomeType> typeOne;

My question is, are there other ways to use an ObjectProvider and manage to resolve ambiguity, or is this approach the way to go?

1 Answers

Short answer is you just need to properly qualify the ObjectProvider you want injected, like this:

public Service(@Qualifier("typeOne") ObjectProvider<SomeType> objectProvider) {
  this.objectProvider = objectProvider;
}

With Spring configuration, when you specify a bean via a method, and don't specify it's name with @Bean("NAME"), Spring uses the method name as the bean name.

Similarly, when injecting a bean that is not specified by @Qualifier("NAME"), Spring takes the injected variable as the name, if that don't exists or is not unique, you might get some exceptions informing you about this (like the NoUniqueBeanDefinitionException you facing).

So, if you match the bean name and the injected variable name you don't need to be more specific, but if you don't, @Qualifier is there to your rescue :D

Related