前言
最近需要实现一个插件功能,但是如果做成两个接口的话(即执行前和执行后),那么会降低插件的可玩性,所以需做成类似AOP的环绕通知形式,所以就使用到了责任链模式和代理模式进行实现。
介绍
代理模式(Proxy Pattern)
定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
UML:
在Java中,常见代理模式的实现有Java静态、动态代理,CGLIB动态代理,JAVAssist动态代理等等。
责任链模式(Chain of Responsibility Pattern)
定义:为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
UML:
可以把它理解为一个链表,每个节点上的对象都实现了同一个接口,并且在对象内部指向下一个节点对象,在开始执行第一个节点的时候,就会传递到每一个节点
常见的责任链实现有 Servlet中的Filter,SpringMVC的Intercept拦截器,AOP中的环绕通知,Mybatis的插件功能,Druid中Filter等等。
实现
实现一个简单的目标执行器执行
定义一个Executor接口,TargetExecutor实现Executor并实现execute方法,然后通过Executor进行调用,定义一个参数对象,模拟真实业务场景。
现在需要通过代理和责任链实现对Executor的execute方法进行批量增强
定义一个封装代理对象
这个对象是用来在拦截器里面手动调用执行目标方法的,这样就可以在拦截前和拦截后做一些业务处理等等。
1:proceed():当调用Proceed对象的proceed方法时,即执行代理对象的目标方法
2:targetObject: 为真实的执行对象(这个是为了记录真实的目标执行对象,可以直接操作目标对象)
3:targetProxy: 为真实/代理对象(第一个拦截器为真实对象,后面的就是前一个拦截器的代理对象)
4:args: 目标执行对象调用方法的参数
定义一个责任链共用接口以及生成代理对象的共用方法
责任链中的共用实现接口
1:intercept():
每个拦截器都需要实现的方法,参数为Proceed对象,每个具体的拦截器可根据具体逻辑进行操作真实的Executor对象和ParamEvent参数对象
2:newProxy():
创建目标对象的代理方法,由于这里目标执行对象是使用接口实现的方式,所以使用的是JDK的动态代理,如果是普通的类,则可以使用CGLIB动态代理生成代理类
实现代理类的具体执行方法,进行对目标对象的增强
目标执行对象方法真实执行类,当目标执行对象调用目标执行方法时,需要调用拦截器的intercept方法,由拦截器手动调用proceed方法,进入下一个拦截器,因此形成调用链路。
1:targetObject: 具体目标执行对象
2:targetProxy:为真实/代理对象
3:intercept:下一个链路节点对象
4:invoke: 动态代理接口执行方法,该方法里面为调用拦截器得intercept方法
创建管理责任链链路对象
用于管理和创建目标执行对象的代理对象
1:interceptList:所有实现链路接口的对象有序集合
2:addIntercept():添加链路节点对象方法
3:createProxy(): 创建代理对象方法,参数为target(具体执行对象),利用循环创建代理对象将所有的拦截器生成一个责任链链路。
验证
记录execute方法的运行时间拦截器
修改目标执行方法的对象参数拦截器
修改目标执行对象属性值拦截器
-
查看运行结果:
拦截器功能实现成功!