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
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:
- 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 // 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