Close

Spring - Using ObjectProvider to Inject shorter-lived Scoped Bean into longer-lived Scoped Bean

[Last Updated: Oct 17, 2022]

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

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

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

Example

package com.logicbig.example;

public class MyPrototypeBean {
  private String message;

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

  public String getMessage() {
      return message;
  }
}
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("%s, prototype instance id: %s%n",
              bean.getMessage(), System.identityHashCode(bean));
  }
}

JavaConfig and main method

package com.logicbig.example;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class AppConfig {

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

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

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

      bean = context.getBean(MySingletonBean.class);
      bean.showMessage();
  }
}

Output

My Prototype Bean, prototype instance id: 1341487403
My Prototype Bean, prototype instance id: 2059201215

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("My Prototype Bean");
  }

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

Output

My Prototype Bean, prototype instance id: 285891949
My Prototype Bean, prototype instance id: 285891949

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("My Prototype Bean");
  }

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

Output

Default Bean, prototype instance id: 1936873997
Default Bean, prototype instance id: 1661918190

Example Project

Dependencies and Technologies Used:

  • spring-context 5.3.23 (Spring Context)
     Version Compatibility: 5.0.0.RELEASE - 5.3.23 Version List
    ×

    Version compatibilities of spring-context with this example:

    • 5.0.0.RELEASE
    • 5.0.1.RELEASE
    • 5.0.2.RELEASE
    • 5.0.3.RELEASE
    • 5.0.4.RELEASE
    • 5.0.5.RELEASE
    • 5.0.6.RELEASE
    • 5.0.7.RELEASE
    • 5.0.8.RELEASE
    • 5.0.9.RELEASE
    • 5.0.10.RELEASE
    • 5.0.11.RELEASE
    • 5.0.12.RELEASE
    • 5.0.13.RELEASE
    • 5.0.14.RELEASE
    • 5.0.15.RELEASE
    • 5.0.16.RELEASE
    • 5.0.17.RELEASE
    • 5.0.18.RELEASE
    • 5.0.19.RELEASE
    • 5.0.20.RELEASE
    • 5.1.0.RELEASE
    • 5.1.1.RELEASE
    • 5.1.2.RELEASE
    • 5.1.3.RELEASE
    • 5.1.4.RELEASE
    • 5.1.5.RELEASE
    • 5.1.6.RELEASE
    • 5.1.7.RELEASE
    • 5.1.8.RELEASE
    • 5.1.9.RELEASE
    • 5.1.10.RELEASE
    • 5.1.11.RELEASE
    • 5.1.12.RELEASE
    • 5.1.13.RELEASE
    • 5.1.14.RELEASE
    • 5.1.15.RELEASE
    • 5.1.16.RELEASE
    • 5.1.17.RELEASE
    • 5.1.18.RELEASE
    • 5.1.19.RELEASE
    • 5.1.20.RELEASE
    • 5.2.0.RELEASE
    • 5.2.1.RELEASE
    • 5.2.2.RELEASE
    • 5.2.3.RELEASE
    • 5.2.4.RELEASE
    • 5.2.5.RELEASE
    • 5.2.6.RELEASE
    • 5.2.7.RELEASE
    • 5.2.8.RELEASE
    • 5.2.9.RELEASE
    • 5.2.10.RELEASE
    • 5.2.11.RELEASE
    • 5.2.12.RELEASE
    • 5.2.13.RELEASE
    • 5.2.14.RELEASE
    • 5.2.15.RELEASE
    • 5.2.16.RELEASE
    • 5.2.17.RELEASE
    • 5.2.18.RELEASE
    • 5.2.19.RELEASE
    • 5.2.20.RELEASE
    • 5.2.21.RELEASE
    • 5.2.22.RELEASE
    • 5.3.0
    • 5.3.1
    • 5.3.2
    • 5.3.3
    • 5.3.4
    • 5.3.5
    • 5.3.6
    • 5.3.7
    • 5.3.8
    • 5.3.9
    • 5.3.10
    • 5.3.11
    • 5.3.12
    • 5.3.13
    • 5.3.14
    • 5.3.15
    • 5.3.16
    • 5.3.17
    • 5.3.18
    • 5.3.19
    • 5.3.20
    • 5.3.21
    • 5.3.22
    • 5.3.23

    Versions in green have been tested.

  • JDK 8
  • Maven 3.8.1

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

    See Also