Recentemente, quando vi o método de modelo do JDBCTemplete da Spring, fiquei muito interessado em modelos e retornos de chamada e consultei algumas informações e fiz algum resumo.
Função de retorno de chamada:
O chamado retorno de chamada significa que o Programa do Cliente C chama uma determinada função A no programa de serviço s e, em seguida, S chama uma certa função B em C em algum momento. Para C, este B é chamado de função de retorno de chamada. Uma função de retorno de chamada é apenas uma função que é implementada pelo usuário de acordo com a convenção de chamada de função de retorno de chamada. Uma função de retorno de chamada faz parte de um fluxo de trabalho e o fluxo de trabalho determina o tempo da chamada da função (retorno de chamada). De um modo geral, C não liga para B por si só. O objetivo de C fornecendo B é deixar S chamá -lo, e C precisa fornecê -lo. Como S não sabe quem B recebeu após C, S concordará com a especificação da interface de B (protótipo da função) e, em seguida, C dirá a S com antecedência que ele usará a função b através de uma função r de S. Serviço da Web e Java RMI usam mecanismos de retorno de chamada para acessar programas de servidor remoto. A função de retorno de chamada contém as seguintes características:
1. Pertence a uma parte do fluxo de trabalho;
2. Deve ser declarado (definido) de acordo com a convenção de chamada especificada pelo fluxo de trabalho;
3. O tempo de sua chamada é determinado pelo fluxo de trabalho. O implementador da função de retorno de chamada não pode chamar diretamente a função de retorno de chamada para implementar a função do fluxo de trabalho;
Mecanismo de retorno de chamada:
O mecanismo de retorno de chamada é um modelo de design comum. Ele expõe uma função no fluxo de trabalho para usuários externos de acordo com a interface acordada, fornece dados a usuários externos ou exige que usuários externos forneçam dados.
Mecanismo de retorno de chamada Java:
Sempre existem certas interfaces entre os módulos de software. Em termos de métodos de chamada, eles podem ser divididos em três categorias: chamadas síncronas, retornos de chamada e chamadas assíncronas.
Chamada síncrona: uma chamada de bloqueio, o chamador deve esperar a outra parte concluir a execução antes de retornar. É uma chamada única;
Retorno de chamada: um modo de chamada de mão dupla, ou seja, a parte chamada também chamará a interface da outra parte quando a interface for chamada;
Chamada assíncrona: um mecanismo semelhante a uma mensagem ou evento, mas sua direção de chamada é exatamente o oposto. Quando um serviço de interface recebe uma determinada mensagem ou um evento, ele notificará ativamente o cliente (ou seja, ligue para a interface do cliente).
A relação entre retornos de chamada e chamadas assíncronas está intimamente relacionada: os retornos de chamada são usados para implementar o registro de mensagens assíncronas, e a notificação de mensagens é obtida através de chamadas assíncronas.
Instância de retorno de chamada
1. Interface de retorno de chamada
interface pública Retorno de chamada {string callback (); } 2. Caller
classe pública outro {retorno de chamada de particular; // chamando o método que implementa a classe pública void setCallback (retorno de chamada) {this.callback = retorno de chamada; } // Quando os negócios precisam, chame o método específico que implementa a classe public void docallback () {System.out.println (callback.callback ()); }} 3. Função de retorno de chamada de teste
classe pública TestCallCack {public static void main (string [] args) {// Crie a classe de implementação do chamador outro outro = new Other (); // Registre a interface traseira na classe de implementação outro.setCallback (new Callback () {@Override public String callback () {return "You Are A Pig";}}); // execute a função de retorno de chamada outro.docallback (); }}O uso de métodos de retorno de chamada geralmente ocorre durante o uso da "interface java" e "classe abstrata". O padrão de design do método do modelo usa o mecanismo de retorno de chamada do método. Esse padrão define primeiro o esqueleto do algoritmo de etapas específicas e atrasa algumas etapas para o padrão de design implementado na subclasse. O padrão de design do método do modelo permite que as subclasses redefinam certas etapas específicas de um algoritmo sem alterar a estrutura de um algoritmo.
Aplicabilidade do padrão de design de modelo:
1. Implemente a parte imutável de um algoritmo ao mesmo tempo e deixe o algoritmo variável para subclasses para implementá -lo.
2. Comportamentos públicos em cada subclasse devem ser extraídos e concentrados em uma classe de pai pública para evitar a duplicação de código.
3. As extensões de subclasse podem ser controladas.
Exemplo de modelo:
Classe de método de modelo abstrato:
classe abstrata public abstractsup {// métodos que requerem implementação de subclasse public abstract void print (); // MOTEMEL Método public void DOPRINT () {System.out.println ("Método do modelo Execute"); for (int i = 0; i <3; i ++) {print (); }}} Classe de Modelo de Implementação de Subclasse:
classe pública Subclasse estende resumos {@Override public void print () {System.out.println ("Método de implementação das subclasses"); }} Classe de teste de método de modelo:
classe pública TempleteteTest {public static void main (string [] args) {subclass subclass = new subclass (); subclass.print (); subclass.doprint (); }} A seguir, é apresentada uma introdução detalhada ao uso do método do modelo de mola. Tomando o JDBCTemplete como exemplo, explicaremos em detalhes o uso do modo de modelo e mecanismo de retorno de chamada.
Primeiro, vamos dar uma olhada no clássico exemplo de programação JDBC:
list public <suser> query () {list <suser> userList = new ArrayList <suser> (); String sql = "selecione * do usuário"; Conexão con = null; Preparado Pstatement Pst = NULL; ResultSet rs = null; tente {con = hsqldbutil.getConnection (); Pst = Con.Preparestatement (SQL); rs = pst.executeQuery (); Usuário do usuário = nulo; while (rs.Next ()) {user = new User (); user.setId (rs.getInt ("id")); user.setUserName (rs.getString ("user_name")); user.setBirth (rs.getdate ("nascimento")); user.setCreatedate (rs.getdate ("create_date")); userlist.add (usuário); }} catch (sqLexception e) {e.printStackTrace (); } finalmente {if (rs! = null) {tente {rs.close (); } catch (sqLexception e) {e.printStackTrace (); }} tente {pst.close (); } catch (sqLexception e) {e.printStackTrace (); } tente {if (! con.iscosed ()) {try {con.close (); } catch (sqLexception e) {e.printStackTrace (); }}} catch (sqLexception e) {E.printStackTrace (); }} retornar UserList; }
Uma consulta simples requer muitas coisas e também lidando com exceções. Vamos resolver se não quisermos:
1. Obtenha conexão
2. Obtenha declaração
3. Obtenha o ResultSet
4. Itera através do conjunto de resultados e o encapsulam em uma coleção
5. Conexão, declaração e resultado de resultados, por sua vez, e considere várias exceções, etc.
Se várias consultas gerarem mais código duplicado, você poderá usar o mecanismo de modelo. Através da observação, descobrimos que a maioria das etapas acima é repetitiva e reutilizável. Somente ao atravessar o conjunto de resultados e encapsulá -lo em uma coleção é personalizável, porque cada tabela mapeia os diferentes feijões Java. Não há como reutilizar essa parte do código, ela só pode ser personalizada.
Código de classe abstrato:
classe public abstrata JDBCTemplate {// METOLE MÉTODO Public Final Object Execute (String SQL) lança SQLEXCECCIONE {Connection con = hsqldbutil.getConnection (); Instrução stmt = null; tente {stmt = con.createstatement (); ResultSet rs = stmt.executeQuery (SQL); Resultado do objeto = doinstatement (rs); // Método abstrato (método personalizado, implementação da subclasse necessária) Resultado de retorno; } catch (sqlexception ex) {ex.printStackTrace (); jogar ex; } finalmente {tente {stmt.close (); } catch (sqLexception e) {e.printStackTrace (); } tente {if (! con.iscosed ()) {try {con.close (); } catch (sqLexception e) {e.printStackTrace (); }}} catch (sqLexception e) {E.printStackTrace (); }}} // Método abstrato (método personalizado) Objeto abstrato protegido doinstatement (ResultSet RS); }Nesta classe abstrata, o principal processo da API Sun JDBC é encapsulado e a etapa de atravessar o conjunto de resultados é colocada no método abstrato doinstatement (), que é implementado pela subclasse.
Código de implementação da subclasse:
classe pública JDBCTemplateUserImpl estende JDBCTemplate {@Override Objeto protegido doinstatement (ResultSet rs) {list <suser> userList = new ArrayList <suser> (); tente {usuário do usuário = null; while (rs.Next ()) {user = new User (); user.setId (rs.getInt ("id")); user.setUserName (rs.getString ("user_name")); user.setBirth (rs.getdate ("nascimento")); user.setCreatedate (rs.getdate ("create_date")); userlist.add (usuário); } retornar UserList; } catch (sqLexception e) {e.printStackTrace (); retornar nulo; }}}No método doinstatement (), atravessamos o ResultSet e finalmente o devolvimos.
Código de teste:
String sql = "selecione * do usuário"; JdbcTemplate jt = novo jdbcTemplateUserImpl (); LIST <usery> userList = (list <suser>) jt.execute (SQL);
O mecanismo de modelo tem sido usado até agora, mas se você precisar herdar a classe pai toda vez que ligar para o JDBCTemplate, é bastante inconveniente, para que o mecanismo de retorno de chamada possa desempenhar um papel.
O chamado retorno de chamada significa passar uma interface nos parâmetros do método. Quando a classe pai chama esse método, ele deve chamar a classe de implementação da interface passada no método.
Implementação de modo de chamada mais de modelo
Interface de retorno de chamada:
Public Interface DeclarationCallback {Object DoinsTatement (Declaração STMT) lança SQLEXCECCETION; } Método de modelo:
public class JDBCTemplate {// METOLE MÉTODO Public Final Object Execute (Ação de DeclaraçãoCallback) lança SQLEXCECCIONE {Connection con = hsqldbutil.getConnection (); Instrução stmt = null; tente {stmt = con.createstatement (); Resultado do objeto = action.DoiStatement (rs); // Método de retorno de retorno de retorno Resultado; } catch (sqlexception ex) {ex.printStackTrace (); jogar ex; } finalmente {tente {stmt.close (); } catch (sqLexception e) {e.printStackTrace (); } tente {if (! con.iscosed ()) {try {con.close (); } catch (sqLexception e) {e.printStackTrace (); }}} catch (sqLexception e) {E.printStackTrace (); }}}} consulta pública de objeto (instruçãoCallback STMT) lança SQLEXCECTION {return Execute (STMT); }}} Classe testada:
Public Object Query (Final String SQL) lança SQLEXCECCETION {classe querystatementCallback implementa a instruçãocallback {public object doinstatement (declaração stmt) lança sqLexception {ResultSet rs = stmt.executeQuery (sql); List <usery> userList = new ArrayList <suser> (); Usuário do usuário = nulo; while (rs.Next ()) {user = new User (); user.setId (rs.getInt ("id")); user.setUserName (rs.getString ("user_name")); user.setBirth (rs.getdate ("nascimento")); user.setCreatedate (rs.getdate ("create_date")); userlist.add (usuário); } retornar UserList; }} Jdbctemplate jt = new jdbcTemplate (); retornar jt.Query (new QueryStatementCallback ()); }
Por que a primavera não usa métodos de modelo tradicionais, mas também coopera com o retorno de chamada?
Imagine, se houver 10 métodos abstratos na classe pai e todas as subclasses que herdam que precisam implementar todos esses 10 métodos abstratos, a subclasse parecerá muito inchada. Às vezes, o que devo fazer se uma subclasse precisar apenas personalizar um determinado método na classe pai? Neste momento, o retorno de chamada é usado.
Além disso, o método acima implementa basicamente o método do modelo + o modo de retorno de chamada. Mas ainda está um pouco longe do JDBCTemplate da primavera. Embora tenhamos implementado o método do modelo + o modo de retorno de chamada acima, parece um pouco "feio" em comparação com o JDBCTemplate da Spring. A primavera apresenta os conceitos de Rowmapper e ResultsEtextractor. A interface Rowmapper é responsável pelo processamento de uma certa linha de dados. Por exemplo, podemos operar em uma certa linha de registros no método Maprow ou encapsulá -lo na entidade. O ResultadoETextractor é um extrator de conjunto de dados, responsável por atravessar o ResultSet e processar os dados de acordo com as regras do Rowmapper. A diferença entre Rowmapper e ResultEtextractor é que o Rowmapper processa uma certa linha de dados e retorna um objeto de entidade. O ResultadoTeTextractor processa um conjunto de dados e retorna uma coleção de objetos.
Obviamente, o exposto acima são apenas os princípios básicos da implementação do Spring JDBCTemplate. O Spring JDBCTemplate fez mais coisas, como encapsular todas as operações básicas na interface JDBCoperations e usar o JDBCAccessor para gerenciar exceções de origem de dados e conversão.
O exposto acima é tudo sobre este artigo, espero que seja útil para o aprendizado de todos.