一、拦截器的理解
学习拦截器之前需要对动态代理和反射有一定的基础。
官方说法:
java里的拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重用部分的方式。在AOP(Aspect-Oriented Programming)中拦截器用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。
简单来说,就是拦截器可以提供一个在方法调用之前的方法,调用之后的方法,方便我们在方法执行的前后做拦截判或其他业务处理。
二、Jdk动态代理+拦截器
创建一个普通接口:HelloWorld.java
package com.xfwl.proxy.jdk; public interface HelloWorld {
public void sayHelloWorld();
}
创建一个上面皆接口的实现子类:HelloWorldImpl.java
package com.xfwl.proxy.jdk; public class HelloWorldImpl implements HelloWorld { public void sayHelloWorld() {
System.out.println("Hello World!");
}
}
创建一个拦截器的接口:Interceptor.java
package com.xfwl.interceptor; import java.lang.reflect.Method; /**
* 定义一个拦截器接口
* @function
* @author 小风微凉
* @time 2018-7-9 下午2:20:35
*/
public interface Interceptor {
/**
* 拦截器-真实方法调用之前before
* @param proxy 代理对象
* @param target 真实对象
* @param method 真实方法
* @param args 运行参数
* @return 返回boolean false则执行around(),true则不执行around()
*/
public boolean before(Object proxy,Object target,Method method,Object[] args);
/**
* before()返回 false则执行around(),true则不执行around()
* @param proxy 代理对象
* @param target 真实对象
* @param method 真实方法
* @param args 运行参数
*/
public void around(Object proxy,Object target,Method method,Object[] args);
/**
* before/around执行之后执行after()
* @param proxy 代理对象
* @param target 真实对象
* @param method 真实方法
* @param args 运行参数
*/
public void after(Object proxy,Object target,Method method,Object[] args);
}
创建上面拦截器接口的实现子类:MyInterceptor.java
package com.xfwl.interceptor; import java.lang.reflect.Method;
/**
* 拦截器实现子类
* @function 理解拦截器之前需要理解动态代理+反射机制
* @author 小风微凉
* @time 2018-7-9 下午2:25:34
*/
public class MyInterceptor implements Interceptor { @Override
public boolean before(Object proxy, Object target, Method method,Object[] args) {
System.out.println("反射方法前逻辑!");
return false;
} @Override
public void around(Object proxy, Object target, Method method, Object[] args) {
System.out.println("取代了被代理对象的方法!");
} @Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.println("反射方法后逻辑!");
}
}
创建一个动态代理类:InterceptorJdkProxy.java
package com.xfwl.interceptor; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* JDK动态代理实现类
* @function 在代理类中嵌入拦截器,关键点还是动态代理
* @author 小风微凉
* @time 2018-7-9 下午2:29:21
*/
public class InterceptorJdkProxy implements InvocationHandler {
//真实对象
private Object target=null;
//拦截器全称
private String interceptorClass=null;
//动态代理类构造器
public InterceptorJdkProxy(){}
public InterceptorJdkProxy(Object target,String interceptorClass){
this.interceptorClass=interceptorClass;
this.target=target;
}
/**
* 给真实独享绑定代理对象
* @param target 真实对象
* @param interceptorClass 拦截器的全称
* @return 代理对象【占位】
*/
public Object bind(Object target,String interceptorClass){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),//真实对象的类加载器
target.getClass().getInterfaces(), //真实对象的实现接口
new InterceptorJdkProxy(target, interceptorClass)//实现了InvocationHandler接口的实现类,一般为当前代理类对象
);
}
/**
* 通过代理对象调用方法,首先进入这个方法
* @param proxy 代理对象
* @param method 方法
* @param args 运行参数
* @return
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
//判断当前代理是否使用了拦截器
if(interceptorClass==null){
//没有拦截器,则直接执行真实对象的方法
return method.invoke(this.target, args);
}
Object result=null;
//通过反射拿到拦截器对象
Interceptor interceptor =(Interceptor)Class.forName(interceptorClass).newInstance();
//调用前置方法
if(interceptor.before(proxy, args, method, args)){
//反射真实对象原有的方法
result=method.invoke(target, args);
}else{
//返回false,执行around方法
interceptor.around(proxy, args, method, args);
}
//调用后置方法
interceptor.after(proxy, args, method, args);
return result;
}
}
创建一个测试类:TestInterceptor.java.
package com.xfwl.interceptor; import com.xfwl.proxy.jdk.HelloWorld;
import com.xfwl.proxy.jdk.HelloWorldImpl; /**
* 拦截器测试
* @function 测试一下拦截器是如何起作用的,
* @author 小风微凉
* @time 2018-7-9 下午2:19:15
*/
public class TestInterceptor { /**
* @param args
*/
public static void main(String[] args) {
//拿到代理对象,并绑定真实对象
HelloWorld proxy=(HelloWorld) new InterceptorJdkProxy().bind(
new HelloWorldImpl(),
"com.xfwl.interceptor.MyInterceptor"
);
//执行代理逻辑
proxy.sayHelloWorld(); } }
测试结果:
运行条件【1】:
@Override
public boolean before(Object proxy, Object target, Method method,Object[] args) {
System.out.println("反射方法前逻辑!");
return false;
}
运行结果:
反射方法前逻辑!
取代了被代理对象的方法!
反射方法后逻辑!
运行条件【2】:
@Override
public boolean before(Object proxy, Object target, Method method,Object[] args) {
System.out.println("反射方法前逻辑!");
return true;
}
运行结果:
反射方法前逻辑!
Hello World!
反射方法后逻辑!
从上面可以看出,拦截器生效了!