什么是拦截器?有什么作用(应用)?
简单点说就是对执行方法请求的拦截,即在执行请求方法前做相应的拦截逻辑处理。
当对象A的a1方法调用B的b1方法时,使用某种技术(大部分是通过代理proxy),使其先调用某个其他方法,然后再去调用b1方法。
拦截器的实现原理是啥?怎么自定义拦截器?
技术原理
大部分是通过代理方式实现的,代理又分 静态代理 、动态代理(大部分)。
动态代理的基础是反射。
自定义拦截器
1.拦截器类Interceptor
public interface Interceptor {boolean before(Object proxy, Object target, Method method, Object[] args);void around(Object proxy, Object target, Method method, Object[] args);void after(Object proxy, Object target, Method method, Object[] args);}
public class LoginInterceptor implements Interceptor {@Overridepublic boolean before(Object proxy, Object target, Method method, Object[] args) {System.out.println(method.getName() + "\tbefore: do something");return true; // or false}@Overridepublic void around(Object proxy, Object target, Method method, Object[] args) {System.out.println(method.getName() + "\taround:do something");}@Overridepublic void after(Object proxy, Object target, Method method, Object[] args) {System.out.println(method.getName() + "\tafter:do something");}}
2. 代理类Proxy
public class InterceptorJdkProxy implements InvocationHandler {private Object target; // 代理目标private Class interceptorClass; // 拦截器类/*** 构造器 - 指定拦截目标和拦截器** @param target* @param interceptorClass*/public InterceptorJdkProxy(Object target, Class interceptorClass) {this.target = target;this.interceptorClass = interceptorClass;}/*** 绑定代理目标对象 和 拦截器类* @param target* @param interceptorClass* @return*/public static Object bind(Object target, Class interceptorClass) {return Proxy.newProxyInstance( target.getClass().getClassLoader(),target.getClass().getInterfaces(),new InterceptorJdkProxy(target, interceptorClass));}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {/*拦截器未指定 直接执行 不作拦截*/if (interceptorClass == null){return method.invoke(target, args);}/* 反射生成拦截器对象*/Interceptor interceptor = (Interceptor)interceptorClass.newInstance();/*拦截器前置方法*/if (interceptor.before(proxy, target,method,args)){/*拦截器环绕方法*/interceptor.around(proxy, target,method,args);}/*拦截器后置方法*/interceptor.after(proxy, target,method,args);return method.invoke(target, args);}}
3. 测试
public interface UserLoginService {boolean doLogin(User user);boolean doLoginVersion2(User user);}
public class Test {public static void main(String[] args) throws Throwable {UserLoginService userLoginService = (UserLoginService)InterceptorJdkProxy.bind(new UserLoginServiceImpl(), LoginInterceptor.class);userLoginService.doLogin(new User());userLoginService.doLoginVersion2(new User());}
深究
JDK动态代理和CGLib动态代理
拦截器栈
Spring web拦截器

