最近、SpringのJDBCtempleteのテンプレート方法を見たとき、私はテンプレートとコールバックに非常に興味を持ち、いくつかの情報を照会して要約をしました。
コールバック関数:
いわゆるコールバックは、クライアントプログラムCがサービスプログラムSで特定の関数Aを呼び出すことを意味し、SがいつかCで特定の関数Bを呼び出します。 Cの場合、このBはコールバック関数と呼ばれます。コールバック関数は、コールバック関数呼び出し条約に従ってユーザーによって実装される関数にすぎません。コールバック関数はワークフローの一部であり、ワークフローは関数の呼び出しのタイミング(コールバック)を決定します。一般的に、Cはそれ自体でBを呼び出しません。 Cを提供する目的は、sを呼び出すことであり、Cはそれを提供する必要があります。 SはCがCにちなんで命名されていることを知らないため、SはBのインターフェイス仕様(関数プロトタイプ)に同意し、CはSの関数Rを使用してB関数を使用することを事前にSに伝えます。このプロセスはコールバック関数の登録と呼ばれ、Rは登録関数と呼ばれます。 WebサービスとJava RMIは、コールバックメカニズムを使用してリモートサーバープログラムにアクセスします。コールバック関数には、次の特性が含まれています。
1。ワークフローの一部に属します。
2。ワークフローによって指定された呼び出し条約に従って宣言(定義)する必要があります。
3.その呼び出しのタイミングは、ワークフローによって決定されます。コールバック関数の実装者は、コールバック関数を直接呼び出してワークフローの関数を実装することはできません。
コールバックメカニズム:
コールバックメカニズムは一般的な設計モデルです。合意されたインターフェイスに従って、ワークフローの関数を外部ユーザーに公開したり、外部ユーザーにデータを提供したり、外部ユーザーにデータを提供する必要があります。
Javaコールバックメカニズム:
ソフトウェアモジュール間には常に特定のインターフェイスがあります。呼び出し方法に関しては、同期呼び出し、コールバック、非同期コールの3つのカテゴリに分けることができます。
同期コール:ブロッキングコールでは、発信者は返却する前に相手が実行を完了するのを待たなければなりません。一方向の呼び出しです。
コールバック:双方向の呼び出しモード、つまり、インターフェイスが呼び出されると、双方向呼び出しモードも相手のインターフェイスを呼び出します。
非同期コール:メッセージやイベントに似たメカニズムですが、その呼び出し方向は正反対です。インターフェイスサービスが特定のメッセージまたはイベントが発生すると、クライアントに積極的に通知されます(つまり、クライアントのインターフェイスに電話します)。
コールバックと非同期呼び出しの関係は非常に密接に関連しています。コールバックは非同期メッセージの登録を実装するために使用され、メッセージの通知は非同期コールを通じて達成されます。
コールバックインスタンス
1。コールバックインターフェイス
public interface callback {string callback(); } 2。発信者
パブリッククラスAnother {プライベートコールバックコールバック。 //クラスのpublic void setcallback(callback callback)を実装するメソッドを呼び出す{this.callback = callback; } //ビジネスが必要な場合は、クラスのpublic void docallback(){system.out.println(callback.callback())を実装する特定の方法を呼び出します。 }} 3.コールバック関数をテストします
public class testcallcack {public static void main(string [] args){//発信者の実装クラスを作成して別の別の= new Another(); //バックインターフェイスを実装クラスに登録します。別の.setCallback(new Callback(){@Override public String callback(){return "you are a pig";}}); // callback関数を実行しますaonther.docallback(); }}通常、コールバックメソッドの使用は、「Javaインターフェイス」と「抽象クラス」の使用中に発生します。テンプレートメソッド設計パターンは、メソッドコールバックメカニズムを使用します。このパターンは、最初に特定のステップのアルゴリズムスケルトンを定義し、サブクラスに実装されている設計パターンのいくつかのステップを遅らせます。テンプレートメソッド設計パターンにより、サブクラスはアルゴリズムの構造を変更せずにアルゴリズムの特定の特定のステップを再定義できます。
テンプレート設計パターンの適用性:
1.一度にアルゴリズムの不変の部分を実装し、可変アルゴリズムをサブクラスに残して実装します。
2。各サブクラスの公共行動は、コードの複製を避けるために、公開親クラスに抽出し、集中する必要があります。
3.サブクラス拡張機能を制御できます。
テンプレートの例:
抽象テンプレートメソッドクラス:
パブリックアブストラクトクラスAbstractSup {//サブクラス実装が必要な方法パブリックアブストラクトボイドプリント(); //テンプレートメソッドpublic void doprint(){system.out.println( "Template Method"); for(int i = 0; i <3; i ++){print(); }}}サブクラス実装テンプレートメソッドクラス:
パブリッククラスのサブクラスはabstractSupを拡張します{@Override public void print(){system.out.println( "実装メソッドのサブクラス"); }}テンプレートメソッドテストクラス:
public class templetetest {public static void main(string [] args){subclass subclass = new subclass(); subclass.print(); subclass.doprint(); }}以下は、スプリングテンプレートメソッドの使用に関する詳細な紹介です。 JDBCTEMPLETEを例にとると、テンプレートモードとコールバックメカニズムの使用について詳しく説明します。
まず、古典的なJDBCプログラミングの例を見てみましょう。
public list <user> query(){list <user> userlist = new ArrayList <user>();文字列sql = "select * from user";接続con = null; reprentStatement pst = null;結果rs = null; try {con = hsqldbutil.getConnection(); pst = con.preparestatement(sql); rs = pst.executequery();ユーザーユーザー= 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(); }最後に{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; }
簡単なクエリには、このような多くのことが必要であり、例外を扱っています。私たちがしたくないなら、それを整理しましょう:
1。接続を取得します
2。ステートメントを取得します
3.結果を取得します
4。結果セットを繰り返してコレクションにカプセル化します
5.接続、ステートメント、および結果を順番に閉じ、さまざまな例外などを検討します。
複数のクエリがより重複したコードを生成する場合、テンプレートメカニズムを使用できます。観察を通じて、上記の手順のほとんどが反復的で再利用可能であることがわかりました。各テーブルが異なるJava Beanをマッピングするため、結果セットを横断してコレクションにカプセル化することがカスタマイズ可能です。コードのこの部分を再利用する方法はありません。カスタマイズするだけです。
抽象クラスコード:
パブリックアブストラクトクラスjdbctemplate {//テンプレートメソッドpublic final objectute(string sql)throws sqlexception {connection con = hsqldbutil.getConnection();ステートメントstmt = null; try {stmt = con.createstatement();結果rs = stmt.executequery(sql); Object result = doinstatement(rs); //抽象メソッド(カスタマイズされた方法、サブクラス実装が必要)return result; } catch(sqlexception ex){ex.printstacktrace(); Exを投げる; }最後に{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(); }}} //要約方法(カスタムメソッド)保護された要約オブジェクトdoinstatement(resultet rs); }この抽象クラスでは、Sun JDBC APIの主なプロセスがカプセル化されており、結果セットのトラバースのステップは、サブクラスによって実装される抽象的なメソッドdoinStatement()に配置されます。
サブクラスの実装コード:
パブリッククラスjdbctemplateuserimpl extends jdbctemplate {@override保護されたオブジェクト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(); nullを返します。 }}}doinStatement()メソッドでは、結果を通過して最終的に返します。
テストコード:
文字列sql = "select * from user"; jdbctemplate jt = new jdbctemplateuserimpl();リスト<ユーザー> userlist =(list <user>)jt.execute(sql);
テンプレートメカニズムはこれまでに使用されてきましたが、JDBCtemplateに電話するたびに親クラスを継承する必要がある場合は、非常に不便なので、コールバックメカニズムが役割を果たすことができます。
いわゆるコールバックとは、メソッドパラメーターにインターフェイスを渡すことを意味します。親クラスがこのメソッドを呼び出す場合、メソッドで渡されたインターフェイスの実装クラスを呼び出す必要があります。
コールバックとテンプレートモードの実装
コールバックインターフェイス:
public Interface StatementCallback {object doinstatement(statement stmt)はsqlexceptionをスローします。 }テンプレートメソッド:
public class jdbctemplate {//テンプレートメソッドpublic final object execute(statementcallback action)throws sqlexception {connection con = hsqldbutil.getConnection();ステートメントstmt = null; try {stmt = con.createstatement(); Object result = action.doinStatement(rs); //コールバックメソッドreturn result; } catch(sqlexception ex){ex.printstacktrace(); Exを投げる; }最後に{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); }}}テスト済みクラス:
パブリックオブジェクトクエリ(最終文字列SQL)スローSQLEXCEPTION {class QueryStatementCallback StatementCallback {public Object doinStatement(statement stmt)throws sqlexception {resultet rs = stmt.executequery(sql); List <user> userlist = new ArrayList <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は従来のテンプレートメソッドを使用しないだけでなく、コールバックにも協力しないのですか?
親クラスに10の抽象的なメソッドがあり、これらの10の抽象的なメソッドをすべて実装する必要があるすべてのサブクラスがある場合、サブクラスは非常に肥大化しているように見えます。サブクラスが親クラスで特定のメソッドをカスタマイズする必要がある場合はどうすればよいですか?現時点では、コールバックが使用されています。
さらに、上記の方法では、基本的にテンプレートメソッド +コールバックモードを実装します。しかし、それはまだSpringのJDBCtemplateから少し遠いです。上記のテンプレートメソッド +コールバックモードを実装しましたが、SpringのJDBCtemplateと比較して「醜い」ようです。 Springでは、RowMapperとResultsEtextractorの概念を紹介します。 RowMapperインターフェイスは、特定のデータを処理する責任があります。たとえば、MapRowメソッドの特定のレコードの行で動作するか、エンティティにカプセル化することができます。 resultseTextractorはデータセット抽出器であり、結果を測定し、rowmapperのルールに従ってデータを処理する責任があります。 rowmapperとresultseTextractorの違いは、rowmapperが特定のデータの行を処理し、エンティティオブジェクトを返すことです。 ResultSeTextractorはデータセットを処理し、オブジェクトのコレクションを返します。
もちろん、上記はSpring JDBCtemplateの実装の基本原則にすぎません。 Spring JDBCtemplateは、すべての基本操作をJDBCoperationsインターフェイスにカプセル化すること、JDBCACCERSERを使用してDataSourceおよび変換の例外を管理するなど、より多くのことを行っています。
上記はこの記事に関するものです。すべての人の学習に役立つことを願っています。