在程序中,通常想要获取信息需要去主动调用,比如调用get方法获取值。 但是这样有些场景就满足不了,比如你想要获取的信息产生的时间不确定。当然,你可以做个循环一直去get,直到get到想要的信息为止。但这并不是一个好办法。 回调,就是被动通知。我调个接口,并没有立刻获取到结果,没关系,等结果出来之后被调用者自动给我返回。这样的好处是我不需要重复去查询结果,解耦代码。 .
现在通过买票的例子进行分析
场景:我买票,售票员通知我出票结果
分析:关键词是被通知,很显然,我的出票结果是被售票员通知的,但是怎么通知?很多网文一笔带过,难道真实情况真的是这么简单不值一提吗?
真相:实际上管理员是不能直接通知到我,而是有个中间人,对,我有个朋友叫小明,是他帮我转告售票员的"口述的"。所以真实的情况是:我在售票窗口买票,给了钱之后,就把身边的小明扣住,然后转身对售票大叔说,待会出票了你跟他说就行了,他会转告给我。于是,过一会,出结果了,小明就屁颠屁颠跑来说:“有结果了,出票成功.”
原理:上面的例子中小明就是回调载体。而小明是定义好的,我在我需要得到通知的事件中交给售票员的,并且在小明身上定义了一些协议,比如通知消息的格式等等。然后他就负责返回我要的消息。
对象: 我–>Me 售票员–>Conductor 小明–>Callback .
结果: 至此,一个简单的回调梳理就结束了。
现在通常都在spring 上开发,那么如何编写回调,并且给外部暴露回调接口呢?往下,进入进阶模式
实现说明:将回调实现抽象起来,然后暴露回调函数,其他地方需要重写回调时继承即可 然后将回调接口注入到spring 容器中即可。
简单比喻就是,我让小明出票了通知我,但是小明比较懒,就让小红来帮忙转达消息(小红继承小明,重写小明回调函数)
/** * 回调,这是一个小明 * @Author TanXiongzhan */ public interface Callback { void returnResult(String msg); } /** * 将回调暴露出去,继承者重写结果返回方法即可 * @Author Tan */ public abstract class CallbackAbstract implements Callback { @Override public void returnResult(String msg) { // System.out.println("小明通知:" + msg); returnResultPublic(msg); } public abstract void returnResultPublic(String msg); } /** * 第三方继承回调实现(监听回调) * 这是小红 * @Author Tan */ @Service public class CallbackImpl extends CallbackAbstract { @Override public void returnResultPublic(String msg) { System.out.println("小红通知:" + msg); } } /** * 售票员 * * @Author Tan */ public class Conductor { public void printTickets(Callback callback) { System.out.println("售票员开始处理 . . . "); try { Thread.currentThread(); Thread.sleep(3000); } catch (Exception e) { e.printStackTrace(); } System.out.println("售票员处理完毕 . . . "); // 出票完成,通知出票结果(这里是发起回调的地方) callback.returnResult("出票完成"); } } /** * 这是我 * @Author TanXiongzhan */ public class Me { // 指定一个售票人(待会他出票后要通知我) Conductor conductor = new Conductor(); /* * 同步回调 * 方法:买票 * 内容:内容:把回调对象(小明)传给售票员 */ public void buyTicketsSyn(Callback callback) { conductor.printTickets(callback); } /* * 异步回调 * 方法:买票 * 内容:把回调对象(小明)传给售票员 */ public void buyTicketsSynASyn(Callback callback) { new Thread(new Runnable() { public void run() { conductor.printTickets(callback); } }).start(); } } /** * 在实际应用中,用注入的方式声明回调接口 * 谁实现,调用谁的回调函数 * @Author Tan */ @Service public class MainSpring implements InitializingBean { @Autowired private Callback callback; @Override public void afterPropertiesSet() throws Exception { Me me = new Me(); System.out.println("我准备买票----"); // me.buyTicketsSyn(callback); //发起买票(同步回调) me.buyTicketsSynASyn(callback); //发起买票(异步回调) System.out.println("我在等待出票----"); } }运行结果: . . . 完毕