Maison >Java >javaDidacticiel >Explication détaillée des modèles Java et du mécanisme de rappel

Explication détaillée des modèles Java et du mécanisme de rappel

高洛峰
高洛峰original
2017-01-24 13:37:241245parcourir

Lorsque j'ai récemment examiné la méthode modèle du JDBCTemplete de Spring, je suis devenu très intéressé par les modèles et les rappels, j'ai interrogé certaines informations et fait des résumés.

Fonction de rappel :

Ce que l'on appelle le rappel signifie que le programme client C appelle une fonction A dans le programme de service S, puis S appelle à son tour une fonction B dans C à un certain moment. time , pour C, ce B est appelé la fonction de rappel. La fonction de rappel n'est qu'un fragment fonctionnel, une fonction implémentée par l'utilisateur selon la convention d'appel de la fonction de rappel. La fonction de rappel fait partie d'un flux de travail et le flux de travail détermine le moment de l'appel de fonction (rappel). D'une manière générale, C n'appellera pas B par lui-même. Le but de C fournissant B est de laisser S l'appeler, et C doit le fournir. Puisque S ne connaît pas le nom de B fourni par C, S se mettra d'accord sur la spécification d'interface (prototype de fonction) de B, puis C dira à S à l'avance qu'il utilisera la fonction B via une fonction R de S. Le processus est appelé un rappel. Enregistrement d'une fonction, R est appelé une fonction enregistrée. Le service Web et le RMI de Java utilisent tous deux des mécanismes de rappel pour accéder aux programmes du serveur distant. La fonction de rappel comprend les caractéristiques suivantes :

1. Elle fait partie du workflow

2. Elle doit être déclarée (définie) selon la convention d'appel spécifiée par le workflow ; 🎜>

3. Le moment de son appel est déterminé par le workflow. L'implémenteur de la fonction de rappel ne peut pas appeler directement la fonction de rappel pour implémenter la fonction du workflow

Mécanisme de rappel :

Le mécanisme de rappel est un modèle de conception commun qui expose une certaine fonction du flux de travail aux utilisateurs externes selon l'interface convenue, fournit des données aux utilisateurs externes ou oblige les utilisateurs externes à fournir des données.

Mécanisme de rappel Java :

Il existe toujours certaines interfaces entre les modules logiciels. En termes de méthodes d'appel, elles peuvent être divisées en trois catégories : les appels synchrones, les rappels et les appels asynchrones.

Appel synchrone : un appel bloquant. L'appelant doit attendre que l'autre partie ait fini de s'exécuter avant de revenir.

Rappel : un mode d'appel bidirectionnel. , c'est-à-dire que l'appelé appellera également l'interface de l'autre partie lorsque l'interface est appelée ;

Appel asynchrone : un mécanisme similaire aux messages ou aux événements, mais son sens d'appel est exactement le service du. l'interface reçoit un certain Lorsqu'un message ou un événement se produit, le client sera averti de manière proactive (c'est-à-dire que l'interface du client sera appelée).

La relation entre les rappels et les appels asynchrones est très étroite : les rappels sont utilisés pour enregistrer les messages asynchrones, et les appels asynchrones sont utilisés pour notifier les messages.

Instance de rappel

1. Interface de rappel

public interface Callback {
 
   String callBack();
 }

2. >3. Test de la fonction de rappel

public class Another {
  private Callback callback;
  //调用实现类的方法
  public void setCallback(Callback callback) {
    this.callback = callback;
  }
    //业务需要的时候,通过委派,来调用实现类的具体方法
  public void doCallback(){
    System.out.println(callback.callBack());
  }
}

L'utilisation de méthodes de rappel se produit généralement lors de l'utilisation de "l'interface Java" et de la "classe abstraite". Le modèle de conception de méthode modèle utilise le mécanisme de rappel de méthode. Ce modèle définit d'abord le squelette de l'algorithme des étapes spécifiques et reporte certaines étapes aux sous-classes pour la mise en œuvre. Le modèle de conception de méthode modèle permet aux sous-classes de redéfinir des étapes spécifiques d’un algorithme sans modifier la structure de l’algorithme.

L'applicabilité du modèle de conception de modèle :
public class TestCallcack {
  public static void main(String[] args) {
    //创建调用者的实现类
    Another another = new Another();
    //将回掉接口注册到实现类中
    another.setCallback(new Callback() { 
      @Override
      public String callBack() {
        return "you are a pig";
      }
    });
    //执行回调函数
    another.doCallback();
  }
}

 1. Implémentez la partie constante d'un algorithme en une seule fois et laissez l'algorithme variable aux sous-classes pour l'implémentation.

2. Les comportements communs dans chaque sous-classe doivent être extraits et concentrés dans une classe parent commune pour éviter la duplication de code.

3. Vous pouvez contrôler l'expansion des sous-classes.

Instance de modèle :

Classe de méthode de modèle abstrait :

Classe de méthode de modèle d'implémentation de sous-classe :

public abstract class AbstractSup {
    //需要子类实现的方法
  public abstract void print();
    //模板方法
  public void doPrint(){
    System.out.println("执行模板方法");
    for (int i = 0; i < 3; i++) {
      print();
    }
  }
}

Classe de test de méthode de modèle :

public class SubClass extends AbstractSup{
  @Override
  public void print() {
    System.out.println("子类的实现方法");
  }
 
}

Ce qui suit est une introduction approfondie à l'utilisation des méthodes de modèle Spring en prenant comme exemple JdbcTemplete, le modèle. le mode et le mécanisme de rappel sont expliqués en détail.

Tout d'abord, jetons un coup d'œil à un exemple de programmation JDBC classique :

public class TempleteTest {
  public static void main(String[] args) {
    SubClass subClass = new SubClass();
    subClass.print();
    subClass.doPrint();
  }
}

Une requête simple doit faire tellement de choses, et elle doit également gérer des exceptions : 1. Obtenez la connexion

2. Obtenez la déclaration

3. Obtenez l'ensemble de résultats
4. Parcourez l'ensemble de résultats et encapsulez-le dans une collection

5. séquence, et considérez également diverses exceptions, etc.
public List<User> query() {
  
  List<User> userList = new ArrayList<User>();
  String sql = "select * from User";
  
  Connection con = null;
  PreparedStatement pst = null;
  ResultSet rs = null;
  try {
    con = HsqldbUtil.getConnection();
    pst = con.prepareStatement(sql);
    rs = pst.executeQuery();
  
    User user = null;
    while (rs.next()) {
  
      user = new User();
      user.setId(rs.getInt("id"));
      user.setUserName(rs.getString("user_name"));
      user.setBirth(rs.getDate("birth"));
      user.setCreateDate(rs.getDate("create_date"));
      userList.add(user);
    }
  
  
  } catch (SQLException e) {
    e.printStackTrace();
  }finally{
    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;
}

Si plusieurs requêtes génèrent davantage de codes en double, vous pouvez utiliser le mécanisme de modèle à ce stade. Grâce à l'observation, nous avons constaté que la plupart des étapes ci-dessus sont répétées et réutilisables uniquement lors du parcours du ResultSet Cette étape d'encapsulation. le placer dans une collection est personnalisable car chaque table mappe un bean java différent. Cette partie du code ne peut pas être réutilisée et peut uniquement être personnalisée.

Code de classe abstraite :


Cette classe abstraite encapsule le processus principal de l'API SUN JDBC et parcourt le ResultSet Les étapes sont placés dans la méthode abstraite doInStatement(), qui est implémentée par la sous-classe.

public abstract class JdbcTemplate {
  
  //模板方法
  public final Object execute(String sql) throws SQLException{
    
    Connection con = HsqldbUtil.getConnection();
    Statement stmt = null;
    try {
   
      stmt = con.createStatement();
      ResultSet rs = stmt.executeQuery(sql);
      Object result = doInStatement(rs);//抽象方法(定制方法,需要子类实现) 
      return result;
    }
    catch (SQLException ex) {
       ex.printStackTrace();
       throw ex;
    }
    finally {
   
      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();
      }
        
    }
  }
    
  //抽象方法(定制方法)
  protected abstract Object doInStatement(ResultSet rs);
}
Code d'implémentation de la sous-classe :

Dans la méthode doInStatement(), nous parcourons le ResultSet et finalement le renvoyons.

public class JdbcTemplateUserImpl extends JdbcTemplate {
  
  @Override
  protected Object doInStatement(ResultSet rs) {
    List<User> userList = new ArrayList<User>();
      
    try {
      User user = null;
      while (rs.next()) {
  
        user = new User();
        user.setId(rs.getInt("id"));
        user.setUserName(rs.getString("user_name"));
        user.setBirth(rs.getDate("birth"));
        user.setCreateDate(rs.getDate("create_date"));
        userList.add(user);
      }
      return userList;
    } catch (SQLException e) {
      e.printStackTrace();
      return null;
    }
  }
  
}
Code de test :

L'utilisation du mécanisme de modèle se termine ici, mais si vous appelez jdbcTemplate à chaque fois, vous devez hériter de la classe parent ci-dessus, donc C'est assez gênant, donc le mécanisme de rappel peut entrer en jeu.

所谓回调,就是方法参数中传递一个接口,父类在调用此方法时,必须调用方法中传递的接口的实现类。

回调加模板模式实现

回调接口:

public interface StatementCallback {
  Object doInStatement(Statement stmt) throws SQLException;
 }

 模板方法:

public class JdbcTemplate {
  
  //模板方法
  public final Object execute(StatementCallback action) throws SQLException{
      
    Connection con = HsqldbUtil.getConnection();
    Statement stmt = null;
    try {
   
      stmt = con.createStatement();
      Object result = action.doInStatement(rs);//回调方法
      return result;
    }
    catch (SQLException ex) {
       ex.printStackTrace();
       throw ex;
    }
    finally {
   
      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();
      }
        
    }
  }    
  }
  public Object query(StatementCallback stmt) throws SQLException{
    return execute(stmt);
  }
}

   

测试的类:

public Object query(final String sql) throws SQLException {
    class QueryStatementCallback implements StatementCallback {
  
      public Object doInStatement(Statement stmt) throws SQLException {
        ResultSet rs = stmt.executeQuery(sql);
        List<User> userList = new ArrayList<User>();
  
        User user = null;
        while (rs.next()) {
  
          user = new User();
          user.setId(rs.getInt("id"));
          user.setUserName(rs.getString("user_name"));
          user.setBirth(rs.getDate("birth"));
          user.setCreateDate(rs.getDate("create_date"));
          userList.add(user);
        }
        return userList;
  
      }
  
    }
  
    JdbcTemplate jt = new JdbcTemplate();
    return jt.query(new QueryStatementCallback());
  }

   


为什么spring不用传统的模板方法,而加之以Callback进行配合呢? 
试想,如果父类中有10个抽象方法,而继承它的所有子类则要将这10个抽象方法全部实现,子类显得非常臃肿。而有时候某个子类只需要定制父类中的某一个方法该怎么办呢?这个时候就要用到Callback回调了。

另外,上面这种方式基本上实现了模板方法+回调模式。但离spring的jdbcTemplate还有些距离。 我们上面虽然实现了模板方法+回调模式,但相对于Spring的JdbcTemplate则显得有些“丑陋”。Spring引入了RowMapper和ResultSetExtractor的概念。 RowMapper接口负责处理某一行的数据,例如,我们可以在mapRow方法里对某一行记录进行操作,或封装成entity。 ResultSetExtractor是数据集抽取器,负责遍历ResultSet并根据RowMapper里的规则对数据进行处理。 RowMapper和ResultSetExtractor区别是,RowMapper是处理某一行数据,返回一个实体对象。而ResultSetExtractor是处理一个数据集合,返回一个对象集合。

  当然,上面所述仅仅是Spring JdbcTemplte实现的基本原理,Spring JdbcTemplate内部还做了更多的事情,比如,把所有的基本操作都封装到JdbcOperations接口内,以及采用JdbcAccessor来管理DataSource和转换异常等。

以上就是本文的全部内容,希望对大家的学习有所帮助。

更多详解java模板和回调机制相关文章请关注PHP中文网!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn