之前一直在糾結攔截器中是怎麼體現動態代理的,因爲動態代理不難理解,而攔截器就是把代理工具類中的代碼放到攔截器中實現,所以綁定方法和構造方法和普通的動態代理有一點點不同。
一、編寫攔截器接口
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時,結果是