Spring – Anotación @PostConstruct y @PreDestroy con ejemplo

Spring es uno de los marcos Java EE más populares. Es un marco ligero de código abierto que permite a los desarrolladores de Java EE 7 crear aplicaciones empresariales sencillas, fiables y escalables. Este marco se centra principalmente en proporcionar varias formas de ayudarlo a administrar sus objetos comerciales. Hizo que el desarrollo de aplicaciones web fuera mucho más fácil en comparación con los marcos Java clásicos y las interfaces de programación de aplicaciones (API), como la conectividad de base de datos Java (JDBC), JavaServer Pages (JSP) y Java Servlet. Este marco utiliza varias técnicas nuevas, como la programación orientada a aspectos (AOP), el objeto Java antiguo simple (POJO) y la inyección de dependencia (DI), para desarrollar aplicaciones empresariales. Ahora hablando de Spring Annotation

Las anotaciones de Spring son una forma de metadatos que proporcionan datos sobre un programa. Las anotaciones se utilizan para proporcionar información complementaria sobre un programa. No tiene un efecto directo sobre el funcionamiento del código que anotan. No cambia la acción del programa compilado. 

Entonces, lo que sucede es que cada vez que configuramos Spring Beans usando la inyección de dependencia , a veces queremos asegurarnos de que todo se inicialice correctamente antes de que el bean comience a atender las requests del cliente. Del mismo modo, cuando se destruye el contexto, es posible que tengamos que cerrar algunos recursos utilizados por Spring Beans. 

Primavera @PostConstruct Anotación

Por lo general, cada vez que anotamos un método en Spring Bean con la anotación @PostConstruct, se ejecuta después de inicializar Spring Bean. Solo podemos tener un método anotado con la anotación @PostConstruct. Esta anotación es parte de la API de anotaciones comunes y es parte del módulo JDK javax.annotation-api

Primavera @PreDestroy Anotación

Cuando anotamos un método Spring Bean con la anotación PreDestroy, se llama cuando la instancia del bean se elimina del contexto. Recuerde que si su ámbito de bean de primavera es «prototipo», entonces no está completamente administrado por el contenedor de primavera y no se llamará al método PreDestroy. Si hay un método llamado apagado o cerrado, el contenedor de primavera intentará configurarlos automáticamente como métodos de devolución de llamada cuando se destruya el bean.

Adición de anotaciones @PostConstruct y @PreDestroy en el proyecto

Los desarrolladores que usan Java 9+, tanto las anotaciones @PostConstruct como @PreDestroy son parte de Java EE. Y dado que Java EE quedó obsoleto en Java 9 y se eliminó en Java 11, debemos agregar una dependencia adicional para usar estas anotaciones:

A. Si está utilizando Maven

<dependency>
   <groupId>javax.annotation</groupId>
   <artifactId>javax.annotation-api</artifactId>
   <version>1.3.2</version>
</dependency>

B. Si agrega el frasco manualmente

Visite el enlace y dentro de la columna de archivos, verá pom y jar. Haga clic en el frasco y se descargará su frasco. Agréguelo al classpath como un jar externo configurando el archivo build. Puede consultar este artículo para agregar un archivo JAR externo a un proyecto de IntelliJ IDEA o consultar este para agregar un archivo JAR externo a un proyecto de Eclipse .

Nota : si tiene Java 8 o una versión inferior, no tendrá que realizar las tareas anteriores.

Implementación: vamos a explicar @PostConstruct y @PreDestroy Annotation simplemente creando un proyecto Spring JDBC. Así que primero creemos un proyecto Spring JDBC. 

Requisito previo: tutorial de JDBC

Paso 1: Cree un proyecto Java simple en su IDE preferido (IntelliJ IDEA o Eclipse). Puedes consultar estos artículos:

Paso 2: crea algunas tablas dentro de tu base de datos. En este artículo, hemos utilizado la base de datos MySQL. Y los siguientes datos han estado presentes dentro de nuestra base de datos MySQL.

Data Inside our MySQL Database

Así que aquí studentdb es nuestro nombre de esquema y hostelstudentinfo es el nombre de la tabla. De manera similar, puede crear su propio esquema y tabla y colocar algunos datos dentro de esa tabla manualmente. 

Sugerencia: puede consultar estos artículos:

Paso 3: Vaya al proyecto Java y cree una clase llamada StudentDAO y dentro de la clase, vamos a crear un único método selectAllRows() para obtener todos los datos presentes dentro de nuestra base de datos MySQL. También vamos a declarar nuestros cuatro atributos más importantes para conectar nuestro programa Java con el servidor MySQL.

  • Conductor
  • URL
  • Usuario
  • Clave

Ejemplo:

Java

// Java Program to Illustrate StudentDAO class
 
// Importing required classes
import java.sql.*;
 
// Class
public class StudentDAO {
 
    // Class data members
    private String driver;
    private String url;
    private String userName;
    private String password;
 
    // Setter methods for
    // Setter Injection
    public void setDriver(String driver)
    {
        // This keyword refers to current instance itself
        this.driver = driver;
    }
 
    // Setter
    public void setUrl(String url) { this.url = url; }
 
    // Setter
    public void setUserName(String userName)
    {
        this.userName = userName;
    }
 
    // Setter
    public void setPassword(String password)
    {
        this.password = password;
    }
 
    // Method
    public void selectAllRows()
        throws ClassNotFoundException, SQLException
    {
        System.out.println("Retrieving all student data..");
 
        // Loading driver using forname() method
        Class.forName(driver);
 
        // Getting a connection
        Connection con = DriverManager.getConnection(
            url, userName, password);
 
        // Executing a query
        Statement stmt = con.createStatement();
 
        ResultSet rs = stmt.executeQuery(
            "SELECT * FROM studentdb.hostelstudentinfo");
 
        // Iterating over till condition holds true
        while (rs.next()) {
            int studentId = rs.getInt(1);
            String studentName = rs.getString(2);
            double hostelFees = rs.getDouble(3);
            String foodType = rs.getString(4);
 
            // Print statement
            System.out.println(studentId + " " + studentName
                               + " " + hostelFees + " "
                               + foodType);
        }
 
        // Closing the connection
        // using close() method
        con.close();
    }
}

Paso 4: ahora tenemos que agregar los archivos JAR externos a un proyecto IntelliJ IDEA. Un JAR (Java Archive) es un formato de archivo de paquete que normalmente se usa para agregar muchos archivos de clase Java y metadatos y recursos asociados (texto, imágenes, etc.) en un solo archivo para distribuir software de aplicación o bibliotecas en la plataforma Java. En palabras simples, un archivo JAR es un archivo que contiene una versión comprimida de archivos .class, archivos de audio, archivos de imagen o directorios. Tenemos que agregar los siguientes archivos jar externos a nuestro proyecto Java

  • Primavera
  • Conector MySQL

Puede descargar el archivo jar desde los siguientes enlaces:

Paso 5: Vamos a crear el bean de la clase StudentDAO dentro del archivo beans.xml e inyectar los valores de las propiedades mediante inyección de setter. Puede consultar este artículo Primavera – Inyección de valores literales por inyección Setter . A continuación se muestra el código para el archivo beans.xml .

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
 
    <bean id="studentDAO" class="StudentDAO">
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/studentdb"/>
        <property name="userName" value="root"/>
        <property name="password" value="your password"/>
    </bean>
 
</beans>

Paso 6: cree la clase principal y probemos si nuestra aplicación funciona bien o no. A continuación se muestra el código del archivo Main.java .

Java

// Java Program to Illustrate Application File
 
// Importing required classes
import java.sql.SQLException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
// Application class
public class Main {
 
    // Main driver method
    public static void main(String[] args)
        throws SQLException, ClassNotFoundException
    {
 
        // Implementing Spring IoC
        // using ApplicationContext
        ApplicationContext context
            = new ClassPathXmlApplicationContext(
                "beans.xml");
 
        // Getting the bean studentDAO
        StudentDAO studentDAO = context.getBean(
            "studentDAO", StudentDAO.class);
 
        // Calling the method
        studentDAO.selectAllRows();
    }
}

Salida: se puede ver que hemos obtenido con éxito los datos de la base de datos MySQL.

Retrieving all student data..
1 Asish 300.5 Veg
2 Vicky 245.89 Non Veg
3 Anshul 123.67 Veg

Nota: Entonces, ¿cuál es el problema con el código anterior? El problema es que supongamos que queremos definir otro método deleteStudentRecord(int studentId) en la clase StudentDAO, como se muestra en el siguiente ejemplo: 

Ejemplo

Java

// Java Program Illustrating Method to Delete Student Record
 
public void deleteStudentRecord(int studentId)
    throws ClassNotFoundException, SQLException
{
    // Display message
    System.out.println("Deleting student data..");
 
    // Loading driver using forName() Method
    Class.forName(driver);
 
    // Getting a connection
    Connection con = DriverManager.getConnection(
        url, userName, password);
 
    // Executing a query
    Statement stmt = con.createStatement();
 
    stmt.executeUpdate(
        "delete from studentdb.hostelstudentinfo where Student_id = "
        + studentId);
    System.out.println("Record Deleted with the ID "
                       + studentId);
 
    // Closing the connections
    // using close() method
    con.close();
}

Ahora puedes ver que tenemos que escribir algunas líneas de código una y otra vez. Entonces piense si supongamos que queremos realizar 100 operaciones diferentes, tenemos que escribir el mismo código una y otra vez. Así que lo que podemos hacer. Podemos escribir el código común dentro de un método y podemos invocar el método. Podemos escribir algo como esto dentro de un método llamado createStudentDBConnection()

Ejemplo

Java

// Java Program Illustrating Method to Create StudentDB
// Connection
 
// Method
public void createStudentDBConnection()
    throws ClassNotFoundException, SQLException
{
 
    // Loading driver
    Class.forName(driver);
 
    // Getting a connection
    con = DriverManager.getConnection(url, userName,
                                      password);
 
    // Executing a query
    stmt = con.createStatement();
}

Del mismo modo, también podemos definir otro método para cerrar la conexión. Podemos escribir algo como esto dentro de un método llamado closeConnection()

public void closeConnection() throws SQLException 
{
  con.close();
}

Y podemos invocar esos métodos dentro de selectAllRows() y deleteStudentRecord() algo como esto.

Ejemplo

Java

// Java Program to Illustrate StudentDAO Class
 
// Importing required classes
import java.sql.*;
 
// Class
public class StudentDAO {
 
    // Class data members
    private String driver;
    private String url;
    private String userName;
    private String password;
 
    // Connection Object
    Connection con;
 
    // Statement Object
    Statement stmt;
 
    // Setter
    public void setDriver(String driver)
    {
        this.driver = driver;
    }
 
    // Setter
    public void setUrl(String url) { this.url = url; }
 
    // Setter
    public void setUserName(String userName)
    {
        this.userName = userName;
    }
 
    // Setter
    public void setPassword(String password)
    {
        this.password = password;
    }
 
    // Creating connection
    public void createStudentDBConnection()
        throws ClassNotFoundException, SQLException
    {
 
        // Loading  driver
        Class.forName(driver);
 
        // Getting a connection
        con = DriverManager.getConnection(url, userName,
                                          password);
 
        // Executing query
        stmt = con.createStatement();
    }
 
    // Method 1
    public void selectAllRows()
        throws ClassNotFoundException, SQLException
    {
        System.out.println("Retrieving all student data..");
 
        // Create connection
        createStudentDBConnection();
 
        ResultSet rs = stmt.executeQuery(
            "SELECT * FROM studentdb.hostelstudentinfo");
 
        while (rs.next()) {
            int studentId = rs.getInt(1);
            String studentName = rs.getString(2);
            double hostelFees = rs.getDouble(3);
            String foodType = rs.getString(4);
 
            System.out.println(studentId + " " + studentName
                               + " " + hostelFees + " "
                               + foodType);
        }
 
        // Closing the connection
        closeConnection()
    }
 
    // Method 2
    public void deleteStudentRecord(int studentId)
        throws ClassNotFoundException, SQLException
    {
        System.out.println("Deleting student data..");
 
        // Create connection
        createStudentDBConnection();
 
        stmt.executeUpdate(
            "delete from studentdb.hostelstudentinfo where Student_id = "
            + studentId);
        System.out.println("Record Deleted with the ID "
                           + studentId);
 
        // Close the connection
        closeConnection();
    }
 
    // Method 3
    // Close the connection
    public void closeConnection() throws SQLException
    {
        con.close();
    }
}

Pero estamos haciendo lo mismo otra vez. Estamos llamando al método createStudentDBConnection() y closeConnection() una y otra vez dentro de los métodos selectAllRows() y deleteStudentRecord() . Supongamos que tenemos un total de 100 métodos de utilidad como ese, entonces tenemos que llamar a estos métodos 100 veces. Así que le diremos a nuestro framework Spring que una vez que usted (framework Spring) cree el bean, ejecute el método createStudentDBConnection() . Entonces, la forma en que le vamos a decir al marco Spring es colocando la anotación @PostConstruct . En resumen, podemos decir que

Hola Spring, una vez que haya creado el objeto StudentDAO, cree createStudentDBConnection() usted mismo. No espere a que lo llamemos. 

Así que ahora podemos poner la anotación @PostConstruct antes de createStudentDBConnection() algo como esto

Java

@PostConstruct
public void createStudentDBConnection() throws ClassNotFoundException, SQLException {
        // load driver
        Class.forName(driver);
 
        // get a connection
        con = DriverManager.getConnection(url, userName, password);
 
        // execute query
        stmt = con.createStatement();
    }

Introduciendo init()

En la aplicación del mundo real, el método init() es el que encontrará en todas partes. También podemos decir que el método init() es un nombre estándar. Por ejemplo, en este proyecto, podemos marcar el método createStudentDBConnection() como init. Aquí , createStudentDBConnection() es el método init() para nosotros. Anote un método con @PostConstruct para usarlo como método init(). No necesitamos llamar al método init(), nuestro marco lo llamará por nosotros. Podemos darle a nuestro método init() el nombre de cualquier cosa. Podemos decirlo init() o podemos decirlo createStudentDBConnection() o xyz() . Así que ahora podemos escribir lo mismo así

Java

@PostConstruct
public void init() throws SQLException, ClassNotFoundException {
        createStudentDBConnection();
    }
 
public void createStudentDBConnection() throws ClassNotFoundException, SQLException {
        // load driver
        Class.forName(driver);
 
        // get a connection
        con = DriverManager.getConnection(url, userName, password);
 
        // execute query
        stmt = con.createStatement();
    }

¿Por qué inicializar()?

  • Puede agregar código/lógica personalizados durante la inicialización del bean
  • Se puede utilizar para configurar recursos como base de datos/socket/archivo, etc.

Introduciendo destruir()

Se llamará al método destroy() antes de que el bean se elimine del contenedor. Ahora pasemos al método closeConnection() . Definimos este método para limpiar las referencias no utilizadas. Por ejemplo, en este proyecto la variable con . Entonces podemos hacer cualquier método como método destroy() marcándolo como @PreDestroy . Así que ahora podemos escribir el código algo así

Java

public void closeConnection() throws SQLException {
        con.close();
    }
 
@PreDestroy
public void destroy() throws SQLException {
        closeConnection();
    }

Tenga en cuenta que también podemos usar la anotación @PreDestroy antes del método closeConnection(). Ahora el código completo para la clase StudentDAO.java es

Java

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.sql.*;
 
public class StudentDAO {
 
    private String driver;
    private String url;
    private String userName;
    private String password;
 
    // Connection Object
    Connection con;
 
    // Statement Object
    Statement stmt;
 
    public void setDriver(String driver) {
        this.driver = driver;
    }
 
    public void setUrl(String url) {
        this.url = url;
    }
 
    public void setUserName(String userName) {
        this.userName = userName;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
 
    @PostConstruct
    public void init() throws SQLException, ClassNotFoundException {
        createStudentDBConnection();
    }
 
    public void createStudentDBConnection() throws ClassNotFoundException, SQLException {
        // load driver
        Class.forName(driver);
 
        // get a connection
        con = DriverManager.getConnection(url, userName, password);
 
        // execute query
        stmt = con.createStatement();
    }
 
    public void selectAllRows() throws ClassNotFoundException, SQLException {
 
        System.out.println("Retrieving all student data..");
 
        ResultSet rs = stmt.executeQuery("SELECT * FROM studentdb.hostelstudentinfo");
 
        while (rs.next()) {
            int studentId = rs.getInt(1);
            String studentName = rs.getString(2);
            double hostelFees = rs.getDouble(3);
            String foodType = rs.getString(4);
 
            System.out.println(studentId + " " + studentName + " " + hostelFees + " " + foodType);
        }
    }
 
    public void deleteStudentRecord(int studentId) throws ClassNotFoundException, SQLException {
        System.out.println("Delete student data..");
 
        stmt.executeUpdate("delete from studentdb.hostelstudentinfo where Student_id = " + studentId);
        System.out.println("Record Deleted with the ID " + studentId);
    }
 
    public void closeConnection() throws SQLException {
        con.close();
    }
 
    @PreDestroy
    public void destroy() throws SQLException {
        closeConnection();
    }
}

Antes de ejecutar la aplicación, asegúrese de haber agregado la siguiente línea dentro de su archivo beans.xml para usar la anotación

<context:annotation-config/>

El código completo para el archivo beans.xml se proporciona a continuación.

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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
 
    <context:annotation-config/>
 
    <bean id="studentDAO" class="StudentDAO">
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/studentdb"/>
        <property name="userName" value="root"/>
        <property name="password" value="143@Arpilu"/>
    </bean>
 
</beans>

El código completo para el archivo Main.java se proporciona a continuación.

Java

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import java.sql.SQLException;
 
public class Main {
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
       
        // Using ApplicationContext tom implement Spring IoC
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
       
        // Get the bean studentDAO
        StudentDAO studentDAO = context.getBean("studentDAO", StudentDAO.class);
       
        // Calling the method
        studentDAO.deleteStudentRecord(2);
        studentDAO.selectAllRows();
    }
}

Producción:

Delete student data..
Record Deleted with the ID 2
Retrieving all student data..
1 Asish 300.5 Veg
3 Anshul 123.67 Veg

Publicación traducida automáticamente

Artículo escrito por AmiyaRanjanRout y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *