Spring lazy-init Examples

0

In this article, we will look into spring’s default-lazy-init and lazy-init attributes. We will come to know about how the attributes influence the instantiation of the bean. default-lazy-init is the default attribute which will be specified in the beans element. One can override it using lazy-int attribute at bean/code> level.

Dependencies

Add the following dependencies:

  1. spring-core
  2. spring-context
  3. spring-beans

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javarticles.jdbc.datasource</groupId>
	<artifactId>springdatasource</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>${spring.version}</version>
		</dependency>
	</dependencies>

	<properties>
		<spring.version>3.2.3.RELEASE</spring.version>
	</properties>

</project>

Default behavior of default-lazy-init

Let’s first look into the default behavior of default-lazy-init which means what will be the behavior if the attribute is not present? Will it be lazily loaded or eagerly. The default behavior is eager loading.

noDefaultLazyInitContext.xml:

<?xml version="1.0" encoding="UTF-8"?>

<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.xsd"
	default-init-method="myInit">

	<bean id="testBean" class="com.javarticles.spring.TestBean">
		<constructor-arg type="java.lang.String" value="A" />
	</bean>

</beans>

Our TestBean has myInit() method will be invoked after the bean is instantiated. We also have a static variable isInitialized which will let us know whether it is instantiated.

TestBean:

package com.javarticles.spring;

public class TestBean {
    private TestBean innerBean;
    private String value;
    public static boolean isInitialized;
    public TestBean(){isInitialized = true;}
    public TestBean(String value) {
        this();
        this.value = value;
    }
    public String getValue() {
        return value;
    }
    public TestBean getInnerBean() {
        return innerBean;
    }
    public void setValue(String value) {
        this.value = value;
    }    
    public void myDestroy() {
        System.out.println("myDestroy called for TestBean(" + value + ")");
    }
    public void myInit() {
        System.out.println("myInit called for TestBean(" + value + ")");
    }
    public void setInnerBean(TestBean innerBean) {
        this.innerBean = innerBean;
    }
    public String toString() {
        return "TestBean: value[" + value + "]";
    }
}

Let’s load the context file and verify the TestBean.isInitialized to know whether TestBean is instantiated.

LazyInitExample:

package com.javarticles.spring;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LazyInitExample {
    public static void main(String[] args) {
        printBeanInitStatus("default-lazy-init is not set: ", "noDefaultLazyInitContext.xml");     
    }

    private static void printBeanInitStatus(String useCase, String contextXml) {
        printBeanInitStatus(useCase, contextXml, false);
    }
    
    private static void printBeanInitStatus(String useCase, String contextXml, boolean getBean) {
        TestBean.isInitialized = false;
        System.out.println(useCase);
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                contextXml);
        try {
            System.out.println("Is TestBean Initialized: " + TestBean.isInitialized);
            if (getBean) {
                System.out.println("Bean is created only when context.getBean is called");
                System.out.println(context.getBean("testBean"));
            }
        } finally {
            context.close();
        }        
    }
}

You can see from the output, it is instantiated. This will help us know during loading phase itself in case our bean has some issue.

Output:

default-lazy-init is not set: 
myInit called for TestBean(A)
Is TestBean Initialized: true

default-lazy-init set to true

Since default-lazy-init is set to true, TestBean shouldn’t be created during the loading phase. It should be instantiated lazily when we call context.getBean("testBean")

defLazyInitTrueContext.xml:

<?xml version="1.0" encoding="UTF-8"?>

<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.xsd"
	default-init-method="myInit"
	default-lazy-init="true">

	<bean id="testBean" class="com.javarticles.spring.TestBean">
		<constructor-arg type="java.lang.String" value="A" />
	</bean>

</beans>

LazyInitExample:

package com.javarticles.spring;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LazyInitExample {
    public static void main(String[] args) {
        printBeanInitStatus("default-lazy-init is not set: ", "noDefaultLazyInitContext.xml");
        printBeanInitStatus("default-lazy-init is set to true: ", "defLazyInitTrueContext.xml", true);    
    }

    private static void printBeanInitStatus(String useCase, String contextXml) {
        printBeanInitStatus(useCase, contextXml, false);
    }
    
    private static void printBeanInitStatus(String useCase, String contextXml, boolean getBean) {
        TestBean.isInitialized = false;
        System.out.println(useCase);
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                contextXml);
        try {
            System.out.println("Is TestBean Initialized: " + TestBean.isInitialized);
            if (getBean) {
                System.out.println("Bean is created only when context.getBean is called");
                System.out.println(context.getBean("testBean"));
            }
        } finally {
            context.close();
        }        
    }
}

Output:

default-lazy-init is not set: 
myInit called for TestBean(A)
Is TestBean Initialized: true
default-lazy-init is set to true:
Is TestBean Initialized: false
Bean is created only when context.getBean is called
myInit called for TestBean(A)
TestBean: value[A]

Override lazy-init

overrideLazyInitTrueContext.xml:

<?xml version="1.0" encoding="UTF-8"?>

<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.xsd"
	default-init-method="myInit" default-lazy-init="true">

	<bean id="testBean" class="com.javarticles.spring.TestBean"
		lazy-init="false">
		<constructor-arg type="java.lang.String" value="A" />
	</bean>

</beans>

LazyInitExample:

package com.javarticles.spring;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LazyInitExample {
    public static void main(String[] args) {
        printBeanInitStatus("default-lazy-init is not set: ", "noDefaultLazyInitContext.xml");
        printBeanInitStatus("default-lazy-init is set to true: ", "defLazyInitTrueContext.xml", true);
        printBeanInitStatus("Override default-lazy-init, set lazy-init to true: ", "overrideLazyInitTrueContext.xml");        
    }

    private static void printBeanInitStatus(String useCase, String contextXml) {
        printBeanInitStatus(useCase, contextXml, false);
    }
    
    private static void printBeanInitStatus(String useCase, String contextXml, boolean getBean) {
        TestBean.isInitialized = false;
        System.out.println(useCase);
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                contextXml);
        try {
            System.out.println("Is TestBean Initialized: " + TestBean.isInitialized);
            if (getBean) {
                System.out.println("Bean is created only when context.getBean is called");
                System.out.println(context.getBean("testBean"));
            }
        } finally {
            context.close();
        }        
    }
}

Output:

default-lazy-init is not set: 
myInit called for TestBean(A)
Is TestBean Initialized: true
default-lazy-init is set to true:
Is TestBean Initialized: false
Bean is created only when context.getBean is called
myInit called for TestBean(A)
TestBean: value[A]
Override default-lazy-init, set lazy-init to true: 
myInit called for TestBean(A)
Is TestBean Initialized: true

Download the source code

This was an example about Spring’s lazy-init attribute. You can download the source code here: springLazyInitExample.zip

Share.

Comments are closed.