1. 程式人生 > >Java動態代理一個淺顯易懂的例子

Java動態代理一個淺顯易懂的例子

簡單用途,在不修改一個類的前提下,在該類的方法執行前或執行後加入一些特殊的處理,如日誌、事務等。

要點:

1、需要使用介面類

2、使用動態代理在方法呼叫時加入自己的處理

示例程式碼:

1、介面類

package proxy;

public interface Subject {
    public void rent();
    
    public void hello(String str);
}

2、實現類

package proxy;

public class RealSubject implements Subject {
	@Override
	public void rent() {
		System.out.println("I want to rent my house");
	}

	@Override
	public void hello(String str) {
		System.out.println("hello: " + str);
	}
}

3、動態代理類

package proxy;

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

public class DynamicProxy implements InvocationHandler {
	// 這個就是我們要代理的真實物件
	private Object subject;

	// 構造方法,給我們要代理的真實物件賦初值
	public DynamicProxy(Object subject) {
		this.subject = subject;
	}

	@Override
	public Object invoke(Object object, Method method, Object[] args) throws Throwable {

		System.out.println("\r\nMethod:" + method);
		
		// 在代理真實物件前我們可以新增一些自己的操作
		System.out.println("before invoke method " + method.getName()); 

		// 當代理物件呼叫真實物件的方法時,其會自動的跳轉到代理物件關聯的handler物件的invoke方法來進行呼叫
		method.invoke(subject, args);

		// 在代理真實物件後我們也可以新增一些自己的操作
		System.out.println("after invoke method " + method.getName());

		return null;
	}

}

4、應用類

package proxy;

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

public class Client {
	public static void main(String[] args) {
		// 我們要代理的真實物件
		Subject realSubject = new RealSubject();

		// 我們要代理哪個真實物件,就將該物件傳進去,最後是通過該真實物件來呼叫其方法的
		InvocationHandler handler = new DynamicProxy(realSubject);

		/*
		 * 通過Proxy的newProxyInstance方法來建立我們的代理物件,我們來看看其三個引數 第一個引數
		 * handler.getClass().getClassLoader()
		 * ,我們這裡使用handler這個類的ClassLoader物件來載入我們的代理物件
		 * 第二個引數realSubject.getClass().getInterfaces(),我們這裡為代理物件提供的介面是真實物件所實行的介面
		 * ,表示我要代理的是該真實物件,這樣我就能呼叫這組介面中的方法了 第三個引數handler, 我們這裡將這個代理物件關聯到了上方的
		 * InvocationHandler 這個物件上
		 */
		Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(),
				realSubject.getClass().getInterfaces(), handler);

		System.out.println(subject.getClass().getName());
		subject.rent();
		subject.hello("world");
	}
}

輸出結果:

com.sun.proxy.$Proxy0

Method:public abstract void proxy.Subject.rent()
before invoke method rent
I want to rent my house
after invoke method rent

Method:public abstract void proxy.Subject.hello(java.lang.String)
before invoke method hello
hello: world
after invoke method hello

參考: