Java回调机制

今天在学习Spring  HibernateTemplate的过程中,碰到了好多回调,一直不太明白回调到底是啥意思,所以自己从网上看了下别人的例子学习了下:


<span style="font-size:18px;">回调机制
回调机制是一种常见的设计模型,他把工作流内的某个功能,按照约定的接口暴露给外部使用者,为外部使用者提供数据,
或要求外部使用者提供数据。 

软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。
同步调用:一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;
回 调:一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;
异步调用:一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,
会主动通知客户方(即调用客户方的接口)。

回调和异步调用的关系非常紧密:使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。

JAVA回调机制
回调是一种双向调用模式,被调用方在被调用时也会调用对方,If you call me, i will call back”。
一个比较经典的使用回调的方式:
class A实现接口InA ——背景1
class A中包含一个class B的引用b ——背景2
class B有一个参数为InA的方法test(InA a) ——背景3
A的对象a调用B的方法传入自己,test(a) ——这一步相当于you call me
然后b就可以在test方法中调用InA的方法 ——这一步相当于i call you back


先来看一个简单的例子,这个我在网上看到的,比较容易理解,不那么绕

/**
 * 接口类(抽象类) 他需要在调用方法处被实现为一个匿名类,其中的postExec()就是回调方法
 */
public interface ICallBack {
    //需要回调的方法
    public void postExec();
}

/**
 * 被调用的类,其中的setCallBack方法是被调用的方法
 */
public class FooBar {

    private ICallBack callBack;
    public void setCallBack(ICallBack callBack){
        this.callBack=callBack;
        doSth();
    }
    public void doSth(){
        callBack.postExec();
    }
}

/**
 * 第二个类在测试类里面,是一个匿名类
 */
public class Test {
   /* public static void main(String [] args){
        FooBar foo=new FooBar();
        foo.setCallBack(new ICallBack() {
            @Override
            public void postExec() {
                System.out.println("在test类中实现但不能被Test的对象引用,而由FooBar对象调用");
            }
        });
    }*/
}

上面的Test就是一个用于测试的调用者类,它通过main方法中实例化一个FooBar,并用实现的ICallBack的匿名
类作为参数传递给FooBar的被调用方法setCallBack,而在这个虚拟方法中,FooBar调用了匿名类的匿名类的postExec方法的动作,
这个动作就是回调(Callback)。

模拟Spring中HibernateTemplate回调机制的代码
/**
 * 模拟Spring 中HibernateTemplate回调机制的代码
 */
public interface CallBack {
    public void doCRUD();
}


/**
 * Created by  on 2014/11/19.
 */
public class HibernateTemplate {
    public void execute(CallBack action){
        getConnection();
        action.doCRUD();
        releaseConnection();
    }

    /**
     * 我在这里的理解是:通过匿名内部类的方式实现了CallBack接口,执行execute方法时执行
     * action.doCRUD(),这是就是回调了CallBack接口中的方法,这个方法已经在匿名内部类
     * 里面是实现了,
     */
    public void add(){
        //1
        execute(new CallBack() {
            @Override
            public void doCRUD() {
                System.out.println("执行add操作");
            }
        });//2    1到2之间的代码相当于A类(这里的A类被隐藏)调用了B类。然后在执行execute时执行了 action.doCRUD();,
		//所以相当于B类又回调了A类中的方法
    }

    public void getConnection(){
        System.out.println("获得连接....");
    }

    public void releaseConnection(){
        System.out.println("释放链接");
    }
}

下面用回调的通俗表达方式来还原上面回调的过程:
interface CallBack{   //相当于接口InA  
    public void doCRUD();     
}    
  
public class A implements CallBack{//【背景1】  
    private B b;//【背景2】  
    public void doCRUD(){    
          System.out.println("执行add操作...");    
     }    
  
     public void add(){    
             b.execute(new A());//【you call me】    
        }    
}  
  
public class B{  
     public void execute(CallBack action){  //【背景3】  
            getConnection();    
            action.doCRUD();  //【i call you back】  
            releaseConnection();    
        }    
  
      public void getConnection(){    
            System.out.println("获得连接...");    
        }    
            
        public void releaseConnection(){    
            System.out.println("释放连接...");    
        }    
}  

总之,相当于就是A调用B的方法,B再反过来调用A的方法.
为什么要使用回调呢?
像getConnection()是费时的操作,A想把这些交给B来完成,等B执行完之后再来通知A

这是使用了匿名内部类,匿名内部类的好处是:
匿名内部类是当做函数的参数传递给方法的,在这个方法中会用接口类型接受传入的匿名类
然后调用其方法,这是多态,原理其实就是实现了回调。
使用匿名内部类可以使语法看上去简洁。


什么是多态?
  多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。
  多态有两种表现形式:重载和覆盖
  首先说重载(overload),是发生在同一类中。与什么父类子类、继承毫无关系。    
  标识一个函数除了函数名外,还有函数的参数(个数和类型)。也就是说,一个类中可以有两个或更多的函数,叫同一个名字而他们的参数不同。    
  他们之间毫无关系,是不同的函数,只是可能他们的功能类似,所以才命名一样,增加可读性,仅此而已!  
    
  再说覆盖(override),是发生在子类中!也就是说必须有继承的情况下才有覆盖发生。
  
  我们知道继承一个类,也就有了父类了全部方法,如果你感到哪个方法不爽,功能要变,那就把那个函数在子类中重新实现一遍。  
  这样再调用这个方法的时候,就是执行子类中的过程了。父类中的函数就被覆盖了。(当然,覆盖的时候函数名和参数要和父类中完全一样,不然你的方法对父类中的方法就不起任何作用,因为两者是两个函数,毫不关系)</span>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值