由于动态代理一般比较难理解,程序设计者会设计一个拦截器接口提供给开发使用,开发只要知道拦截器接口的方法,含义,作用即可,无需知道动态代理是怎么样实现的
jdk动态代理实现拦截器
定义接口
package com.lean.ssm.chapter2.reflect;
import java.lang.reflect.Method;
public interface Interceptor {
/**
* @param proxy 代理对象
* @param target 真实对象
* @param method 方法
* @param args 运行参数
* @return 返回TRUE调用真实对象方法,false调用around方法
*/
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);
}
实现类
package com.lean.ssm.chapter2.reflect;
import java.lang.reflect.Method;
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("在反射方法后逻辑");
}
}
它实现了所有的接口方法,使用jdk动态代理可以去实现这些方法的调用逻辑了,在jdk动态代理中使用拦截器
package com.lean.ssm.chapter2.reflect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class InterceptorJdkProxy implements InvocationHandler {
private Object target;//真实对象
private String interceptorClass=null;//拦截器完全限定名
public InterceptorJdkProxy(Object target, String interceptorClass) {
this.target = target;
this.interceptorClass = interceptorClass;
}
/**绑定真实对象和拦截器
* @param target 真实对象
* @param interceptorClass 拦截器完全限定名
* @return
*/
public static Object bind(Object target, String interceptorClass){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InterceptorJdkProxy(target, interceptorClass));
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//没有设置拦截器直接返回真实对象方法
if (interceptorClass==null) {
return method.invoke(target, args);
}
Object ret=null;
//反射生成拦截器
Interceptor interceptor=(Interceptor) Class.forName(interceptorClass).newInstance();
//before返回true调用真实方法,false调用around方法
if (interceptor.before(proxy, target, method, args)) {
ret=method.invoke(target, args);
}else {
interceptor.around(proxy, target, method, args);
}
interceptor.after(proxy, target, method, args);
return ret;
}
}
拦截器可以进一步简化动态代理的使用方法,使程序变得简单
测试
/**
* jdk拦截器
*/
@Test
public void testInterceptor(){
HelloWorld proxy=(HelloWorld) InterceptorJdkProxy
.bind(new HelloWorldImpl(),"com.lean.ssm.chapter2.reflect.MyInterceptor");
proxy.sayHelloWorld();
}
输出
在反射方法前逻辑
取代代理对象的方法...
在反射方法后逻辑
显然,拦截器已经生效了