1. 程式人生 > >攔截器(由JDK動態代理實現的攔截器)

攔截器(由JDK動態代理實現的攔截器)

gpo ret throwable voc row 接口 his 截器 運行

要實現攔截器,首先我們需要定義幾個類和接口

package com.xiawei.reflect.interceptor;

public interface JavaBenDao {

public void look();
}

==================================================

package com.xiawei.reflect.interceptor;

public class JavaBenDaoImpl implements JavaBenDao {

@Override
public void look() {
System.out.println("這是真實對象的方法!");


}

}

==================================================

這裏要自定義一個攔截器的接口,並且定義了三個抽象的方法

before(),around(),after()。這三個方法分別被用在執行反射

方法前;取代被代理的對象時;在執行反射方法後三個節點。

package com.xiawei.reflect.interceptor;

import java.lang.reflect.Method;

/**
* 自定義攔截器的接口
* @author Administrator
*
*/
public interface InterceptorDao {

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.xiawei.reflect.interceptor;

import java.lang.reflect.Method;
/**
* 攔截器實現類
* @author Administrator
*
*/
public class InterceptorDaoImpl implements InterceptorDao{

@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.println("在執行反射方法前執行的邏輯!");
return true;//默認值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動態代理類,再在動態代理中使用攔截器

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 在動態代理中使用攔截器</p>
* 動態代理類
* @author Administrator
*
*/
public class JdkInterceptorClass implements InvocationHandler {

/**
* 真實對象
*/
private Object target;
/**
* 攔截器的全限定名
*/
private String interceptorClass;

public JdkInterceptorClass(Object target, String interceptorClass) {
this.target = target;
this.interceptorClass = interceptorClass;
}

//綁定委托對象,並返回一個代理站位
public static Object bind(Object target,String interceptorClass){

return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), new JdkInterceptorClass(target,interceptorClass));
}

/**
* 通過代理對象調用方法,首先進入invoke()
* @param proxy 代理對象
* @param method 被調用的方法
* @param args 方法參數
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//判斷,如果攔截器全限定名為空,也就是沒有設置攔截器則反射原有方法(真實對象的方法)
if(interceptorClass == null){
return method.invoke(target, args);
}

//通過反射生成攔截器
Object result = null;//定義執行以下邏輯後的返回值
InterceptorDao interceptor =
(InterceptorDao) Class.forName(interceptorClass).newInstance();

//調用真實對象的方法前的方法邏輯
if(interceptor.before(proxy, target, method, args)){
//如果為true,則反射原有(真實)對象方法
result = method.invoke(target, args);
}else{
//如果為false,執行around()方法
interceptor.around(proxy, target, method, args);
}
//調用真實對象的方法後的方法邏輯
interceptor.after(proxy, target, method, args);

return result;
}

}

=========================================================

好了,代碼完成後我們測試一下,寫個測試類

package com.xiawei.reflect.interceptor;

public class Test {

public static void main(String[] args) {
//獲得代理對象
JavaBenDao proxy = (JavaBenDao) JdkInterceptorClass.bind(new JavaBenDaoImpl(),
"com.xiawei.reflect.interceptor.InterceptorDaoImpl");
//調用真實對象的方法
proxy.look();

}

運行結果:

  在執行反射方法前執行的邏輯!
  這是真實對象的方法!
  在執行反射方法後執行的邏輯!

可以將上面的 before()方法的返回值改為false試一下.哈哈

攔截器(由JDK動態代理實現的攔截器)