反射-動態代理的概述和實現

ZHOU_VIP發表於2017-06-11
動態代理:在程式執行過程中產生的這個物件

而程式執行過程中產生物件其實就是剛才反射講解的內容,所以,動態代理其實就是通過反射來生成一個代理。

在Java中java.lang.reflect包下提供了一個Proxy類和一個InvocationHandler介面,通過使用這個類和介面

就可以生成動態代理物件。JDK提供的代理只能針對介面做代理。我們有更強大的代理cglib,和後面要學的框架有關。

Proxy類中的方法建立動態代理類物件

publicstatic Object newProxyInstance(ClassLoaderloader,Class<?>[]interfaces,InvocationHandlerh)

最終會呼叫InvocationHandler的方法

InvocationHandler

Object invoke(Object proxy,Methodmethod,Object[] args)

------------------------------------------------------------------------------------------------------------------------------------

Proxy類中建立動態代理物件的方法的三個引數;

ClassLoader物件,定義了由哪個ClassLoader物件來對生成的代理物件進行載入

Interface物件的陣列,表示的是我將要給我需要代理的物件提供一組什麼介面,如果我提供了一組介面給它,那麼這個代理物件就

宣稱實現了該介面(多型),這樣我就能呼叫這組介面中的方法了

InvocationHandler物件,表示的是當我這個動態代理物件在呼叫方法的時候,會關聯到哪一個InvocationHandler物件上

------------------------------------------------------------------------------------------------------------------------------------

每一個動態代理類都必須要實現InvocationHandler這個介面,並且每個代理類的例項都關聯到了一個handler,當我們通過代理物件

呼叫一個方法的時候,這個方法的呼叫就會被轉發為由InvocationHandler這個介面的invoke 方法來進行呼叫。

InvocationHandler介面中invoke方法的三個引數:

proxy:代表動態代理物件

method:代表正在執行的方法

args:代表呼叫目標方法時傳入的實參

------------------------------------------------------------------------------------------------------------------------------------

Proxy.newProxyInstance

建立的代理物件是在jvm執行時動態生成的一個物件,它並不是我們的InvocationHandler型別,也不是我們定義的那組介面的型別,

而是在執行是動態生成的一個物件,並且命名方式都是這樣的形式,以$開頭,proxy為中,最後一個數字表示物件的標號。

System.out.println(u.getClass().getName());

------------------------------------------------------------------------------------------------------------------------------------

package cn.itcast_06;

/*
 * 使用者操作介面
 */
public interface UserDao {
	
	public abstract void add();

	public abstract void delete();

	public abstract void update();

	public abstract void find();
}
package cn.itcast_06;

public class UserDaoImpl implements UserDao {

	@Override
	public void add() {
		System.out.println("新增功能");
	}

	@Override
	public void delete() {
		System.out.println("刪除功能");
	}

	@Override
	public void update() {
		System.out.println("修改功能");
	}

	@Override
	public void find() {
		System.out.println("查詢功能");
	}

}
package cn.itcast_06;

public interface StudentDao {
	
	public abstract void login();

	public abstract void regist();
}
package cn.itcast_06;

public class StudentDaoImpl implements StudentDao {

	@Override
	public void login() {
		System.out.println("登入功能");
	}

	@Override
	public void regist() {
		System.out.println("註冊功能");
	}

}
package cn.itcast_06;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {
	
	private Object target; // 目標物件

	public MyInvocationHandler(Object target) {
		this.target = target;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("許可權校驗");
		Object result = method.invoke(target, args);
		System.out.println("日誌記錄");
		return result; // 返回的是代理物件
	}
}
package cn.itcast_06;

import java.lang.reflect.Proxy;

public class Test {
	public static void main(String[] args) {
		UserDao ud = new UserDaoImpl();
		ud.add();
		ud.delete();
		ud.update();
		ud.find();
		System.out.println("-----------");
		
		// 我們要建立一個動態代理物件
		// Proxy類中有一個方法可以建立動態代理物件
		// public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
		// 我準備對ud物件做一個代理物件,想對誰做代理,就把誰傳過來
		MyInvocationHandler handler = new MyInvocationHandler(ud);
		UserDao proxy = (UserDao) Proxy.newProxyInstance(ud.getClass().getClassLoader(), ud.getClass().getInterfaces(), handler);
		proxy.add();
		proxy.delete();
		proxy.update();
		proxy.find();
		System.out.println("-----------");

		StudentDao sd = new StudentDaoImpl();
		MyInvocationHandler handler2 = new MyInvocationHandler(sd);
		StudentDao proxy2 = (StudentDao) Proxy.newProxyInstance(sd.getClass().getClassLoader(), sd.getClass().getInterfaces(), handler2);
		proxy2.login();
		proxy2.regist();
		/*
		 許可權校驗
		 登入功能
		 日誌記錄
		 許可權校驗
		 註冊功能
		 日誌記錄
		*/
	}
}

相關文章