詳解java模板和回調機制。本站提示廣大學習愛好者:(詳解java模板和回調機制)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解java模板和回調機制正文
比來看spring的JDBCTemplete的模板方法挪用時,對模板和回調發生了濃重興致,查詢了一些材料,做一些總結。
回調函數:
所謂回調,就是客戶法式C挪用辦事法式S中的某個函數A,然後S又在某個時刻反過去挪用C中的某個函數B,關於C來講,這個B便叫做回調函數。回調函數只是一個功效片斷,由用戶依照回調函數挪用商定來完成的一個函數。回調函數是一個任務流的一部門,由任務流來決議函數的挪用(回調)機會。普通說來,C不會本身挪用B,C供給B的目標就是讓S來挪用它,並且是C不能不供給。因為S其實不曉得C供給的B姓甚名誰,所以S會商定B的接口標准(函數原型),然後由C提早經由過程S的一個函數R告知S本身將要應用B函數,這個進程稱為回調函數的注冊,R稱為注冊函數。Web Service和Java 的RMI都用到回調機制,可以拜訪長途辦事器法式。回調函數包括上面幾個特征:
1、屬於任務流的一個部門;
2、必需依照任務流指定的挪用商定來聲名(界說);
3、他的挪用機會由任務流決議,回調函數的完成者不克不及直接挪用回調函數來完成任務流的功效;
回調機制:
回調機制是一種罕見的設計模子,他把任務流內的某個功效,依照商定的接口裸露給內部應用者,為內部應用者供給數據,或請求內部應用者供給數據。
java回調機制:
軟件模塊之間老是存在著必定的接口,從挪用方法上,可以把他們分為三類:同步驟用、回折衷異步驟用。
同步驟用:一種壅塞式挪用,挪用方要期待對方履行終了才前往,它是一種單向挪用;
回 調:一種雙向挪用形式,也就是說,被挪用方在接口被挪用時也會挪用對方的接口;
異步驟用:一品種似新聞或事宜的機制,不外它的挪用偏向恰好相反,接口的辦事在收到某種訊息或產生某種事宜時,會自動告訴客戶方(即挪用客戶方的接口)。
回折衷異步驟用的關系異常慎密:應用回調來完成異步新聞的注冊,經由過程異步驟用來完成新聞的告訴。
回調實例
1、回調接口
public interface Callback { String callBack(); }
2、挪用者
public class Another { private Callback callback; //挪用完成類的辦法 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) { //創立挪用者的完成類 Another another = new Another(); //將回失落接口注冊到完成類中 another.setCallback(new Callback() { @Override public String callBack() { return "you are a pig"; } }); //履行回調函數 another.doCallback(); } }
回調辦法的應用平日產生在“java接口”和“籠統類”的應用進程中。模板辦法設計形式就應用辦法回調的機制,該形式起首界說特定的步調的算法骨架,而將一些步調延遲到子類中去完成的設計形式。模板辦法設計形式使得子類可以不轉變一個算法的構造便可從新界說該算法的某些特定步調。
模板方法設計形式的實用性:
1、一次性完成一個算法的不變部門,並將可變的算法留給子類來完成。
2、各子類中公共的行動應當被提掏出來並集中一個公共父類中以免代碼反復。
3、可以掌握子類擴大。
模板實例:
籠統模板辦法類:
public abstract class AbstractSup { //須要子類完成的辦法 public abstract void print(); //模板辦法 public void doPrint(){ System.out.println("履行模板辦法"); for (int i = 0; i < 3; i++) { print(); } } }
子類完成模板方法類:
public class SubClass extends 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(); } }
上面深刻引見下spring模板辦法的應用,以JdbcTemplete為例,具體解釋模板形式和回調機制的應用。
起首看一下經典的JDBC編程的例子:
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; }
一個簡略的查詢,就要做這麼一年夜堆工作,並且還要處置異常,我們不防來梳理一下:
1、獲得connection
2、獲得statement
3、獲得resultset
4、遍歷resultset並封裝成聚集
5、順次封閉connection,statement,resultset,並且還要斟酌各類異常等等。
假如是多個查詢會發生較多的反復代碼,這時候候便可以應用模板機制,經由過程不雅察我們發明下面步調中年夜多半都是反復的,可復用的,只要在遍歷ResultSet並封裝成聚集的這一步調是可定制的,由於每張表都映照分歧的java bean。這部門代碼是沒有方法復用的,只能定制。
籠統類代碼:
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); }
這個籠統類中,封裝了SUN JDBC API的重要流程,而遍歷ResultSet這一步調則放到籠統辦法doInStatement()中,由子類擔任完成。
子類完成代碼:
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; } } }
我們在doInStatement()辦法中,對ResultSet停止了遍歷,最初並前往。
測試代碼:
String sql = "select * from User"; JdbcTemplate jt = new JdbcTemplateUserImpl(); List<User> userList = (List<User>) jt.execute(sql);
模板機制的應用到此為止,然則假如每次挪用jdbcTemplate時,都要繼續一下下面的父類,如許挺不便利的,如許回調機制便可以施展感化了。
所謂回調,就是辦法參數中傳遞一個接口,父類在挪用此辦法時,必需挪用辦法中傳遞的接口的完成類。
回調加模板形式完成
回調接口:
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和轉換異常等。
以上就是本文的全體內容,願望對年夜家的進修有所贊助。