Java回调机制

来源:互联网 发布:有什么金融软件 编辑:程序博客网 时间:2024/06/01 22:16

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


<span style="font-size:18px;">回调机制回调机制是一种常见的设计模型,他把工作流内的某个功能,按照约定的接口暴露给外部使用者,为外部使用者提供数据,或要求外部使用者提供数据。 软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。同步调用:一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;回 调:一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用:一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。回调和异步调用的关系非常紧密:使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。JAVA回调机制回调是一种双向调用模式,被调用方在被调用时也会调用对方,If you call me, i will call back”。一个比较经典的使用回调的方式:class A实现接口InA ——背景1class A中包含一个class B的引用b ——背景2class B有一个参数为InA的方法test(InA a) ——背景3A的对象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>



0 0
原创粉丝点击