1. 程式人生 > >【Java基礎】【動態代理 一個動態代理的例子】

【Java基礎】【動態代理 一個動態代理的例子】

參考資料:

阿里雲大學MLDN高階開發課程

2016黑馬程式設計師JAVAEE Day25 基礎加強

動態代理是理解Spring AOP功能的一個重要概念

程式碼例子:

動態代理用於介面TargetInterface

實體類Target和代理類ProxyTest都實現了TargetInterface

1. TargetInterface.java

public interface TargetInterface {

	public void method1();
	public String method2();
	public int method3(int x);
}

2. Target中實現了TargetInterface的3個方法

public class Target implements TargetInterface {

	@Override
	public void method1() {
		System.out.println("method1 running...");
	}

	@Override
	public String method2() {
		System.out.println("method2 running...");
		return "method2";
	}

	@Override
	public int method3(int x) {
		return x;
	}

}

3. 實現動態代理類方式一:

需要用到3個包

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

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

import org.junit.Test;

public class ProxyTest {

	@Test
	public void test1(){
		//獲得動態的代理物件----在執行時 在記憶體中動態的為Target建立一個虛擬的代理物件
		//objProxy是代理物件 根據引數確定到底是誰的代理物件
		TargetInterface objProxy = (TargetInterface) Proxy.newProxyInstance(
				Target.class.getClassLoader(), //與目標物件相同的類載入器
				new Class[]{TargetInterface.class}, 
				new InvocationHandler() {
					//invoke 代表的是執行代理物件的方法
					@Override
					//method:代表目標物件的方法位元組碼物件
					//args:代表目標物件的響應的方法的引數
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("目標方法前的邏輯");
						//執行目標物件的方法
						Object invoke = method.invoke(new Target(), args);
						System.out.println("目標方法後的邏輯");
						return invoke;
					}
				}
			);
		
		objProxy.method1();
		String method2 = objProxy.method2();
		System.out.println(method2);
		
	}
	
}

4. 實現動態代理類方式二:

直接先建立實體類物件

final Target target = new Target();
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyTest2 {

	public static void main(String[] args) {
		
		final Target target = new Target();
		
		//動態建立代理物件
		
		TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(
				target.getClass().getClassLoader(), 
				target.getClass().getInterfaces(), 
				new InvocationHandler() {
					@Override
					//被執行幾次?------- 看代理物件呼叫方法幾次
					//代理物件呼叫介面相應方法 都是呼叫invoke
					/*
					 * proxy:是代理物件
					 * method:代表的是目標方法的位元組碼物件
					 * args:代表是呼叫目標方法時引數
					 */
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						//反射知識點
						Object invoke = method.invoke(target, args);//目標物件的相應方法
						//retrun返回的值給代理物件
						return invoke;
					}
				}
			);
		
		proxy.method1();//呼叫invoke---Method:目標物件的method1方法  args:null  返回值null
		String method2 = proxy.method2();//呼叫invoke---Method:目標物件的method2方法  args:null  返回值method2
		int method3 = proxy.method3(100);////呼叫invoke-----Method:目標物件的method3方法 args:Object[]{100}  返回值100
		
		System.out.println(method2);
		System.out.println(method3);
		
	}
	
}