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();
}
}
OutputMy 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();
}
.............
} OutputMy 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();
}
.............
} OutputDefault Bean, prototype instance id: 1936873997 Default Bean, prototype instance id: 1661918190
Example ProjectDependencies and Technologies Used: - spring-context 6.1.2 (Spring Context)
Version Compatibility: 5.0.0.RELEASE - 6.1.2 Version compatibilities of spring-context with this example: Versions in green have been tested.
- JDK 17
- Maven 3.8.1
|