Recientemente, cuando vi el método de plantilla de JDBCTemplete de Spring, me interesé mucho en plantillas y devoluciones de llamada, y consulté información e hice algún resumen.
Función de devolución de llamada:
La llamada devolución de llamada significa que el programa del cliente C llama a una determinada función A en el programa de servicio S, y luego S llama a una determinada función B en C en algún momento. Para C, esta B se llama función de devolución de llamada. Una función de devolución de llamada es solo una función que implementa el usuario de acuerdo con la convención de llamadas de la función de devolución de llamada. Una función de devolución de llamada es parte de un flujo de trabajo, y el flujo de trabajo determina el momento de la llamada de la función (devolución de llamada). En términos generales, C no llamará B por sí solo. El propósito de que C proporcione B es dejar que R lo llame, y C tiene que proporcionarlo. Dado que S no sabe quién B lleva el nombre de C, S estará de acuerdo en la especificación de la interfaz de B (prototipo de funciones), y luego C le dirá S por adelantado que usará la función B a través de una función R de S. Servicio web y Java RMI utilizan mecanismos de devolución de llamada para acceder a programas de servidores remotos. La función de devolución de llamada contiene las siguientes características:
1. Pertenece a una parte del flujo de trabajo;
2. Debe declararse (definido) de acuerdo con la convención de llamadas especificada por el flujo de trabajo;
3. El momento de su llamado está determinado por el flujo de trabajo. El implementador de la función de devolución de llamada no puede llamar directamente a la función de devolución de llamada para implementar la función del flujo de trabajo;
Mecanismo de devolución de llamada:
El mecanismo de devolución de llamada es un modelo de diseño común. Expone una función en el flujo de trabajo a usuarios externos de acuerdo con la interfaz acordada, proporciona datos a usuarios externos o requiere usuarios externos para proporcionar datos.
Mecanismo de devolución de llamada Java:
Siempre hay ciertas interfaces entre los módulos de software. En términos de métodos de llamadas, se pueden dividir en tres categorías: llamadas sincrónicas, devoluciones de llamada y llamadas asincrónicas.
Llamada sincrónica: una llamada de bloqueo, la persona que llama tiene que esperar a que la otra parte complete la ejecución antes de regresar. Es una llamada de ida;
Devolución de llamada: un modo de llamadas bidireccional, es decir, la parte llamada también llamará a la interfaz de la otra parte cuando se llama a la interfaz;
Llamada asíncrona: un mecanismo similar a un mensaje o evento, pero su dirección de llamada es todo lo contrario. Cuando un servicio de interfaz recibe un determinado mensaje o un evento, notificará activamente al cliente (es decir, llame a la interfaz del cliente).
La relación entre las devoluciones de llamada y las llamadas asincrónicas está muy relacionada: las devoluciones de llamada se utilizan para implementar el registro de mensajes asincrónicos, y la notificación de mensajes se logra a través de llamadas asincrónicas.
Instancia de devolución de llamada
1. Interfaz de devolución de llamada
Public Interface Callback {String Callback (); } 2. Llamadora
clase pública otra {devolución de llamada privada; // Llamando al método que implementa la clase public void setCallback (devolución de llamada de devolución de llamada) {this.callback = llamado; } // Cuando el negocio lo necesita, llame al método específico que implementa la clase public void docallback () {system.out.println (callback.callback ()); }} 3. Prueba la función de devolución de llamada
public class testCallCack {public static void main (string [] args) {// Cree la clase de implementación de la persona que llama otro otro = nuevo otro (); // Registre la interfaz de retroceso en la clase de implementación otro.setCallback (new Callback () {@Override public String Callback () {return "usted es un cerdo";}}); // ejecutar la función de devolución de llamada otro.docallback (); }}El uso de métodos de devolución de llamada generalmente ocurre durante el uso de "interfaz Java" y "clase abstracta". El patrón de diseño del método de plantilla utiliza el mecanismo de devolución de llamada del método. Este patrón primero define el esqueleto de algoritmo de pasos específicos y retrasa algunos pasos al patrón de diseño implementado en la subclase. El patrón de diseño del método de plantilla permite que las subclases redefinen ciertos pasos específicos de un algoritmo sin cambiar la estructura de un algoritmo.
Aplicabilidad del patrón de diseño de plantillas:
1. Implemente la parte inmutable de un algoritmo a la vez y deje el algoritmo variable a subclases para implementarlo.
2. Los comportamientos públicos en cada subclase deben extraerse y concentrarse en una clase de padres públicos para evitar la duplicación de código.
3. Se pueden controlar las extensiones de subclase.
Ejemplo de plantilla:
Clase de método de plantilla de abstracto:
Public Abstract Class AbstractSup {// Métodos que requieren implementación de subclase Public Abstract void print (); // Método de plantilla public void doprint () {System.out.println ("Ejecutar el método de plantilla"); para (int i = 0; i <3; i ++) {print (); }}} Clase de método de plantilla de implementación de subclase:
Public Class Subclass extiende AbstractSup {@Override public void print () {System.out.println ("Método de implementación de subclases"); }} Clase de prueba del método de plantilla:
public class TempLetetest {public static void main (string [] args) {subclass subclass = new subclass (); subclass.print (); subclass.doprint (); }} La siguiente es una introducción detallada al uso del método de plantilla de resorte. Tomando JDBCTemplete como ejemplo, explicaremos en detalle el uso del modo de plantilla y el mecanismo de devolución de llamada.
Primero, echemos un vistazo al clásico ejemplo de programación JDBC:
Lista pública <seremir> QUERY () {List <Serem> UserList = New ArrayList <Serer> (); Cadena sql = "seleccionar * de usuario"; Conexión con = nulo; Preparado PST = NULL; ResultSet rs = null; intente {con = hsqldbutil.getConnection (); PST = Con.PrepareStatement (SQL); rs = pst.executeQuery (); Usuario user = nulo; while (rs.next ()) {user = new User (); user.setId (rs.getInt ("id")); user.setUsername (rs.getString ("user_name")); user.setBirth (rs.getDate ("nacimiento")); user.setCreateDate (rs.getDate ("create_date")); UserList.Add (usuario); }} Catch (SQLException e) {E.PrintStackTrace (); } finalmente {if (rs! = null) {try {rs.close (); } Catch (Sqlexception e) {E.PrintStackTrace (); }} try {pst.close (); } Catch (Sqlexception e) {E.PrintStackTrace (); } try {if (! Con.isClosed ()) {try {con.close (); } Catch (Sqlexception e) {E.PrintStackTrace (); }}} Catch (SQLException e) {E.PrintStackTrace (); }} return UserList; }
Una consulta simple requiere muchas cosas y también lidiar con excepciones. Vamos a resolverlo si no queremos:
1. Obtener conexión
2. Obtener la declaración
3. Obtenga el conjunto de resultados
4. iterar a través del conjunto de resultados y encapsularlo en una colección
5. Cierre conexión, declaración y resultado a su vez, y considere varias excepciones, etc.
Si varias consultas generan un código más duplicado, puede usar el mecanismo de plantilla. A través de la observación, encontramos que la mayoría de los pasos anteriores son repetitivos y reutilizables. Solo al atravesar el conjunto de resultados y encapsularlo en una colección es personalizable, porque cada tabla mapea diferentes frijoles Java. No hay forma de reutilizar esta parte del código, solo se puede personalizar.
Código de clase abstracta:
Public Abstract Class JDBCTemplate {// Método de plantilla Public Object Final Execute (String SQL) lanza SQLException {Connection Con = HSqldButil.getConnection (); Instrucción stmt = null; intente {stmt = con.createStatement (); ResultSet rs = stmt.executeQuery (sql); Resultado del objeto = doInStatement (RS); // Método Abstract (método personalizado, implementación de subclase requerida) Resultado de retorno; } catch (Sqlexception ex) {Ex.PrintStackTrace (); tirar ex; } finalmente {try {stmt.close (); } Catch (Sqlexception e) {E.PrintStackTrace (); } try {if (! Con.isClosed ()) {try {con.close (); } Catch (Sqlexception e) {E.PrintStackTrace (); }}} Catch (SQLException e) {E.PrintStackTrace (); }}} // método abstracto (método personalizado) objeto abstracto protegido doinstatement (resultset rs); }En esta clase abstracta, el proceso principal de la API JDBC SUN se encapsula, y el paso de atravesar el conjunto de resultados se coloca en el método abstracto doinstatement (), que implementa la subclase.
Código de implementación de subclase:
clase pública JDBCTemplateUserImpl extiende JDBCTEMPLATE {@Override Object DoInStatement (ResultSet RS) {list <serem> userList = new ArrayList <Serem> (); intente {user user = null; while (rs.next ()) {user = new User (); user.setId (rs.getInt ("id")); user.setUsername (rs.getString ("user_name")); user.setBirth (rs.getDate ("nacimiento")); user.setCreateDate (rs.getDate ("create_date")); UserList.Add (usuario); } return UserList; } Catch (Sqlexception e) {E.PrintStackTrace (); regresar nulo; }}}En el método doInStatement (), atravesamos el conjunto de resultados y finalmente lo devolvemos.
Código de prueba:
Cadena sql = "seleccionar * de usuario"; Jdbctemplate jt = new jdbctemplateUserImpl (); List <Serem> UserList = (List <Serem>) JT.Execute (SQL);
El mecanismo de la plantilla se ha utilizado hasta ahora, pero si necesita heredar la clase principal cada vez que llame a JDBCTemplate, es bastante inconveniente, por lo que el mecanismo de devolución de llamada puede desempeñar un papel.
La llamada devolución de llamada significa pasar una interfaz en los parámetros del método. Cuando la clase principal llama a este método, debe llamar a la clase de implementación de la interfaz aprobada en el método.
Implementación del modo de plantilla de devolución de llamada más
Interfaz de devolución de llamada:
Declaración de interfaz pública Callback {Object DoInStatement (Declaración STMT) lanza SQLException; } Método de plantilla:
public class JDBCTemplate {// Método de plantilla Public Final Object Execute (DeclarationCallback Action) lanza SQLException {Connection Con = HSqldButil.getConnection (); Instrucción stmt = null; intente {stmt = con.createStatement (); Resultado del objeto = Action.DoInStatement (RS); // Resultado de retorno del método de devolución de llamada; } catch (Sqlexception ex) {Ex.PrintStackTrace (); tirar ex; } finalmente {try {stmt.close (); } Catch (Sqlexception e) {E.PrintStackTrace (); } try {if (! Con.isClosed ()) {try {con.close (); } Catch (Sqlexception e) {E.PrintStackTrace (); }}} Catch (SQLException e) {E.PrintStackTrace (); }}}} consulta de objeto público (DeclaryCallback stmt) lanza SQLException {return Ejecute (stmt); }}} Clase probada:
Public Object Query (Final String SQL) lanza SQLException {Class QueryStatementCallback implementa DeclarationCallback {Public Object doInStatement (Declaración stmt) lanza SQLException {resultSet rs = stmt.executeQuery (sql); List <Serem> UserList = New ArrayList <Seremower> (); Usuario user = nulo; while (rs.next ()) {user = new User (); user.setId (rs.getInt ("id")); user.setUsername (rs.getString ("user_name")); user.setBirth (rs.getDate ("nacimiento")); user.setCreateDate (rs.getDate ("create_date")); UserList.Add (usuario); } return UserList; }} Jdbctemplate jt = new jdbctemplate (); return jt.Query (New QueryStatementCallback ()); }
¿Por qué la primavera no utiliza los métodos de plantilla tradicionales, sino que también coopera con la devolución de llamada?
Imagínense, si hay 10 métodos abstractos en la clase principal y todas las subclases que los heredan necesitan implementar todos estos 10 métodos abstractos, la subclase aparecerá muy hinchada. A veces, ¿qué debo hacer si una subclase solo necesita personalizar un determinado método en la clase principal? En este momento, se usa devolución de llamada.
Además, el método anterior implementa básicamente el método de plantilla + modo de devolución de llamada. Pero todavía está un poco lejos de JDBCTemplate de primavera. Aunque implementamos el modo de devolución de llamada + Método de plantilla anterior, parece un poco "feo" en comparación con JDBCTemplate de Spring. Spring presenta los conceptos de RowMapper y ResultSetExtractor. La interfaz RowMapper es responsable de procesar una cierta fila de datos. Por ejemplo, podemos operar en una cierta fila de registros en el método Maprow, o encapsularlo en entidad. ResultSetExtractor es un extractor de conjunto de datos, que es responsable de atravesar el conjunto de resultados y procesar los datos de acuerdo con las reglas en RowMapper. La diferencia entre RowMapper y ResultSetExtractor es que RowMapper procesa una cierta fila de datos y devuelve un objeto de entidad. El ProvEdSetExtractor procesa un conjunto de datos y devuelve una colección de objetos.
Por supuesto, lo anterior son solo los principios básicos de la implementación de Spring JDBCTemplate. Spring JDBCTemplate ha hecho más cosas, como encapsular todas las operaciones básicas en la interfaz JDBCoperations, y usar JDBCACCessor para administrar las excepciones de datos de datos y conversión.
Lo anterior se trata de este artículo, espero que sea útil para el aprendizaje de todos.