
1. Overview
In this article, we will learn about the lazy loading of beans in BeanFactory.
2. BeanFactory
The Spring framework comes with two IOC containers:
BeanFactory
ApplicationContext
The BeanFactory
is the root interface for accessing a Spring bean container whereas ApplicationContext
extends the BeanFactory
and its functionalities.
The Spring IOC container gets its instructions on what bean objects to instantiate, configure, and assemble by reading configuration metadata. We can represent the configuration metadata using any of the below:
- XML configuration
- Annotation-based configuration
- Java-based configuration.
It lets you express the objects that compose your application and the rich interdependencies between those objects. See this bean instantiation article to understand more.
2.1. Bean Initialization
BeanFactory
uses lazy initialization but ApplicationContext
uses eager initialization. The BeanFactory
creates the beans when you invoke or use the beans such as getBeans()
method, whereas the ApplicationContext eagerly creates and configures all singleton beans as part of the initialization process.
This pre-instantiation is desirable because you can discover any errors in the configuration or surrounding environment immediately during application start-up, as opposed to runtime hours or even days later.
When this behavior is not desirable, you can prevent pre-instantiation of a singleton bean by marking the bean definition as lazy-initialized. You can refer to this article to learn more about lazy initialization.
2.2. BeanFactory lazy loading
Let’s see an example to confirm the default lazy loading of beans in BeanFactory
.
First, let’s create a sample class and its instance needs to be managed by the BeanFactory
Spring IOC container.
We will instruct the BeanFactory
to instantiate using the constructor. Note that we have added a print statement in the constructor to check whether the sample bean is instantiated during load time eagerly or at runtime.
public class SampleBean { private int value; public SampleBean(int value) { System.out.println("SampleBean initialized"); this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } }
Now, let’s create an XML configuration by defining the beans that need to be managed by BeanFactory
container.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="employee" class="com.tedblob.beanfactory.models.SampleBean"> <constructor-arg value="1000" /> </bean> </beans>
In the below test case, we are loading the BeanFactory
pointing to the config.xml
configuration
@Test public void testBeanFactoryLazyInitialization() { Resource res = new ClassPathResource("config.xml"); BeanFactory factory = new XmlBeanFactory(res); }
If you execute the above test case, you cannot see any “SampleBean initialized” print statement in the logs. This confirms that the BeanFactory
loads the beans lazily.
Let’s modify the test case a little bit to confirm this.
@Test public void testBeanFactoryLazyInitialization() { Resource res = new ClassPathResource("config.xml"); BeanFactory factory = new XmlBeanFactory(res); SampleBean sampleBean = factory.getBean(SampleBean.class); sampleBean.getValue(); }
If you execute this test case now, the “SampleBean initialized” text will appear in the logs as invoking getBean
method would initialize the bean at runtime.
3. Conclusion
To sum up, we have learned that the BeanFactory loads the beans lazily and an example to confirm the behavior. You can find code samples of this article in our GitHub repository.