Spring 3.0, started supporting JSR-330 standard annotations (Dependency Injection). That means now we can use @jakarta.inject.Inject (@javax.inject.Inject pre Spring 6)instead of @Autowire along with other standard annotations and interfaces.
To solve shorter-lived scoped bean injection problem (tutorial), we now have a standard option, i.e. using jakarta.inject.Provider<T> interface:
The Provider interface
package jakarta.inject;
........
public interface Provider<T> {
....
T get();
}
In Spring application we can inject Provider<T> :
@Autowired
private Provider<MyPrototypeBean> myPrototypeBeanProvider;
According to the specification, Provider.get() will always return the new instance of MyPrototypeBean.
We won't need any other extra configuration in @Configuration class. We just have to return instance of MyPrototypeBean bean from one of the factory method, annotated with @Bean.
Having this interface injected has other advantages as well e.g. lazy retrieval of an instance etc.
The good thing is, this approach doesn't involve any runtime byte code generation but it's just like Spring's ObjectFactory implementation. ObjectFactory is Spring specific alternative to Provider interface. In the following example with can replace Provider with ObjectFactory without any other change.
Example
Prototype bean
package com.logicbig.example;
import java.time.LocalDateTime;
public class MyPrototypeBean {
private String dateTimeString = LocalDateTime.now().toString();
public String getDateTime() {
return dateTimeString;
}
}
Singleton bean
package com.logicbig.example;
import org.springframework.beans.factory.annotation.Autowired;
import jakarta.inject.Provider;
public class MySingletonBean {
@Autowired
private Provider<MyPrototypeBean> myPrototypeBeanProvider;
public void showMessage () {
MyPrototypeBean bean = myPrototypeBeanProvider.get();
System.out.println("Hi, the time is " + bean.getDateTime());
}
}
Configuration and Main class
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();
}
@Bean
public MySingletonBean singletonBean() {
return new MySingletonBean();
}
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();
}
}
OutputHi, the time is 2023-10-13T21:06:26.509193800 Hi, the time is 2023-10-13T21:06:27.520053100
Example ProjectDependencies and Technologies Used: - spring-context 6.1.2 (Spring Context)
Version Compatibility: 3.2.3.RELEASE - 6.1.2 Version compatibilities of spring-context with this example: Versions in green have been tested.
- jakarta.inject-api 2.0.1 (Jakarta Dependency Injection)
- JDK 17
- Maven 3.8.1
|