Spring Bean Life Cycle – Callback Interface, Custom Method, Annotation, Aware Interface

spring-framework-bean-life-cycle-callback-interface-custom-method-annotation-aware-interface-feature-image

Spring Bean Life Cycle is very important because in many applications, we want to create some operations before initializing a Bean or make some operations before bean’s destruction.

This tutorial introduce four ways to control life cycle events of a Bean.

I. Demo

II. Technology

– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.8.1.RELEASE
– Spring Boot: 1.4.0.RELEASE

III. Overview
1. Bean Life Cycle

bean-life-cycle

2. Goal

To build a simple application that expresses how we can provide post-initialization and pre-destroy methods in a Spring Bean Life Cycle.

3. Project Structure

beanlifecycle-structure

4. Step to do

– Create Spring Boot project
– Create Class for Bean
– Create Services
– Create Spring Bean Configuration Files
– Add commands to SpringBootApplication Class
– Run Spring Boot Application & Enjoy Result

IV. Practice
1. Create Spring Boot project

Open Spring Tool Suite, on Menu, choose File -> New -> Spring Starter Project, then fill each field:
beanlifecycle-startproj

Click Next and Finish. Spring Boot project will be created successfully.

2. Create Class for Bean

Under package bean, create class Customer:

public class Customer {
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}
3. Create Services

Under package service, create service classes:

Content of CustomerServiceImpCustomMethod.java

public class CustomerServiceImpCustomMethod implements InitializingBean, DisposableBean {

	private Customer customer;

	public CustomerServiceImpCustomMethod() {
		System.out.println("Call constructor for CustomerServiceImpCustomMethod");
	}

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("afterPropertiesSet(): Bean initialization here");
	}

	@Override
	public void destroy() throws Exception {
		System.out.println("destroy(): Bean destruction here");
	}

	public void customInitBean() throws Exception {
		System.out.println("customInitBean()");
	}

	public void customDestroyBean() throws Exception {
		System.out.println("customDestroyBean()");
	}

	@PostConstruct
	public void postConstruct() {
		System.out.println(
				"post-construct():  perform some initialization after all the setter methods have been called");
	}

	@PreDestroy
	public void predestroy() {
		System.out.println("pre-destroy()");
	}
}

InitializingBean and DisposableBean callback interfaces will be implemented to override 2 methods afterPropertiesSet() and destroy().
custom init() and destroy() methods are defined in configuration bean file (by init-method and destroy-method) and implemented under customInitBean() and customDestroyBean().
@PostConstruct and @PreDestroy annotations which are part of javax.annotation package will be annotated to methods: postConstruct() and preDestroy(). To use those annotations, we must add bean for org.springframework.context.annotation.CommonAnnotationBeanPostProcessor in Bean Configuration File.

– We also use other Aware interfaces for specific behavior such as: setBeanName, setBeanClassLoader, setBeanFactory, setApplicationContext

Content of CustomerServiceImpAwareInterface.java

public class CustomerServiceImpAwareInterface implements ApplicationContextAware, ApplicationEventPublisherAware,
		BeanClassLoaderAware, BeanFactoryAware, BeanNameAware, EnvironmentAware, ResourceLoaderAware {

	private Customer customer;
	private String[] beanNames;

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	public String[] getBeanNames() {
		return beanNames;
	}

	public void setBeanNames(String[] beanNames) {
		this.beanNames = beanNames;
	}

	public CustomerServiceImpAwareInterface() {
		System.out.println("Call constructor for CustomerServiceImpAwareInterface");
	}

	@Override
	public void setBeanName(String beanName) {
		System.out.println("setBeanName()");
		System.out.println("Current Bean Name: " + beanName);
	}

	@Override
	public void setBeanClassLoader(ClassLoader classLoader) {
		System.out.println("setBeanClassLoader()");
		System.out.println("Current ClassLoader Name: " + classLoader.getClass().getName());
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		System.out.println("setBeanFactory()");
		for (String beanName : beanNames)
			System.out.println(
					"The BeanFactory contains Bean \"" + beanName + "\"? : " + beanFactory.containsBean(beanName));
	}

	@Override
	public void setEnvironment(Environment environment) {
		System.out.println("setEnvironment()");
	}

	@Override
	public void setResourceLoader(ResourceLoader resourceLoader) {
		System.out.println("setResourceLoader()");
		Resource resource = resourceLoader.getResource("classpath:bean_imp_aware.xml");
		System.out.println("Current Resource File Name:" + resource.getFilename());
	}

	@Override
	public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
		System.out.println("setApplicationEventPublisher()");
	}

	@Override
	public void setApplicationContext(ApplicationContext context) throws BeansException {
		System.out.println("setApplicationContext()");
		System.out.println("All Beans: " + Arrays.toString(context.getBeanDefinitionNames()));
	}

}
4. Create Spring Bean Configuration Files

Under src/main/resources, create two XML files:

bean_imp_custom_method.xml




	
		
	

	
		
	

	


bean_imp_aware.xml




	
		
	

	
		
		
			
				customerServiceAware
				customer
				dummyBean
			
		
	


5. Add commands to SpringBootApplication Class

Open SpringBeanLifeCycleApplication.java, change the content inside:

@SpringBootApplication
public class SpringBeanLifeCycleApplication {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean_imp_custom_method.xml");

		System.out.println("Context has been initialized");
		CustomerServiceImpCustomMethod service = (CustomerServiceImpCustomMethod) context.getBean("customerServiceCustomerMethod");
		System.out.println("Already retrieved Bean from context. Next, show Bean data.");
		System.out.println("Customer Name: " + service.getCustomer().getName());
		context.close();
		
		System.out.println("-----new testing Context-----");
		System.out.println("-----Spring Aware Interface-----");
		
		context = new ClassPathXmlApplicationContext("bean_imp_aware.xml");
		context.getBean("customerServiceAware", CustomerServiceImpAwareInterface.class);
		context.close();
	}
}
6. Run Spring Boot Application & Enjoy Result

– Config maven build:
clean install
– Run project with mode Spring Boot App
– Check results in Console Screen:

Call constructor for CustomerServiceImpCustomMethod
post-construct():  perform some initialization after all the setter methods have been called
afterPropertiesSet(): Bean initialization here
customInitBean()
Context has been initialized
Already retrieved Bean from context. Next, show Bean data.
Customer Name: Jack
pre-destroy()
destroy(): Bean destruction here
customDestroyBean()
-----new testing Context-----
-----Spring Aware Interface-----
Call constructor for CustomerServiceImpAwareInterface
setBeanName()
Current Bean Name: customerServiceAware
setBeanClassLoader()
Current ClassLoader Name: sun.misc.Launcher$AppClassLoader
setBeanFactory()
The BeanFactory contains Bean "customerServiceAware"? : true
The BeanFactory contains Bean "customer"? : true
The BeanFactory contains Bean "dummyBean"? : false
setEnvironment()
setResourceLoader()
Current Resource File Name:bean_imp_aware.xml
setApplicationEventPublisher()
setApplicationContext()
All Beans: [customer, customerServiceAware]
IV. Source Code

spring-bean-lifecycle

Leave a Reply

Your email address will not be published. Required fields are marked *