Below are the steps of a Spring Bean Lifecycle:
- Within the IoC Container, the constructor is called of the bean.
2. Now the dependency injection is performed using setter method.
3. Once the dependency injection is completed all the Aware specific interface methods are called if they have been in implemented in the bean.
4. Now the IoC container callsBeanPostProcessor.postProcessBeforeInitialization
on the bean. Using this method a wrapper can be applied on original bean.
5. Now the method annotated with@PostConstruct
is called.
6. After@PostConstruct
, the methodInitializingBean.afterPropertiesSet()
is called.
7. Now the method specified by@Bean
is called.
8. And thenBeanPostProcessor.postProcessAfterInitialization()
is called. It can also be used to apply wrapper on original bean.
9. Now the bean instance is ready to be used. Perform the task using the bean.
10. Now when theApplicationContext
shuts down such as by usingregisterShutdownHook()
then the method annotated with@PreDestroy
is called.
11. After thatDisposableBean.destroy()
method is called on the bean.
12. Now the method specified bydestroy-method
attribute of bean in XML configuration is called.
13. Before garbage collection,finalize()
method ofObject
is called.
Lets run an example code:
@Configuration public class Book implements InitializingBean, DisposableBean, BeanFactoryAware, BeanNameAware, BeanClassLoaderAware { private String bookName; public Book() { System.out.println("---inside constructor---"); } @Override public void setBeanClassLoader(ClassLoader classLoader) { System.out.println("---BeanClassLoaderAware.setBeanClassLoader---"); } @Override public void setBeanName(String name) { System.out.println("---BeanNameAware.setBeanName---"); } @Bean public void myPostConstruct() { System.out.println("---init-method---"); } @PostConstruct public void springPostConstruct() { System.out.println("---@PostConstruct---"); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("---BeanFactoryAware.setBeanFactory---"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("---InitializingBean.afterPropertiesSet---"); } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; System.out.println("setBookName: Book name has set."); } public void myPreDestroy() { System.out.println("---destroy-method---"); } @PreDestroy public void springPreDestroy() { System.out.println("---@PreDestroy---"); } @Override public void destroy() throws Exception { System.out.println("---DisposableBean.destroy---"); } @Override protected void finalize() { System.out.println("---inside finalize---"); } }
If you run the above code from the below main application:
public static void main(String[] args) { ApplicationContext context=SpringApplication.run(SpringDemoApplication.class, args); Book book=context.getBean(Book.class); book.setBookName("Harry Potter"); System.out.println("Book Name:"+ book.getBookName()); ((ConfigurableApplicationContext)context).close(); }
The output:
---inside constructor--- ---BeanNameAware.setBeanName--- ---BeanClassLoaderAware.setBeanClassLoader--- ---BeanFactoryAware.setBeanFactory--- ---@PostConstruct--- ---InitializingBean.afterPropertiesSet--- ---init-method--- setBookName: Book name has set. Book Name:Harry Potter ---@PreDestroy--- ---DisposableBean.destroy---
Whenever we declare a class with @Component annotation, spring IoC container takes care of the lifecycle of that bean automatically. Suppose we want to take care of the bean, then below methods are for that:
@PostConstruct
This will be called after the bean is created with all dependencies.
import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.springframework.stereotype.Component; @Component public class MyBean { @PostConstruct public void postConsMethod() { System.out.println("----> @PostConstruct called"); } @PreDestroy public void preDesMethod() { System.out.println("-----> @PreDestroy called"); } }
@PreDestroy
This will be called just before the bean is destroyed.
You have to close the Application Context to see its effect. To close it first you have to get hold of the context object, then close it.
ConfigurableApplicationContext context=SpringApplication.run(MyMainClass.class, args); context.close();