動態代理原理
阿新 • • 發佈:2018-09-17
eth throwable 自動 結束 ins ati sub 方法 t對象 Spring底層用了哪些技術?(第一 工廠模式 第二 動態代理 )
// 第一個參數是: 類加載器
ClassLoader cl = App.class.getClassLoader();
// 第二個參數:字節碼對象數組
// 第二個參數是字節碼對象數組,表示動態代理創建出來的那個對象,自動實現了哪些接口
Class[] interfaces = new Class[]{ICalculator.class};
// 第三個參數:調用處理器
// 每當調用代理對象的方法時,都不是去執行真正的方法,而是統統進入 調用處理器 對象的invoke方法!
// 因為代理對象(所屬的類)已經實現了I接口,所以可以通過代理對象調用I接口中的所有方法:
class MyHandler implements InvocationHandler {
private Object target;
public MyHandler(Object target) {
this.target = target;
}
}
ICalculator proxy = (ICalculator) Proxy.newProxyInstance(cl, interfaces, new MyHandler(c));
package com.xaeduask.k_dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import org.junit.Test;
interface ICalculator {
public int add(int a, int b);
public int sub(int a, int b);
public int mul(int a, int b);
public int div(int a, int b);
public int mod(int a, int b);
}
class CalculatorImpl implements ICalculator {
public int add(int a, int b) {
int r = a + b;
return r;
}
public int sub(int a, int b) {
int r = a -b;
return r;
}
public int mul(int a, int b) {
int r = a * b;
return r;
}
public int div(int a, int b) {
int r = a / b;
return r;
}
public int mod(int a, int b) {
int r = a % b;
return r;
}
}
class MyHandler implements InvocationHandler {
private Object target;
public MyHandler(Object target) {
this.target = target;
}
//這裏又有3個參數,一會再解釋
// 第一個參數proxy,就是代理對象本身
// 第二個參數是method,本次正在調用中的代理對象的方法
// 第三個參數是args,表示本次代理對象調用的方法中的參數!
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("aaa");
System.out.println(method.getName()+"開始,參數是:" + Arrays.toString(args));
// 把method代表的方法,當做target對象的方法調用,
Object r = method.invoke(target, args);
System.out.println(method.getName()+"結束,結果是:" + r);
System.out.println("bbb");
return r; // 這裏的返回值,會返回到代理對象調用方法的點用處!
}
}
public class App {
@Test
public void test() throws Exception {
//創建一個目標對象(真實對象,不是代理對象)
//調用目標對象的任何方法,都調用的是真正的方法
ICalculator c = new CalculatorImpl();
// 創建代理對象,需要3個參數
// 第一個參數是: 類加載器
// 我們知道,構造器就是用來實例化對象的,其實在構造器的底層實例化對象時,會調用類加載器來實例化對象!
// 而使用動態代理也能實例化類的對象,勢必也少不了底層的那個類加載器!
ClassLoader cl = App.class.getClassLoader();
// 第二個參數:字節碼對象數組
// 第二個參數是字節碼對象數組,表示動態代理創建出來的那個對象,自動實現了哪些接口
Class[] interfaces = new Class[]{ICalculator.class};
// 第三個參數:調用處理器
// 每當調用代理對象的方法時,都不是去執行真正的方法,而是統統進入 調用處理器 對象的invoke方法!
// 因為代理對象(所屬的類)已經實現了I接口,所以可以通過代理對象調用I接口中的所有方法:
ICalculator proxy = (ICalculator) Proxy.newProxyInstance(cl, interfaces, new MyHandler(c));
int r = proxy.mod(-5, -2);
System.out.println("proxy:" + r);
}
}
動態代理原理