之前一直在纠结拦截器中是怎么体现动态代理的,因为动态代理不难理解,而拦截器就是把代理工具类中的代码放到拦截器中实现,所以绑定方法和构造方法和普通的动态代理有一点点不同。
一、编写拦截器接口
package com.taylor.interceptor;
import java.lang.reflect.Method;
public interface Interceptor {
/**
* 方法需要的4个参数
* 1.代理对象
* 2.真实对象
* 3.调用的方法
* 4.方法的参数
*/
/*
* 1.before方法返回boolean值,它在真实对象调用之前执行,当返回值为true,则反射真实对象的方法,若返回值
* 为false,则调用around方法。
*/
public boolean before(Object object,Object target,Method method,Object[] args);
public void after(Object object,Object target,Method method,Object[] args);
public void around(Object object,Object target,Method method,Object[] args);
}
二、、编写拦截器接口实现类
package com.taylor.interceptor;
import java.lang.reflect.Method;
public class MyInterceptor implements Interceptor {
@Override
public boolean before(Object object, Object target, Method method, Object[] args) {
System.out.println("反射方法前逻辑");
return true; //不反射被代理对象原有方法
}
@Override
public void after(Object object, Object target, Method method, Object[] args) {
System.out.println("反射方法后逻辑");
}
@Override
public void around(Object object, Object target, Method method, Object[] args) {
System.out.println("取代了被代理对象的方法");
}
}
三、编写代理工具类
package com.taylor.interceptor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class InterceptorJdkProxy implements InvocationHandler{
//把真实对象和拦截器传递进来
private Object target; //真实对象
/*
* 这里传拦截器路径名的原因很简单,通过反射生成对象,而不是new
*/
private String InterceptorClass = null; //这个是拦截器的路径名
//通过构造方法把值传入
public InterceptorJdkProxy(Object target, String interceptorClass) {
this.target = target;
InterceptorClass = interceptorClass;
}
//提供一个生成代理对象的方法,参数是真实对象和拦截器的全路径。
public static Object bind(Object target, String interceptorClass) {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InterceptorJdkProxy(target, interceptorClass));
/*
*这里和动态代理不同的就是第三个参数,
*普通动态代理的第三个参数是this,表示当前对象,因为它调用的就是该类的方法。
*而这里的第三个参数是一个代理工具类的对象,因为它要调用的的方法是写在了拦截器中,
*刚好拦截器和真实对象又可以通过构造方法传递进来。
*至于为什么bind()写成static,是想通过类名直接调用,而无需生成多余对象。
*/
}
/*
* proxy:代理对象
* method:被调用的方法
* args:方法所需参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//通过代理调用方法,首先进入这个方法
if(InterceptorClass==null) { //没传入拦截器,则直接反射原有方法
return method.invoke(target, args);
}
Object result = null; //返回值
//通过反射生成拦截器
Interceptor interceptor
= (Interceptor) Class.forName(InterceptorClass).newInstance();
//调用前置方法
if(interceptor.before(proxy, target, method, args)) {
//反射原有方法
result = method.invoke(target, args);
}else {
//返回false执行取代方法
interceptor.around(proxy, target, method, args);
}
interceptor.after(proxy, target, method, args);
return result;
}
}
四、编写被代理对象的接口和实现类
package com.taylor.dao;
public interface HelloWorld {
public void say();
}
package com.taylor.dao;
public class HelloWorldImpl implements HelloWorld{
@Override
public void say() {
System.out.println("hello world");
}
}
五、测试类和运行结果
package com.taylor.test;
import com.taylor.dao.HelloWorld;
import com.taylor.dao.HelloWorldImpl;
import com.taylor.interceptor.InterceptorJdkProxy;
public class TestHelloWorld {
public static void main(String[] args) {
//1.代理对象
HelloWorld proxy = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(),
"com.taylor.interceptor.MyInterceptor");
//2.通过代理对象调用方法
proxy.say();
}
}
*当before方法的返回值为true时,结果是
*当before方法的返回值为false时,结果是