Close

Spring - Using ObjectProvider to Inject Narrower Scoped Bean

[Last Updated: Jun 4, 2020]

In this example we are going to use org.springframework.beans.factory.ObjectProvider<T> to solve narrower bean injection problem.

The use of ObjectProvider is very simpler to using javax.inject.Provider<T>.

ObjectProvider has added various new methods in Spring 5.0 which use Java 8 java.util.function callbacks (tutorial).

Example

public class MyPrototypeBean {
  @Autowired
  private BeanNameFormatter beanNameFormatter;
  private String dateTimeString = LocalDateTime.now().toString();
  private String name;

  public MyPrototypeBean(String name) {
      this.name = name;
  }

  public String getDateTime() {
      return dateTimeString;
  }

  public String getFormattedName() {
      return beanNameFormatter.formatName(name);
  }
}
package com.logicbig.example;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;

public class MySingletonBean {

  @Autowired
  private ObjectProvider<MyPrototypeBean> myPrototypeBeanProvider;

  public void showMessage() {
      MyPrototypeBean bean = myPrototypeBeanProvider.getIfAvailable(
              () -> new MyPrototypeBean("Default Bean"));
      System.out.printf("Time: %s from bean: %s - instance: %s%n", bean.getDateTime(), bean.getFormattedName(),
              System.identityHashCode(bean));
  }
}
package com.logicbig.example;


public class BeanNameFormatter {
  public String formatName(String name) {
      return String.format("Formatted Bean Name: %s%n", name);
  }
}

JavaConfig and main method

@Configuration
public class AppConfig {

  @Bean
  @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  public MyPrototypeBean prototypeBean() {
      return new MyPrototypeBean("Registered Bean");
  }

  @Bean
  public MySingletonBean singletonBean() {
      return new MySingletonBean();
  }

  @Bean
  public BeanNameFormatter beanNameFormatterBean() {
      return new BeanNameFormatter();
  }

  public static void main(String[] args) throws InterruptedException {
      AnnotationConfigApplicationContext context =
              new AnnotationConfigApplicationContext(AppConfig.class);
      MySingletonBean bean = context.getBean(MySingletonBean.class);
      bean.showMessage();
      Thread.sleep(1000);

      bean = context.getBean(MySingletonBean.class);
      bean.showMessage();
  }
}
Time: 2020-06-05T00:04:05.187058200 from bean: Formatted Bean Name: Registered Bean
- instance: 1125736023
Time: 2020-06-05T00:04:06.197291500 from bean: Formatted Bean Name: Registered Bean
- instance: 1201484275

If we don't use prototype scope (i.e. use the same scope, singleton for both beans) then same bean instance will be used:

@Configuration
public class AppConfig {

  @Bean
  //@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  public MyPrototypeBean prototypeBean() {
      return new MyPrototypeBean("Registered Bean");
  }
 ....
}
Time: 2020-06-05T00:04:09.114761600 from bean: Formatted Bean Name: Registered Bean
- instance: 1125736023
Time: 2020-06-05T00:04:10.121716700 from bean: Formatted Bean Name: Registered Bean
- instance: 1201484275

If we do not register MyPrototypeBean at all then default bean created by the supplier of ObjectProvider#getIfAvailable(supplier) will be used:

@Configuration
public class AppConfig {

  //@Bean
  //@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  public MyPrototypeBean prototypeBean() {
      return new MyPrototypeBean("Registered Bean");
  }
 ....
}
Time: 2020-06-05T00:04:13.062290 from bean: Formatted Bean Name: Registered Bean
- instance: 1125736023
Time: 2020-06-05T00:04:14.069995300 from bean: Formatted Bean Name: Registered Bean
- instance: 1201484275

Example Project

Dependencies and Technologies Used:

  • spring-context 5.2.6.RELEASE: Spring Context.
  • JDK 1.8
  • Maven 3.5.4

Using Spring's ObjectProvider for Prototype Bean Select All Download
  • spring-object-provider-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • MyPrototypeBean.java

    See Also