Java - 拦截器 - 图1

什么是拦截器?有什么作用(应用)?

简单点说就是对执行方法请求的拦截,即在执行请求方法前做相应的拦截逻辑处理。

当对象A的a1方法调用B的b1方法时,使用某种技术(大部分是通过代理proxy),使其先调用某个其他方法,然后再去调用b1方法。

拦截器的实现原理是啥?怎么自定义拦截器?

技术原理

大部分是通过代理方式实现的,代理又分 静态代理 、动态代理(大部分)。
动态代理的基础是反射。

自定义拦截器

1.拦截器类Interceptor

  1. public interface Interceptor {
  2. boolean before(Object proxy, Object target, Method method, Object[] args);
  3. void around(Object proxy, Object target, Method method, Object[] args);
  4. void after(Object proxy, Object target, Method method, Object[] args);
  5. }
  1. public class LoginInterceptor implements Interceptor {
  2. @Override
  3. public boolean before(Object proxy, Object target, Method method, Object[] args) {
  4. System.out.println(method.getName() + "\tbefore: do something");
  5. return true; // or false
  6. }
  7. @Override
  8. public void around(Object proxy, Object target, Method method, Object[] args) {
  9. System.out.println(method.getName() + "\taround:do something");
  10. }
  11. @Override
  12. public void after(Object proxy, Object target, Method method, Object[] args) {
  13. System.out.println(method.getName() + "\tafter:do something");
  14. }
  15. }

2. 代理类Proxy

  1. public class InterceptorJdkProxy implements InvocationHandler {
  2. private Object target; // 代理目标
  3. private Class interceptorClass; // 拦截器类
  4. /**
  5. * 构造器 - 指定拦截目标和拦截器
  6. *
  7. * @param target
  8. * @param interceptorClass
  9. */
  10. public InterceptorJdkProxy(Object target, Class interceptorClass) {
  11. this.target = target;
  12. this.interceptorClass = interceptorClass;
  13. }
  14. /**
  15. * 绑定代理目标对象 和 拦截器类
  16. * @param target
  17. * @param interceptorClass
  18. * @return
  19. */
  20. public static Object bind(Object target, Class interceptorClass) {
  21. return Proxy.newProxyInstance( target.getClass().getClassLoader(),
  22. target.getClass().getInterfaces(),
  23. new InterceptorJdkProxy(target, interceptorClass));
  24. }
  25. @Override
  26. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  27. /*拦截器未指定 直接执行 不作拦截*/
  28. if (interceptorClass == null){
  29. return method.invoke(target, args);
  30. }
  31. /* 反射生成拦截器对象*/
  32. Interceptor interceptor = (Interceptor)interceptorClass.newInstance();
  33. /*拦截器前置方法*/
  34. if (interceptor.before(proxy, target,method,args)){
  35. /*拦截器环绕方法*/
  36. interceptor.around(proxy, target,method,args);
  37. }
  38. /*拦截器后置方法*/
  39. interceptor.after(proxy, target,method,args);
  40. return method.invoke(target, args);
  41. }
  42. }

3. 测试

  1. public interface UserLoginService {
  2. boolean doLogin(User user);
  3. boolean doLoginVersion2(User user);
  4. }
  1. public class Test {
  2. public static void main(String[] args) throws Throwable {
  3. UserLoginService userLoginService = (UserLoginService)
  4. InterceptorJdkProxy.bind(new UserLoginServiceImpl(), LoginInterceptor.class);
  5. userLoginService.doLogin(new User());
  6. userLoginService.doLoginVersion2(new User());
  7. }

image.png

深究

JDK动态代理和CGLib动态代理
拦截器栈
Spring web拦截器