Quantcast
Channel: Tech Tutorials
Viewing all articles
Browse latest Browse all 892

Lazy Initializing Spring Beans

$
0
0

By default, in Spring framework, all the singleton beans are eagerly created and configured by ApplicationContext as part of the initialization process. Though this behavior of pre-instantiation is desirable most of the time as you can detect errors in the configuration immediately. But sometimes you may have a large object graph and loading all those beans in the beginning itself may be expensive. In that kind of scenario you can prevent pre-instantiation of a singleton bean by marking the bean definition as lazy-initialized.

If you mark a bean as lazy-initialized in Spring that means IoC container will create a bean instance when it is first requested, rather than at startup.

Here note that when a lazy-initialized bean is a dependency of a singleton bean that is not lazy initialized, the ApplicationContext creates the lazy-initialized bean at startup, because it must satisfy the singleton’s dependencies.

How to configure bean as lazy-initialized in Spring

You can configure bean as lazy-initialized in both XML based configuration and Java based configuration. In XML configuration you need to add lazy-init attribute on the <bean/> element.

In case of Java configuration you need to use @Lazy annotation.

Let’s see Spring example for both these type of configurations.

XML Configuration example for lazy initializing beans

In this example there are two beans PayServiceImpl and CashPayment. For PayServiceImpl bean lazy-init attribute is true.

Interface IpayService


public interface IPayService {
void performPayment();
}

PayServiceImpl.java


import javax.annotation.PostConstruct;

public class PayServiceImpl implements IPayService{
private IPayment payment;
public PayServiceImpl(){

}
public PayServiceImpl(IPayment payment){
this.payment = payment;
}

public void performPayment() {
System.out.println("performPayment Method called");
}

@PostConstruct
public void annoInitMethod(){
System.out.println("Calling InitMethod for PayServiceImpl");
}
public IPayment getPayment() {
return payment;
}

public void setPayment(IPayment payment) {
this.payment = payment;
}
}

CashPayment.java


import javax.annotation.PostConstruct;

public class CashPayment implements IPayment{
public void executePayment() {
System.out.println("Perform Cash Payment ");
}
@PostConstruct
public void annoInitMethod(){
System.out.println("Calling InitMethod for CashPayment");
}
}

In these classes you can see that Spring bean life cycle initialization method annotated with @PostConstruct is used to see when bean is actually initialized.

XML Configuation


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
<!-- Defining PayServiceImpl bean -->
<bean id="payServiceBean" class="org.netjs.exp.Spring_Example.PayServiceImpl" lazy-init="true"/>
<bean id="cashPaymentBean" class="org.netjs.exp.Spring_Example.CashPayment" />

</beans>
You can run it using the following code.

public class App {
public static void main( String[] args ){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
("appcontext.xml");
System.out.println("Loading app context");

IPayService bean = (IPayService) context.getBean("payServiceBean");
}
}

Output


INFO: Loading XML bean definitions from class path resource [appcontext.xml]
Calling InitMethod for CashPayment
Loading app context
Calling InitMethod for PayServiceImpl

You can see that the CashPayment bean which is not lazy-initialized is initialized while loading the XML bean definitions where as PayServiceImpl bean is initialized when it is first requested.

Making lazy initialized default behaviour in Spring

If you want to make it a default behaviour at the container level that all the beans are lazy initialized then you can add default-lazy-init attribute on the <beans/> element; for example:


<beans default-lazy-init="true">
<!-- no beans will be pre-instantiated... -->
<bean>bean definitions </bean>
</beans>

Spring Java Configuration example for lazy initializing beans

If we use the same two classes as above PayServiceImpl and CashPayment. Then the Java config class where PayServiceImpl bean is marked as lazy will look like as follows.


import org.netjs.exp.Spring_Example.CashPayment;
import org.netjs.exp.Spring_Example.IPayService;
import org.netjs.exp.Spring_Example.IPayment;
import org.netjs.exp.Spring_Example.PayServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

@Configuration
public class AppConfig {
@Bean
@Lazy
public IPayService payService(){
PayServiceImpl payServiceImpl = new PayServiceImpl();

return new PayServiceImpl(cashPayment());
//return null;
}

@Bean
public IPayment cashPayment(){
return new CashPayment();
}
}

Here note @Lazy annotation is used to mark PayServiceImpl as lazy initialized.

To run it you can use the following code.


import org.netjs.exp.Spring_Example.IPayService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

public class App {
public static void main( String[] args ){
AbstractApplicationContext context = new AnnotationConfigApplicationContext(
AppConfig.class);
System.out.println("Loading AnnotationConfig app context");
IPayService bean = (IPayService) context.getBean("payService");

context.close();
}
}

output


Calling InitMethod for CashPayment
Loading AnnotationConfig app context
Calling InitMethod for PayServiceImpl

Here again you can see that the CashPayment bean which is not lazy-initialized is initialized while loading the bean definitions where as PayServiceImpl bean is initialized when it is first requested.

If you want to lazy initialized all the beans then use the annotation @Lazy at the class level.


@Configuration
@Lazy
public class AppConfig {
..
..
}

That's all for this topic Lazy Initializing Spring Beans. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How to Inject Prototype Scoped Bean in Singleton Bean
  2. Injecting Inner Bean in Spring
  3. Different Bean Scopes in Spring
  4. Wiring Collections in Spring
  5. Bean Definition Inheritance in Spring

You may also like -

>>>Go to Spring Tutorial Page


Viewing all articles
Browse latest Browse all 892

Trending Articles