Spring – Métodos init() y destroy() con ejemplo

Durante el desarrollo de la aplicación Spring, a veces, cuando se crean los beans Spring, se requiere que los desarrolladores ejecuten las operaciones de inicialización y las operaciones de limpieza antes de que se destruya el bean. En el framework Spring, podemos usar las etiquetas init-method y destroy-method en la configuración del bean. 

método init()

En la aplicación del mundo real, el método init() es el que encontrará en todas partes. init-method es el atributo de la etiqueta spring <bean>. Se utiliza para declarar un método personalizado para el bean que actuará como método de inicialización del bean. Podemos definirlo de la siguiente manera.

<bean id="student" class="com.amiya.Student" init-method="myPostConstruct">

Aquí el método myPostConstruct() es el método de inicialización del bean en la clase Student. Este método de inicialización se llama después de inicializar las propiedades del bean. Podemos usar un método de inicialización de este tipo para validar el valor de las propiedades del bean o inicializar cualquier tarea. La interfaz InitializingBean en spring realiza la misma tarea pero está muy acoplada a spring, por lo que deberíamos preferir el método init.

¿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.

método destroy()

Se llamará al método destroy() antes de que el bean se elimine del contenedor. destroy-method es un atributo de bean mediante el cual podemos asignar un método de bean personalizado que se llamará justo antes de que se destruya el bean. Para usar el atributo destroy-method, hacemos lo siguiente.

<bean id="student" class="com.amiya.Student" destroy-method="myPreDestroy">

Aquí se definirá el método myPreDestroy() en la clase Student. Spring llamará a este método justo antes de destruir el bean. El método destroy se usa para liberar recursos o realizar alguna tarea de destrucción. La interfaz del Bean desechable en primavera realiza la misma tarea, pero está muy acoplada a la primavera, por lo que deberíamos preferir el método de destrucción. Entonces, entendamos estos dos métodos con un ejemplo simple. 

Sugerencia: es bueno seguir con el tutorial de JDBC antes porque sirve como requisito previo.

Implementación:

Vamos a explicar los métodos init() y destroy() a través de las anotaciones @PostConstruct y @PreDestroy simplemente creando un proyecto Spring JDBC. Así que primero creemos un proyecto Spring JDBC. 

Paso 1: Cree un proyecto Java simple en su IDE preferido (IntelliJ IDEA o Eclipse). 

Sugerencia: puede consultar el conjunto de artículos enumerados a continuación de la siguiente manera:

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 el conjunto de artículos enumerados a continuación de la siguiente manera:

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 que se enumeran a continuación de la siguiente manera: 

  1. Conductor
  2. URL
  3. Usuario
  4. 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
    // To select all rows
    public void selectAllRows()
        throws ClassNotFoundException, SQLException
    {
        System.out.println("Retrieving all student data..");
  
        // Loading drivers
        // using forName() method
        Class.forName(driver);
  
        // Getting a connection
        Connection con = DriverManager.getConnection(
            url, userName, password);
  
        // Executing a query
        Statement stmt = con.createStatement();
  
        // Storing it in a ResultSet 
        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
        // 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

Sugerencia: puede consultar el artículo enumerado: Cómo agregar un archivo JAR externo a un proyecto IntelliJ IDEA para el cual el usuario puede descargar el archivo jar desde los enlaces que se proporcionan a continuación de la siguiente manera:

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. 

Sugerencia: puede consultar el artículo enumerado: Spring: inyección de valores literales mediante inyección de Setter

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. 

Archivo: Main.java

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.selectAllRows();
    }
}

Producción:

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

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 algo así como se representa en el siguiente fragmento de código de la siguiente manera:

Archivo: Clase StudentDAO

public void deleteStudentRecord(int studentId)
throws ClassNotFoundException, SQLException 
{

        // Display command only
        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);

        // Printing the deleted record to corresponding ID
        System.out.println("Record Deleted with the ID " + studentId);

        // Close the connection
        // 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()

public void createStudentDBConnection()
throws ClassNotFoundException, SQLException 
{

        // Loading driver
        // using forName() method
        Class.forName(driver);

        // Getting connection
        // using DriverManager
        con = DriverManager.getConnection(url, userName, password);

        // Executing 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. Ahora el código completo para la clase StudentDAO.java se puede escribir como

Archivo: StudentDAO.java

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;
    }
  
    // Method
    // Create connection
    public void createStudentDBConnection()
        throws ClassNotFoundException, SQLException
    {
  
        // Loading driver using forName() method
        Class.forName(driver);
  
        // Getting a connection
        con = DriverManager.getConnection(url, userName,
                                          password);
  
        // Executing a query
        stmt = con.createStatement();
    }
  
    // Method
    // To select all rows
    public void selectAllRows()
        throws ClassNotFoundException, SQLException
    {
  
        // Display message
        System.out.println("Retrieving all student data..");
  
        // Create connection
        createStudentDBConnection();
  
        // Storing it in a ResultSet
        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);
  
            // Printing student attributes
            System.out.println(studentId + " " + studentName
                               + " " + hostelFees + " "
                               + foodType);
        }
  
        // Closing connection
        closeConnection()
    }
  
    // Method
    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
    // 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 oye Spring, una vez que crees el objeto StudentDAO, crea createStudentDBConnection()por tí mismo. No espere a que lo llamemos. 

Anotación Spring @PostConstruct: Por lo general, cada vez que anotamos un método en Spring Bean con la anotación @PostConstruct, se ejecuta después de inicializar el 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

Nota: agregar 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:

Si uno está usando Maven, entonces   

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

De lo contrario, si agrega el jar manualmente, es el siguiente:

  • Visite el enlace y dentro de la columna de archivos, se puede 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: Agregar un archivo JAR externo a un proyecto IntelliJ IDEA o consultar el artículo: Agregar un archivo JAR externo a un proyecto Eclipse .

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

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

@PostConstruct
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();
}

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 dar nuestro nombre de método init() como cualquier cosa. Podemos decirlo init() o podemos decirlo createStudentDBConnection() o xyz() . Así que ahora podemos escribir lo mismo así

@PostConstruct
public void init() throws SQLException, ClassNotFoundException 
{
        createStudentDBConnection();
}

// Method
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();
}

¿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 fragmento de código que se verá así:

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

// Annotation
@PreDestroy
// Method
public void destroy() throws SQLException
{
    closeConnection();
}

Anotación Spring @PreDestroy: 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.

Tenga en cuenta que también podemos usar la anotación @PreDestroy antes del método closeConnection().

Archivo: StudentDAO.java

Java

// Java Program to Illustrate StudentDAO Class
  
// Importing required classes
import java.sql.*;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
  
// 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;
    }
  
    @PostConstruct
    public void init()
        throws SQLException, ClassNotFoundException
    {
        createStudentDBConnection();
    }
  
    // Method 1
    public void createStudentDBConnection()
        throws ClassNotFoundException, SQLException
    {
  
        // Loading driver
        // using forName() method
        Class.forName(driver);
  
        // Getting a connection
        // using DriverManager
        con = DriverManager.getConnection(url, userName,
                                          password);
  
        // Executing query
        stmt = con.createStatement();
    }
  
    // Method 2
    public void selectAllRows()
        throws ClassNotFoundException, SQLException
    {
  
        // Display command
        System.out.println("Retrieving all student data..");
  
        // Storing in a ResultSet
        ResultSet rs = stmt.executeQuery(
            "SELECT * FROM studentdb.hostelstudentinfo");
  
        // Iterating
        while (rs.next()) {
            int studentId = rs.getInt(1);
            String studentName = rs.getString(2);
            double hostelFees = rs.getDouble(3);
            String foodType = rs.getString(4);
  
            // Printing corresponding student attributes
            System.out.println(studentId + " " + studentName
                               + " " + hostelFees + " "
                               + foodType);
        }
    }
  
    // Method 3
    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);
    }
  
    // Method 4
    public void closeConnection() throws SQLException
    {
        con.close();
    }
  
    // Method 5
    @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/>

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"
       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>

Archivo: Main.java

Java

// Java Program to Illustrate Application Class
  
// 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
    {
  
        // Using ApplicationContext tom implement Spring IoC
        ApplicationContext context
            = new ClassPathXmlApplicationContext(
                "beans.xml");
  
        // Getting the bean studentDAO
        StudentDAO studentDAO = context.getBean(
            "studentDAO", StudentDAO.class);
  
        // Calling the method
        // inside main() 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 *