Showing posts with label spring-bean-lifecycle. Show all posts
Showing posts with label spring-bean-lifecycle. Show all posts

Tuesday, 24 May 2011

init-method and destroy-method attribute in Spring

Sometimes it required to call a (non-static) method in the bean only-once at the ApplicationContext load up, just to initialize the bean components. So you may inject some parameters by setters or constructors, but than you may have some other fields, which have to instantiated from those fields or separately like from some local file.

So for this various approaches are available. See here for these approaches.

Consider the Student service example we saw here. Also note the approach of doing the same thing by using @PostConstruct and @PreDestroy annotations.

Service Bean:

public class StudentService {

String message;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}


public void initIt() throws Exception {
System.out.println("After properties has been set : " + message);
//do some initialization
}


public void cleanUp() throws Exception {
System.out.println("Cleaned Everyting");
}

}


Bean config file (initMethod.xml):

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
>
<!-- our bean here -->
<bean id="studentService" class="com.xxxx.StudentService"
init-method="initIt" destroy-method="cleanUp">
<property name="message" value="property message" />
</bean>

<beans>


Running the program:


public class Runner 
{
public static void main( String[] args )
{
ConfigurableApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"initMethod.xml"});

StudentService stud =
(StudentService)context.getBean("studentService");

System.out.println(stud );

context.close();
}
}

Initializing the bean by some init method using Spring

Sometimes it required to call a (non-static) method in the bean only-once at the ApplicationContext load up, just to initialize the bean components. So you may inject some parameters by setters or constructors, but than you may have some other fields, which have to instantiated from those fields or separately like from some local file.

So for this various approaches are available. See here for these approaches.

  1. Using init-method attribute. This method is discussed here.
    Pros – doesn't require bean to implement an interface
  2. Implement InitializingBean
    Cons – more invasive than init-method approach
  3. Use JSR-250 @PostConstruct lifecycle annotation. This method is discussed here.
    Pros :

    Useful when using component scanning to autodetect beans.

    Makes it clear that a specific method is to be used for initialisation

    Cons:

    Initialisation no longer centrally specified in configuration. Now scattered throughout code.

Sunday, 15 May 2011

Lazy loading vs pre-loading beans in spring framework

Spring framework can instantiate and load related Java objects (called beans) according to a given configuration. An XML file can easily be used to define these bindings. Spring framework supports two different types of loading methods; lazy loading and pre-loading respectively managed by BeanFactory and ApplicationContext containers.

Lazy Loading

A bean is loaded only when an instance of that Java class is requested by any other method or a class. org.springframework.beans.factory.BeanFactory (and subclasses) container loads beans lazily. Following code snippet demonstrate lazy loading, concentrate on how "beans.xml" spring configuration file is loaded by BeanFactory container class.
BeanFactory factory = new XmlBeanFactory(
new InputStreamResource(
new FileInputStream("beans.xml"))); // 1
Employee emp = (Employee) factory.getBean("employeeBean"); // 2


Even though "beans.xml" configuration file is loaded with BeanFactory container in line number 1, none of the beans will be instantiated. Instantiation takes place only at line number 2, where bean called "employeeBean" is requested from container. Since the class is instantiated at getBean() method call, time spend to return this method will vary depending on the instantiated object.




Pre-loading


All beans are instantiated as soon as the spring configuration is loaded by a container. org.springframework.context.ApplicationContext container follows pre-loading methodology.

ApplicationContext context =
new ClassPathXmlApplicationContext("beans.xml"); // 1
Employee emp = (Employee) context.getBean("employeeBean"); // 2


As all singleton beans are instantiated by container at line number 1, this line will take some considerable time to complete. However line number 2 will return the bean instance immediately since instances are already available inside the container.

Point to note

Decision to choose one from these two methods would depend solely on application specific requirements. Some applications need to load as soon as possible while many others would probably willing to spend more time at startup but serve client requests faster. However some of the beans defined in a configuration may only be used rarely, so instantiating such classes at start up would not be a wise decision. Similarly, some Java instances would be highly resource consuming; leading not to instantiate at start up.

Sunday, 20 March 2011

Spring : Life Cycle of bean

Beans are managed by IOC container, having a life cycle associated with it. These are the possible ways of managing there life cycle:

  • Callback API implementation
  • XML configuration
  • Annotations

There are two distinct spring containers one is bean factory and another is application context. Life cycle phases varies a lil in the containers. More precisely, only one additional phase is added in case of application context. Let's see what these phases are:

  1. Instantiate: in this phase container finds the bean's definition and default constructor called.
  2. Autowiring executes
  3. Dependency check performed
  4. setters method of bean called
  5. setBeanFactory () / setApplicationContext () / method called
  6. afterPropertiesSet() / init-method /@PostConstruct method called
  7. Application running, beans ready to work
  8. destroy()/ destroy-method / @PreDestroy method called
    An existing bean can be removed from the container in two ways:
    1. DisposableBean: If bean implements the DisposableBean interface then destroy() method is called.
    2. Call-custom destroy: if custom-destroy method is specified then it is called.

Implementing the life cycle interface

Spring : DisposableBean Interface and InitializingBean

The InitializingBean and DisposableBean are two marker interfaces which call the  afterPropertiesSet() for the begining and destroy() for the last action of initialization and    destruction to be performed.

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class StudentService implements InitializingBean, DisposableBean {
String message;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public void afterPropertiesSet() throws Exception {
System.out.println(" After properties has been set : " + message);
}

public void destroy() throws Exception {
System.out.println("Cleaned everything!!");
}

}


In context.xml bean is created in usual style.

Spring : Lifecycle interface

Lifecycle interface is basically meant for managing startup and shutdown callbacks. For eg., on startup we would like to load data into the cache and on shutdown just clear the cache or start the process at startup and end it when exiting.

So SmartLifecycle is extension of Lifecycle Interface.

Example :

import org.springframework.context.SmartLifecycle;

public class LifecycleImpl implements SmartLifecycle {

public LifecycleImpl() {
System.out.println("LifecycleImpl class instantiated..");
}

@Override
public boolean isAutoStartup() {
System.out.println("isAutoStartup method our LifecyleImpl class called..");
return true;
}

@Override
public void stop(Runnable r) {
System.out.println("stop(Runnable) method of our LifecycleImpl class called..");
r.run();
}

@Override
public boolean isRunning() {
System.out.println("isRunning method of our LifecycleImpl class called..");
return true;
}

@Override
public void start() {
System.out.println("start method of our LifecycleImpl class called..");
}

@Override
public void stop() {
System.out.println("stop method of our LifecycleImpl class called..");
}

@Override
public int getPhase() {
System.out.println("getPhase method of our LifecycleImpl class called..");
return 1;
}
}



Create the bean in simple way in context.xml.

BeanFactoryPostProcessor interface

The semantics of this interface is similar to BeanPostProcessor but with one major difference : BeanFactoryPostProcessor operate on bean configuration metadata; So spring IoC container allow BeanFactoryPostProcessor to read the configuration metadata and potentially change it before the container instantiates any bean other than BeanFactoryPostProcessor .

But if you want to change the actual bean instances( the objects that are created from the configuration metadata), then use BeanPostProcessor.

Example …

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class BeanFactoryPostProcessorImpl implements BeanFactoryPostProcessor {

public BeanFactoryPostProcessorImpl() {
System.out.println("BeanFactoryPostProcessorImpl class instantiated..");
}

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory)
throws BeansException {
System.out.println("postProcessBeanFactory method of our BeanFactoryPostProcessorImpl class called..");

//dynamically registering a new bean in the context. you can try this later on.
//similar to @Configuration and @Bean we saw in previous section.
//factory.registerSingleton("myBean", new SampleBean());
}
}



Again one of the commonly used BeanFactoryPostProcessor is PropertyPlaceHolderConfigurer class. We already have seen the usage of this class before. This replaces the config of any bean containing ${}  with the actual property value so by the time the bean is instantiated, the correct values are already in the container.

@Required annotation

BeanPostProcessor is used by the framework heavily. One of the best example is RequiredAnnotationBeanPostProcessor class. In spring we require @Required annotation to make it a mandatory dependency, that thas to be injected.

Just by using annotation in the code will not work, since someone has to check whether the requirement has been met or not and reposrt an error it not.

Example

//The service
public interface BankService {

public BillPaymentService getBillPaymentService();
public CustomerService getCustomerService();
}

//The impl class
public class BankServiceImpl implements BankService {

private CustomerService customerService;
private BillPaymentService billPaymentService;

@Required
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}

@Required
public void setBillPaymentService(BillPaymentService billPaymentService) {
this.billPaymentService = billPaymentService;
}

public BillPaymentService getBillPaymentService() {
return billPaymentService;
}

public CustomerService getCustomerService() {
return customerService;
}
}


Now here we have mentioned what is required, but we need RequiredAnnotationBeanPostProcessor to check whether these required dependency are injected or not.


The configuration


<!--  According the code, we need to set both the dependencies.
Comment out one or both the property tag and see the error -->
<bean id="bankService" class="com.xxxx.BankServiceImpl">
<property name="billPaymentService" ref="billPaymentService" />
<property name="customerService" ref="customerService" />
</bean>

<!-- Just by using @Required will not work. Someone has to parse it
and that's the role of this class -->
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />


Spring : BeanPostProcessor interface

The interface BeanPostProcessor allows custom modification of all new bean instance like for example making for marker interfaces or wrapping them with all proxies. The advance of interface BeanPostProcessor is that it auto-detect BeanPostProcessor beans in their bean definations and apply all beans before any others get created.

So it provides callback methods thaty you can implement to provide your own instantiation logic, dependency resolution logic and so forth. In a way you override default container's logic.

You can control the order in which these BeanPostProcessor interfaces execute by setting the order property only if the BeanPostProcessor implements the Ordered Interface.

Classes which implement BeanPostProcessor are special and treaded differently by container. All BeanPostProcessor and their directly referenced beans are instantiated on startup, as a part of the special startup phase of the ApplicationContext.

Example:

 

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

class StudentBean implements BeanPostProcessor {

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {

System.out.println("Before initialization : " + beanName);


return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {

System.out.println("After initialization : " + beanName);
return bean;
}
}



So BeanPostProcessor implementation gives us chance to perform custom processing before and after any bean is initialized.


In config.xml


<bean id="studentBean" class="com.roseindia.common.StudentBean" />

@PostConstruct and @PreDestroy example

In this tutorial you will learn how to implement the @PostConstruct and @PreDestroy which work similar to init-method and destroy-method in bean configuration file or implement the InitializingBean and DisposableBean in your bean class. To use @PostConstruct and @PreDestroy you have to register the CommonAnnotationBeanPostProcessor at bean configuration or specifying the <context:annotation-config /> in the bean configuration file.

Consider the service bean:

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class StudentService {

String message;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

@PostConstruct
public void initIt() throws Exception {
System.out.println("After properties has been set : " + message);
}

@PreDestroy
public void cleanUp() throws Exception {
System.out.println("Cleaned Everyting");
}

}


Bean config file:


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
>

<context:annotation-config />

<bean id="studentService" class="com.xxxx.StudentService">
<property name="message" value="property message" />
</bean>

</beans>


Spring : init-method and destroy-method

In this first example, I’ll show you how the lifecycle of a bean happens within the xml-configfile.

In the xml-file, we can define an init- and destroy-method to the bean, which will be called automatically by Spring.
Config.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
>
<!-- -->
<bean id="attributesTest" class="a.Test" init-method="initMethod"
destroy-method="destroyMethod">
</bean>

</beans>

 

Now consider our bean with these 2 methods into it:

 

public class LifeCycledBean2{    
//
public LifeCycledBean2(){
System.out.println("We are in the constructor of LifeCycledBean2");
}
public void initMethod()
{
System.out.println("We are in initMethod of LifeCycledBean2");
}
public void destroyMethod()
{
System.out.println("We are in destroyMethod of Test");
}
}




Main or Runner program
In this case, I’ll use AbstractApplicationContext because this Context has a function to destroy the Context which a normal ApplicationContext doesn’t have.

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class JustATest {
public static void main(String[] args) {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("Config.xml");
ctx.registerShutdownHook();
Test test = ctx.getBean("attributesTest",Test.class);
}
}


The output will be:

We are in the constructor of Test
We are in initMethod of Test
We are in destroyMethod of Test

It’s also possible to declare default init- and destroy-methods in the xml-file. This is done in the beans-tag:

<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"

default-init-method="initMethod"
default-destroy-method="destroyMethod"
>
...

Saturday, 19 March 2011

Spring : BeanNameAware Interface

Consider the following bean:

import org.springframework.beans.factory.BeanNameAware;

public class LifeCycledBean implements BeanNameAware
{
private String languageName;
private String beanName;

public LifeCycledBean ()
{
}

public String getLanguageName()
{
return languageName;
}

public void setLanguageName(String languageName)
{
this.languageName = languageName;
}

@Override
public void setBeanName(String beanName)
{
this.beanName = beanName;
}

public String getBeanName()
{
return beanName;
}
}


The above sample class provides one such implementation and the below client code uses the above class to know the name of the bean.

static void beanNameAwareTest()
{
Resource resource = new FileSystemResource("./src/resources/bean-lifecycle-1.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
LanguageBean lifeCycledBean= (LanguageBean)beanFactory.getBean("lifeCycledBean");
System.out.println(lifeCycledBean.getLanguageName());
System.out.println(lifeCycledBean.getBeanName());
}



The following piece of Xml code snippet goes into the Xml Configuration file.

<bean id="javaLanguage" class="com.xxxx.LifeCycledBean">
<property name="lifeCycledBean" value="Java"/>
</bean>