拦截器
2019-04-14 本文已影响5人
xm的那年
由于动态代理一般都比较难理解,程序设计者都会设计一个拦截器接口供开发者使用,开发者只要知道拦截器接口的方法,含义和作用即可。无须知道动态代理是怎么实现的,用JDK动态代理来实现一个拦截器的逻辑,为此先定义拦截器接口Interceptor,
package com.lean.ssm.chapter2.Inceptor;
import java.lang.reflect.Method;
public interface Interceptor {
public boolean before(Object proxy,Object target,Method method,Object[] args);
public void around(Object proxy,Object target,Method method,Object[] args);
public void after(Object proxy,Object target,Method method,Object[] args);
}
/**
- 这里定义了3个方法,before,around,after方法,分别给予这些方法如下的逻辑定义。
- 3个方法的参数:proxy为代理对象,target真实对象,method方法,args运行方法参数
- before方法返回boolean值,它在真实对象前调用,当返回true值,就反射真实对象的方法,当返回false的时候,则调用around方法
- 在before方法返回为false的情况下,调用around方法
- 在反射真实对象方法或around方法使用完成后,调用after方法
- @author Administrator
*/
实现Interceptor的实现类,MyInterceptor
package com.lean.ssm.chapter2.Inceptor;
import java.lang.reflect.Method;
public class MyInterceptor implements Interceptor{
@Override
public boolean before(Object proxy, Object target, Method method,
Object[] args) {
// TODO Auto-generated method stub
System.out.println("反射方法前调用");
return true;
// 不反射被代理对象原有方法
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
// TODO Auto-generated method stub
System.out.println("取代反射方法");
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
// TODO Auto-generated method stub
System.out.println("反射方法后的逻辑");
}
}
它实现了所有的Interceptor的方法,使用JDK动态代理,就可以实现这些方法在适当的调用逻辑
package com.lean.ssm.chapter2.Inceptor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.lean.ssm.chapter.proxy.HelloWorld;
import com.lean.ssm.chapter.proxy.HelloWorldImpl;
public class InterceptorProxy implements InvocationHandler {
// 使用JDK动态代理就可以去实现这些方法在适当的时候调用逻辑。
private Object target;
// 真实对象
private String interceptorClass=null;
// 拦截器权限定名
public InterceptorProxy(Object target,String interceptorClass){
this.interceptorClass=interceptorClass;
this.target=target;
}
public static Object bind(Object target,String interceptorClass){
// 取得代理对象 interceptorClass的拦截器的类名
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InterceptorProxy(target,interceptorClass));
}
/**
* 通过代理对象调用方法,首先进入这个方法
* proxy 代理对象
* method 方法,被调用方法
* args 方法的参数
*
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
if(interceptorClass==null){
// 如果没有设置拦截器则直接反射原有方法
return method.invoke(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;
}
public static void main(String[] args) {
HelloWorld proxy=(HelloWorld)InterceptorProxy.bind(new HelloWorldImpl(), "com.lean.ssm.chapter2.Inceptor.MyInterceptor");
proxy.sayHelloWorld("AJMAN");
}
}
这里有两个属性,一个是target,它是真实对象,另一个是字符串,interceptorClass,它是一个拦截器的全限定名 ,
解释一下代码的执行步骤
- 在bind方法中使用JDK动态代理绑定了一个对象,然后返回代理对象
- 如果没有拦截器,则直接反射真实对象的方法,然后结束否则进行第3步
- 通过反射生成拦截器,并准备使用它
- 调用拦截器的before方法,如果返回为true,则反射原来的方法,否则运行拦截器的around方法
- 调用拦截器的after方法
- 返回结果