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;
}
}