Explain Codes LogoExplain Codes Logo

Spring Java Config: how do you create a prototype-scoped @Bean with runtime arguments?

java
singleton
lambda
best-practices
Alex KataevbyAlex Kataev·Mar 7, 2025
TLDR

Elevate your Spring coding game by using the ServiceLocatorFactoryBean for creating prototype beans with runtime arguments:

// MyBeanFactory: an interface to freedom (from XML config) public interface MyBeanFactory { MyBean create(String arg); } @Configuration public class AppConfig { // BeanFactory: The magician behind the curtains @Bean public ServiceLocatorFactoryBean beanFactory() { ServiceLocatorFactoryBean factory = new ServiceLocatorFactoryBean(); factory.setServiceLocatorInterface(MyBeanFactory.class); // don't ask it about rabbits! return factory; } // MyBean: Your trusty bean. No XML were harmed in creating it! @Bean @Scope("prototype") public MyBean myBean(String arg) { return new MyBean(arg); } }

To retrieve a brand new bean instance with runtime arguments:

@Autowired private MyBeanFactory factory; public void useBean() { MyBean myBean = factory.create("value"); // like ordering at a fast-food joint ;) // use your fresh myBean as desired }

This pattern lets Spring context abstract bean creation while enjoying the perks of prototype-scoping with runtime arguments.

Enhancing bean accessibility with ObjectProvider

Applying Spring's ObjectProvider

Facilitate bean retrieval using Spring's ObjectProvider which enhances programmatic flexibility:

@Autowired private ObjectProvider<MyBean> myBeanProvider; public MyBean getMyBeanWithArg(String arg) { return myBeanProvider.getObject(arg); // MyBean, report for duty with arg! }

ObjectProvider is designed to gracefully handle bean resolution both for optional dependencies and non-unique bean scenarios.

Exploring the power of Java 8 functional interfaces

Spring supports Java's Functional Interfaces for multiple parameters, enabling a clear contract for your bean:

@FunctionalInterface // License to create public interface MyBeanFactory { MyBean create(String arg1, int arg2); // Dual wield your parameters }

In your @Configuration class, use lambda expressions to implement this factory method providing a quick 'n' clean technique:

@Bean public MyBeanFactory myBeanFactory() { return (arg1, arg2) -> new MyBean(arg1, arg2); // Constructing MyBean in a jiffy! }

Going deep with AutowireCapableBeanFactory

To use constructor injection for prototype beans, meet Spring's AutowireCapableBeanFactory:

@Autowired private AutowireCapableBeanFactory beanFactory; // The Bean Wizard public MyBean createMyBean(String arg) { return (MyBean) beanFactory.createBean(MyBean.class, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false); // MyBean at your service, constructor-injected! }

This technique takes care of the bean's complete lifecycle from initialization to destruction.

Ready your defences against NoSuchBeanDefinitionException. Manage scnenarios where dependencies are optional or non-unique with ObjectProvider:

public void handleBeanCreation() { try { MyBean myBean = myBeanProvider.getIfAvailable(() -> new MyBean("default")); // Fresh or default, you decide! } catch (NoSuchBeanDefinitionException ex) { // Handle this exception like a boss } }

Exploring dynamic bean factories

Diving into dynamic bean factories

Imagine a bean factory that molds itself based on parameters known only at runtime. Spring supports such dynamic creation of beans. It's especially useful for prototype-scoped beans.

Leveraging Spring's conditionals

Combine this concept with Spring's @Conditional annotations. Your factory methods can smartly declare beans only when certain conditions are met, resulting in a lean and efficient Spring context:

@ConditionalOnProperty(name = "myBean.enabled", havingValue = "true") @Bean @Scope("prototype") public MyBean conditionalMyBean(String arg) { // Crafty crafting of MyBean based on conditions return new MyBean(arg); }

Embracing container managed beans

In Spring, every call to getBean results in a brand new instance of a prototype bean. It's fully initialized and ready to be used. Less time managing beans' lifecycle, more focus on your business logic.