说起钩子(Hook)熟悉windows开发的人应该比较熟悉,例如鼠标钩子、键盘钩子等。用简单的语言描述就是在正常处理流程中安置某个钩子,当执行到安置钩子的地方就将进入指定的钩子函数进行处理,待处理完再返回原流程继续处理,当然也可以直接停止原流程的执行。所以说钩子是windows消息处理的一个重要的机制,专门用于监控指定的某些事件消息。
如果往更高层更抽象的角度来看,钩子其实是一种机制是一种思想,它的核心思想是在整个复杂的处理流程的所有关键点都触发响应的事件消息,假如添加了钩子则会调用钩子函数,函数中可根据传递过来的事件消息判断执行不同的逻辑。它就好像透明地让程序挂上额外的处理,且处理的逻辑可推迟到后面由开发者自定义。
为什么要使用钩子机制?可以这样认为,在一个庞大的系统内,某些基本的处理流程是相对固定的,且涉及到系统内部逻辑不应该允许外部去修改它,但又要考虑到系统的扩展性,必须预留某些接口让开发者在不改变系统内部基本处理流程的情况下可以自定义一些额外的处理逻辑。于是引入钩子机制,按照钩子思想最后实现的效果相当是在一个允许在适当位置嵌入自定义的代码,此机制保证了系统内部不受外界修改同时又预留足够的扩展空间。
对于java大家比较熟悉的就是JVM的关闭钩子ShutdownHook了,提供一种在虚拟机关闭之前进行额外操作的功能。当然钩子并不仅仅是具体的某些功能,它更是一种机制,是一种设计方法。看看tomcat的响应对象如何使用钩子机制。
① 定义钩子接口
public interface ActionHook {
public void action(ActionCode actionCode, Objectparam);
}
② 定义消息状态值,为方便理解,假设这里只有两种状态,实际包含了几十个状态
public enum ActionCode {
CLOSE, COMMIT
}
③ 响应对象,它包含了钩子属性
public class Response {
public ActionHook hook;
public ActionHook getHook() {
return hook;
}
public void setHook(ActionHook hook) {
this.hook = hook;
}
public void action(ActionCode actionCode,Object param) {
hook.action(actionCode, param);
}
}
④ 钩子处理类,分别对不同的消息状态进行不同的逻辑处理
public class Http11Processor implements ActionHook {
public void action(ActionCode actionCode,Object param) {
if (actionCode ==ActionCode.CLOSE) {
System.out.println("Beforeclosing");
} else if (actionCode ==ActionCode.COMMIT) {
System.out.println("Beforecommitting");
}
}
}
⑤ 测试类,假设对response对象的处理流程如下,那么在每个关键节点都通过action方法触发钩子,并附带上消息状态,于是每个关键点都能做点额外的事,只要通过修改Http11Processor中action发放即可,根据状态自定义处理逻辑。
public class HookTest {
public static void main(String[] args) {
ActionHook actionHook=new Http11Processor();
Response response=new Response();
response.setHook(actionHook);
response.action(ActionCode.COMMIT, null);
System.out.println("commit...");
response.action(ActionCode.CLOSE, null);
System.out.println("close...");
}
}