Spring Bean Life Cycle - @PostConstruct and @PreDestroy example

Posted on January 21, 2017


Technologies used:   JDK 1.8.0_121 | Spring 4.3.5.RELEASE | Maven 3.3.9 | Eclipse Mars.2 (4.5.2)

In Spring framework, we can manage lifecycle of a bean by using method-level annotations @PostConstruct and @PreDestroy.

The @PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization.

The @PreDestroy annotation is used on methods as a callback notification to signal that the instance is in the process of being removed by the container.

The following examples demonstrate the use of @PostConstruct and @PreDestroy annotations.

Consider the MailService bean, whose init() and destroy() methods are annotated with @PostConstruct and @PreDestroy annotations respectively.

MailService.java

package com.boraji.tutorial.spring;

import java.util.HashMap;
import java.util.Map;

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

import org.springframework.stereotype.Component;

/**
 * @author imssbora
 */
@Component
public class MailService {

   private Map<String, String> map=null;
   
   public MailService() {
      map=new HashMap<>();
   }

   public void send(String mailTo){
      //Code for sending mail
      System.out.println("Inside send method - "+mailTo);
   }
   
   @PostConstruct
   public void init() {
      map.put("host", "mail.example.com");
      map.put("port", "25");
      map.put("from", "[email protected]");
      System.out.println("Inside init method - "+map);
   }

   @PreDestroy
   public void destroy() {
      map.clear();
      System.out.println("Inside destroy method - "+map);
   }
}

Create AppConfig class and write the following code in it.

AppConfig.java

package com.boraji.tutorial.spring;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author imssbora
 */
@Configuration
@ComponentScan(basePackages = "com.boraji.tutorial.spring")
public class AppConfig {
   
}

Note - @ComponentScan annotation scans all beans, whose class is annotated by the @Component annotation in a package, specified by basePackages attribute.

 

Create main class and run application.

MainApp.java

package com.boraji.tutorial.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author imssbora
 */
public class MainApp {
   public static void main(String[] args) {
      AnnotationConfigApplicationContext context = 
            new AnnotationConfigApplicationContext(AppConfig.class);
      
      // Send mail 1
      MailService mailService1 = context.getBean(MailService.class);
      mailService1.send("[email protected]");

      // Send mail 2
      MailService mailService2 = context.getBean(MailService.class);
      mailService2.send("[email protected]");

      context.close();
   }
}

Output

Inside init method - {port=25, host=mail.example.com, [email protected]}
Inside send method - [email protected]
Inside send method - [email protected]
Inside destroy method - {}

As you can see, the init() and destroy() methods of MailService bean are called only once, when the scope of bean is singleton (default scope).

In case of prototype scope, the destroy method of the MailService bean will not work. You can try this by downloading the sources from the below download link.