《代码精进之路》中看到的拦截器实现,方式比较巧妙,在此记录一下
一般我们在代码中实现业务拦截器的功能,是通过Spring提供的AOP来实现的,底层也就是基于动态代理及反射,这里看一下使用另一种不同的实现方式
使用时需要先构建TargetInvocation, 设置好目标类的实现、入参以及具体的拦截器信息,之后将TargetInvocation当做要调用的目标类使用,直接进行调用即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public void test() { final TargetInvocation targetInvocation = new TargetInvocation(); targetInvocation.addInterceptor(new LogInterceptor()); targetInvocation.addInterceptor(new AuditInterceptor()); targetInvocation.setRequest("100"); targetInvocation.setTarget(Integer::parseInt); final Integer result = targetInvocation.invoke(); System.out.println("main resp:" + result); }
|
下面看一下具体每个类的实现
- 首先需要明确好我们要调用的接口和接口具体的实现类,也就是这里的Target
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public interface Target { Integer execute(String req); }
Target target = Integer::parseInt;
|
- 定义核心的TargetInvocation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public class TargetInvocation { private List<Interceptor> interceptorList = new ArrayList<>(); private Iterator<Interceptor> interceptors; private Target target; private String request;
public Integer invoke() { if (interceptors.hasNext()) { final Interceptor interceptor = interceptors.next(); interceptor.interceptor(this); } return target.execute(request); }
public void addInterceptor(Interceptor interceptor) { interceptorList.add(interceptor); interceptors = interceptorList.iterator(); }
public Target getTarget() { return target; }
public void setTarget(Target target) { this.target = target; }
public void setRequest(String request) { this.request = request; } }
|
- 定义 Interceptor拦截器接口及实现类
1 2 3 4
| public interface Interceptor { Integer interceptor(TargetInvocation targetInvocation); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class AuditInterceptor implements Interceptor { @Override public Integer interceptor(TargetInvocation targetInvocation) { System.out.println("Audit Succeeded"); return targetInvocation.invoke(); } }
public class LogInterceptor implements Interceptor { @Override public Integer interceptor(TargetInvocation targetInvocation) { System.out.println("Logging Begin"); final Integer resp = targetInvocation.invoke(); System.out.println("Loggin end resp:" + resp); return resp; } }
|
上述代码利用了iterator的特性,在拦截器中递归调用时来实现执行下一个拦截器的功能,最终都拦截器执行完成后再进行实际代码的执行
这时执行之前的代码,执行结果如下:
1 2 3 4
| Logging Begin Audit Succeeded Loggin end resp:100 main resp:100
|
相比SpringAop方式的实现,因为没有使用反射所以这里的拦截器只能针对单一明确的入参和返回类型,无法做到特别通用