Showing posts with label Spring Bean Lifecycle. Show all posts
Showing posts with label Spring Bean Lifecycle. Show all posts

Monday, 20 August 2018

Spring Bean Life Cycle - Spring @PostConstruct and @PreDestroy Annotations | Spring Tutorial

🚀 Master Java & Spring with Ram N Java!

Subscribe to Ram N Java for simplified guides, clean coding examples, and in-depth software engineering tutorials.

🔔 Subscribe on YouTube

What Are @PostConstruct and @PreDestroy Annotations?

In the Spring Framework, managing the lifecycle of a bean is essential for initializing resources and ensuring clean shutdowns. The @PostConstruct and @PreDestroy annotations are part of the standard Java annotations (JSR-250) supported seamlessly by Spring.

They offer a clean, readable, annotation-driven approach to execute custom startup and teardown logic without coupling your classes to Spring-specific interfaces.

Understanding @PostConstruct

The @PostConstruct annotation is placed on a method that needs to run immediately after dependency injection is complete and the bean has been fully initialized.

  • Initialization Logic: Ideal for loading configuration files, opening database connections, or pre-caching required data.
  • Safety: Guarantees that all autowired properties and dependencies are ready to use.

Understanding @PreDestroy

The @PreDestroy annotation marks a callback method that executes just before the Spring container destroys the bean instance during application shutdown.

  • Resource Cleanup: Used to close open streams, release file locks, or shut down active worker threads safely.
  • Graceful Shutdown: Prevents memory leaks and connection hanging when your application stops.

📺 Recommended Spring Tutorials from Ram N Java


Click here to watch on Youtube:
https://www.youtube.com/watch?v=DdQy0raenwI&list=UUhwKlOVR041tngjerWxVccw

Click the below Image to Enlarge:
Spring Bean Life Cycle - Spring @PostConstruct and @PreDestroy Annotations | Spring Tutorial


Spring Bean Life Cycle - Spring @PostConstruct and @PreDestroy Annotations | Spring Tutorial

Spring Bean Life Cycle - Spring @PostConstruct and @PreDestroy Annotations | Spring Tutorial

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0%20http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.ram.core</groupId>
    <artifactId>SpringDemo</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>SpringDemo</name>
    <url>http://maven.apache.org</url>

    <properties>
        <spring.version>5.0.2.RELEASE</spring.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <!-- Spring 5 dependencies -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>
</project>

Employee.java

package com.ram.model;

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

public class Employee
{
    private int id;
    private String name;

    public int getId()
    {
        return id;
    }

    public void setId(int id)
    {
        this.id = id;
    }

    public String getName()
    {
        return name;
    }

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

    @PostConstruct
    public void init() throws Exception
    {
        System.out.println("inside Init method after properties are set. ");
    }
   
    @PreDestroy
    public void cleanUp() throws Exception
    {
        System.out.println("Inside cleanUp(), Performed clean up tasks.");
    }

    @Override
    public String toString()
    {
        return "Employee [id=" + id + ", name=" + name + "]";
    }

}

applicationContext.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-4.3.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.3.xsd">


    <bean id="employee" class="com.ram.model.Employee" >
        <property name="id" value="100"></property>
        <property name="name" value="Peter"></property>
    </bean>

    <context:annotation-config />

</beans>

App.java

package com.ram.core;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ram.model.Employee;

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

        System.out.println("---------------------------------------");

        Employee employee = context.getBean("employee", Employee.class);
        System.out.println(
                "Got employee object from the ApplicationContext(Spring Container)");

        System.out.println(employee);

        context.close();
    }

}

Output

Aug 07, 2018 10:27:26 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5b37e0d2: startup date [Tue Aug 07 10:27:26 IST 2018]; root of context hierarchy
Aug 07, 2018 10:27:26 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [applicationContext.xml]
inside Init method after properties are set.
---------------------------------------
Got employee object from the ApplicationContext(Spring Container)
Employee [id=100, name=Peter]
Aug 07, 2018 10:27:26 AM org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@5b37e0d2: startup date [Tue Aug 07 10:27:26 IST 2018]; root of context hierarchy
Inside cleanUp(), Performed clean up tasks.

Click the below link to download the code:
https://sites.google.com/site/ramj2eev2/java_basics/SpringDemo_PostConstruct_PreDestroy.zip?attredirects=0&d=1

Github Link:
https://github.com/ramram43210/javaee/tree/master/Spring_2018/SpringDemo_PostConstruct_PreDestroy

Bitbucket Link:
https://bitbucket.org/ramram43210/spring/src/924507f5515578f632825f98c99b1cb6c7d7a7be/Spring_2018/SpringDemo_PostConstruct_PreDestroy/?at=master

See also:

  • All JavaEE Videos Playlist
  • All JavaEE Videos
  • All JAVA EE Links
  • Spring Tutorial
  • Servlets Tutorial
  • All Design Patterns Links
  • JDBC Tutorial
  • Java Collection Framework Tutorial
  • JAVA Tutorial
  • Kids Tutorial
  • Cooking Tutorial
  • Spring Bean Life Cycle - Spring init-method and destroy-method | Spring Tutorial

    🚀 Enjoying Java & Spring Tutorials?

    Subscribe to Ram N Java for beginner-friendly, hands-on programming guides!

    🔔 Subscribe Now

    What are init-method and destroy-method?

    In Spring, beans often need to execute custom setup logic when they are created and custom cleanup logic when they are destroyed. You can configure custom callback methods declaratively in the Spring XML configuration file using the init-method and destroy-method attributes.

    • init-method: Specifies a custom method inside your bean class that the Spring Container calls immediately after the bean is instantiated and all its dependencies are injected.
    • destroy-method: Specifies a custom method called just before the container destroys the bean and releases its resources.

    Why Use XML-Based Lifecycle Configuration?

    Configuring lifecycle callbacks via XML offers distinct advantages for modular architecture:

    • Zero Code Coupling: Your Java class remains pure and independent of any Spring-specific interfaces (such as InitializingBean or DisposableBean).
    • Flexible Method Naming: You can choose descriptive method names like init(), setup(), cleanup(), or destroy().
    • Externalized Configuration: Lifecycle behaviors can be modified entirely through XML configuration files without recompiling Java source code.

    XML Configuration Example

    Here is how you define a bean with custom lifecycle methods in your Spring XML configuration file:

    <bean id="myBean" class="com.ram.MyBean" init-method="init" destroy-method="destroy" />

    Related Tutorials from Ram N Java


    Click here to watch on Youtube:
    https://www.youtube.com/watch?v=wa2nphKki2I&list=UUhwKlOVR041tngjerWxVccw

    Click the below Image to Enlarge:

    Spring Bean Life Cycle - Spring init-method and destroy-method | Spring Tutorial

    Spring Bean Life Cycle - Spring init-method and destroy-method | Spring Tutorial

    Spring Bean Life Cycle - Spring init-method and destroy-method | Spring Tutorial

    pom.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0%20http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.ram.core</groupId>
        <artifactId>SpringDemo</artifactId>
        <packaging>jar</packaging>
        <version>1.0-SNAPSHOT</version>
        <name>SpringDemo</name>
        <url>http://maven.apache.org</url>

        <properties>
            <spring.version>5.0.2.RELEASE</spring.version>
        </properties>

        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>3.8.1</version>
                <scope>test</scope>
            </dependency>

            <!-- Spring 5 dependencies -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>

            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
        </dependencies>
    </project>

    Employee.java

    package com.ram.model;

    public class Employee
    {
        private int id;
        private String name;

        public int getId()
        {
            return id;
        }

        public void setId(int id)
        {
            this.id = id;
        }

        public String getName()
        {
            return name;
        }

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

        public void init() throws Exception
        {
            System.out.println("inside Init method after properties are set. ");
        }

        public void cleanUp() throws Exception
        {
            System.out.println("Inside cleanUp(), Performed clean up tasks.");
        }

        @Override
        public String toString()
        {
            return "Employee [id=" + id + ", name=" + name + "]";
        }

    }

    applicationContext.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-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd">


        <bean id="employee" class="com.ram.model.Employee" init-method="init"
            destroy-method="cleanUp">
            <property name="id" value="100"></property>
            <property name="name" value="Peter"></property>
        </bean>

    </beans>

    App.java

    package com.ram.core;

    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    import com.ram.model.Employee;

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

            System.out.println("---------------------------------------");

            Employee employee = context.getBean("employee", Employee.class);
            System.out.println(
                    "Got employee object from the ApplicationContext(Spring Container)");

            System.out.println(employee);

            context.close();
        }

    }

    Output

    Aug 07, 2018 9:46:31 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
    INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5b37e0d2: startup date [Tue Aug 07 09:46:31 IST 2018]; root of context hierarchy
    Aug 07, 2018 9:46:31 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    INFO: Loading XML bean definitions from class path resource [applicationContext.xml]
    inside Init method after properties are set.
    ---------------------------------------
    Got employee object from the ApplicationContext(Spring Container)
    Employee [id=100, name=Peter]
    Aug 07, 2018 9:46:31 AM org.springframework.context.support.AbstractApplicationContext doClose
    INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@5b37e0d2: startup date [Tue Aug 07 09:46:31 IST 2018]; root of context hierarchy
    Inside cleanUp(), Performed clean up tasks.

    Click the below link to download the code:
    https://sites.google.com/site/ramj2eev2/java_basics/SpringDemo_init-method_destroy-method.zip?attredirects=0&d=1

    Github Link:
    https://github.com/ramram43210/javaee/tree/master/Spring_2018/SpringDemo_init-method_destroy-method

    Bitbucket Link:
    https://bitbucket.org/ramram43210/spring/src/924507f5515578f632825f98c99b1cb6c7d7a7be/Spring_2018/SpringDemo_init-method_destroy-method/?at=master

    See also:

  • All JavaEE Videos Playlist
  • All JavaEE Videos
  • All JAVA EE Links
  • Spring Tutorial
  • Servlets Tutorial
  • All Design Patterns Links
  • JDBC Tutorial
  • Java Collection Framework Tutorial
  • JAVA Tutorial
  • Kids Tutorial
  • Cooking Tutorial
  • Friday, 17 August 2018

    Spring Bean Life Cycle - Spring InitializingBean and DisposableBean | Spring Tutorial

    🚀 Enjoying Java & Spring Tutorials?

    Subscribe to Ram N Java for beginner-friendly, hands-on programming guides!

    🔔 Subscribe Now

    What are InitializingBean and DisposableBean?

    In the Spring Framework, managing the creation and destruction phases of your objects is essential for setup operations and clean resource management. Spring provides two core programmatic callback interfaces: InitializingBean and DisposableBean.

    • InitializingBean: Provides the afterPropertiesSet() method, which the Spring container invokes immediately after all bean properties are set and dependencies are injected.
    • DisposableBean: Provides the destroy() method, which is invoked when the Spring container shuts down and the bean instance is being destroyed.

    How Does It Work?

    By directly implementing these interfaces in your bean class, Spring automatically detects and invokes the lifecycle hooks without needing extra configuration:

    • Automatic Invocation: Spring executes afterPropertiesSet() after initialization and destroy() on container shutdown.
    • Programmatic Approach: Useful when you want explicit contract enforcement for initialization and cleanup logic directly inside your Java class.

    Sample Implementation Code

    Here is an example of implementing both interfaces in a Spring bean:

    public class DatabaseService implements InitializingBean, DisposableBean { @Override public void afterPropertiesSet() throws Exception { System.out.println("Init: Database connection initialized."); } @Override public void destroy() throws Exception { System.out.println("Clean up: Database connection closed."); } }

    Related Tutorials from Ram N Java


    Click here to watch on Youtube:
    https://www.youtube.com/watch?v=8JilnzXYHIA&list=UUhwKlOVR041tngjerWxVccw

    Click the below Image to Enlarge:

    Spring Bean Life Cycle - Spring InitializingBean and DisposableBean | Spring Tutorial

    Spring Bean Life Cycle - Spring InitializingBean and DisposableBean | Spring Tutorial

    Spring Bean Life Cycle - Spring InitializingBean and DisposableBean | Spring Tutorial

    pom.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0%20http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.ram.core</groupId>
        <artifactId>SpringDemo</artifactId>
        <packaging>jar</packaging>
        <version>1.0-SNAPSHOT</version>
        <name>SpringDemo</name>
        <url>http://maven.apache.org</url>

        <properties>
            <spring.version>5.0.2.RELEASE</spring.version>
        </properties>

        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>3.8.1</version>
                <scope>test</scope>
            </dependency>

            <!-- Spring 5 dependencies -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>

            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
        </dependencies>
    </project>

    Employee.java

    package com.ram.model;

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

    public class Employee implements InitializingBean, DisposableBean
    {
        private int id;
        private String name;

        public int getId()
        {
            return id;
        }

        public void setId(int id)
        {
            this.id = id;
        }

        public String getName()
        {
            return name;
        }

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

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

        public void destroy() throws Exception
        {
            System.out.println("Inside destroy(), Performed clean up tasks.");
        }

        @Override
        public String toString()
        {
            return "Employee [id=" + id + ", name=" + name + "]";
        }

    }

    applicationContext.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-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd">


        <bean id="employee" class="com.ram.model.Employee">
            <property name="id" value="100"></property>
            <property name="name" value="Peter"></property>
        </bean>

    </beans>

    App.java

    package com.ram.core;

    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    import com.ram.model.Employee;

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

            System.out.println("---------------------------------------");

            Employee employee = context.getBean("employee", Employee.class);
            System.out.println(
                    "Got employee object from the ApplicationContext(Spring Container)");

            System.out.println(employee);

            context.close();
        }

    }

    Output

    Aug 06, 2018 10:35:53 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
    INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5b37e0d2: startup date [Mon Aug 06 10:35:53 IST 2018]; root of context hierarchy
    Aug 06, 2018 10:35:53 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    INFO: Loading XML bean definitions from class path resource [applicationContext.xml]
    inside afterPropertiesSet().
    ---------------------------------------
    Got employee object from the ApplicationContext(Spring Container)
    Employee [id=100, name=Peter]
    Aug 06, 2018 10:35:54 AM org.springframework.context.support.AbstractApplicationContext doClose
    INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@5b37e0d2: startup date [Mon Aug 06 10:35:53 IST 2018]; root of context hierarchy
    Inside destroy(), Performed clean up tasks.

    Click the below link to download the code:
    https://sites.google.com/site/ramj2eev2/java_basics/SpringDemo_InitializingBean_DisposableBean.zip?attredirects=0&d=1

    Github Link:
    https://github.com/ramram43210/javaee/tree/master/Spring_2018/SpringDemo_InitializingBean_DisposableBean

    Bitbucket Link:
    https://bitbucket.org/ramram43210/spring/src/476437cc0ec4e46c307e790b2c10c4099b1c066b/Spring_2018/SpringDemo_InitializingBean_DisposableBean/?at=master

    See also:

  • All JavaEE Videos Playlist
  • All JavaEE Videos
  • All JAVA EE Links
  • Spring Tutorial
  • Servlets Tutorial
  • All Design Patterns Links
  • JDBC Tutorial
  • Java Collection Framework Tutorial
  • JAVA Tutorial
  • Kids Tutorial
  • Cooking Tutorial
  • Tutorials