Java回調函數詳解



1、回調函數的簡單實例


回調函數的簡單說明:
對象A的方法funA把對象A的引用傳遞到對象B的方法funB裏(且對象B方法funB的接收參數一般是對象A的實現接口),在對象B的方法funB中調用對象A的方法funC。對象A的方法funC被稱爲回調方法。






先上uml圖:


 




可以使用回調函數的場景:
   1、在java裏回調就是把對象A的引用傳遞到對象B的方法裏,且對象B方法的接收參數一般是對象A的實現接口,所以對象B的方法裏也只能調用到接口裏的方法,不會暴露其他方法。
   2、如果對象B中需要執行保密的任務,
   3、如果對象B執行的操作需要花比較長的時間,這是A就可以單開一個線程來調度B,讓B繼續執行,且A可以做其他事情去。
   4、如果對象B可以抽象出來公共性的工作。
實例1:
參考網上打電話的例子: 這個例子採用異步加回調


這是一個調用接口
   public interface CallBack{
        /**
         這個是小李知道答案時要調用的函數告訴小王,也就是回調函數
        */
        public void solve(String result);
   }


   /*
   這個是小王,實現了一個回調接口CallBack,相當於對象A
   */
   public class Wang implements CallBack {
      private Li li;
      public Wang(Li li){
          this.li = li;
      }


      public void askQuestion(final String question){
      
       //這裏用一個線程就是異步調用 
       new Thread(new Runnable(){
          @Override
          public void run(){
             li.executeMessage(this,question);
          }
       }).start();
       //問完問題了,可以做其他有意義的事情去了。
       play();
      }


    public void play(){
      System.out.println("做有意義的事情去了");
    }


    //回調函數,知道答案後就就可以通知小王了
    @Override
    public void solve(String result){
      System.out.println("小李通知小王的答案是:"+result);
    }
   }




/*
 這個是小李類,相當於對象B 
*/
  public class Li {


    public void executeMessage(CallBack callBack,String question){
       //小王問的問題是 
       System.out.println("小王問的問題是:"+question);
     
       System.out.println("小李思考->找到解決辦法->獲得答案");
       //把答案通知小王
       String result = "答案是ok";
       callBack.solve(result);
    }


  }


實例2:


UML類圖:


 
接口:
import java.sql.Connection;
import java.sql.SQLException;




public interface ConnectionCallback<T> {


T doSql(Connection conn) throws SQLException;


}




異步+回調+匿名內部類:使用回調實現了公共性的工作。


import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 執行數據庫操作
 * 
 * execute database operation  
 */
public class DbHelper {

private static final Logger LOG = LoggerFactory.getLogger(DbHelper.class);

/**
* 執行數據庫操作

* execute database operation  

* @param action
* @return
*/
public static <T> T execute(ConnectionCallback<T> action) {
Connection conn = null;
try {
conn = DbPool.getConnection();
return action.doSql(conn);
} catch (SQLException e) {
LOG.error(e.getMessage(),e);
} finally {
try {
if(conn != null){
conn.close();
}
} catch (SQLException e) {
LOG.error(e.getMessage(),e);
}
}
return null;
}


/**
* 執行數據入庫或更新刪除操作

* execute database operation  

* @param sql
* @param args
* @return
*/
public static Integer executeUpdate(final String sql,final Object... args) {

return execute(new ConnectionCallback<Integer>() {

@Override
public Integer doSql(Connection conn) throws SQLException {

PreparedStatement pstmt = conn.prepareStatement(sql,ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);

//        pstmt.setFetchSize(fetchSize);
   
   if (null != args) {
    StringBuilder sb = new StringBuilder(100);
     for (int i = 0; i < args.length; i++) {
       pstmt.setObject(i + 1, args[i]);
       sb.append(args[i]).append(",");
     }
//      System.out.println(sb);
   }


   LOG.info("SQL: " + pstmt);
   
   int result = pstmt.executeUpdate();
   
if(pstmt != null){
pstmt.close();
}


   return result;
}

});

}


/**
* 執行數據查詢操作

* execute database operation  

* @param sql
* @param args
* @return
*/
public static List<Map<String,Object>> executeQuery(final String sql,final Object... args) {

return execute(new ConnectionCallback<List<Map<String,Object>>>() {

@Override
public List<Map<String,Object>> doSql(Connection conn) throws SQLException {
PreparedStatement pstmt = null;
try{
pstmt = conn.prepareStatement(sql,ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);


pstmt.setFetchSize(50);

if (null != args) {
StringBuilder sb = new StringBuilder(100);
for (int i = 0; i < args.length; i++) {
pstmt.setObject(i + 1, args[i]);
sb.append(args[i]).append(",");
}
// System.out.println(sb);
}

LOG.info("SQL: " + pstmt);

ResultSet rs = pstmt.executeQuery();

return convertToList(rs);

}finally{
if(pstmt != null){
pstmt.close();
}

}
}

});

}



private static List<Map<String,Object>> convertToList(ResultSet rs) throws SQLException {


List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();


ResultSetMetaData md = rs.getMetaData();


int columnCount = md.getColumnCount();


while (rs.next()) {


Map<String,Object> rowData = new HashMap<String,Object>();


for (int i = 1; i <= columnCount; i++) {


rowData.put(md.getColumnName(i), rs.getObject(i));


}


list.add(rowData);


}
return list;


}
}




中間獲取數據庫連接的。




import java.sql.Connection;
import java.sql.SQLException;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import com.jolbox.bonecp.BoneCPDataSource;


/**
 * 數據庫連接池
 * 
 * database connection pool (singleton)
 * 
 */
public class DbPool {


private static final Logger LOG = LoggerFactory.getLogger(DbPool.class);
private static volatile DbPool INSTANCE = null;
private static BoneCPDataSource dataSource = null;


// Private constructor suppresses default public constructor
private DbPool() {}


// thread safe and performance promote
public static DbPool getInstance() {
if (INSTANCE == null) {
synchronized (DbPool.class) {
// when more than two threads run into the first null check same  time, to avoid instanced more than one time, it needs to be checked again.
if (INSTANCE == null) {
INSTANCE = new DbPool();
setDataSource(new BoneCPDataSource());
}
}
}
return INSTANCE;
}


/**
* 這個需要手工關閉當你用過這個connection時

* this need to be closed by hand when you finished the query 

* @return connection
*/
@SuppressWarnings("static-access")
public static Connection getConnection() {
try {
return getInstance().getDataSource().getConnection();
} catch (SQLException e) {
LOG.error(e.getMessage(),e);
}
return null;
}



/**
* close db pool
*/
public void shutdown() {
if(getDataSource() != null){
getDataSource().close();
}
}


private static BoneCPDataSource getDataSource() {
return dataSource;
}


private static void setDataSource(BoneCPDataSource dataSource) {
DbPool.dataSource = dataSource;
}


}








   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章