Java 動態代理底層原理是基于反射機制實現的,其中最重要的是 InvocationHandler 接口,它定義了一個 invoke() 方法,用于實現對代理類中各個方法的調用,在 invoke() 方法中,可以實現對真實角色的調用,并進行擴展,實現動態代理的效果。

Java動態代理是一種在運行時創建代理類的機制,動態代理可以在不修改源代碼的情況下,在運行時為某個接口動態生成實現類,并且可以攔截接口中的方法調用,從而實現一些特殊的功能。
Java 動態代理底層原理是基于反射機制實現的,其中最重要的是 InvocationHandler 接口,它定義了一個 invoke() 方法,用于實現對代理類中各個方法的調用,在 invoke() 方法中,可以實現對真實角色的調用,并進行擴展,實現動態代理的效果。
動態代理的實現步驟:
1. 創建一個實現 InvocationHandler 接口的類,它必須實現 invoke() 方法;
2. 創建被代理的真實對象;
3. 通過 Proxy 類的 newProxyInstance() 方法創建代理對象,它需要參數:
(1)ClassLoader:類加載器,它是用于加載代理對象字節碼的,和被代理對象使用相同的類加載器;
(2)Class[]:字節碼數組,它是用于讓代理對象和被代理對象有相同方法;
(3)InvocationHandler:它是調用處理器,執行代理對象的方法時,會觸發該對象的 invoke() 方法;
4. 通過代理對象調用目標方法,實際上會轉到 invoke() 方法中,在 invoke() 方法中,可以進行預處理、調用后處理等工作。
反射上一篇文章講過了,這里就是反射的一個應用,這個最常見的場景就是給代碼加日志,例如在執行某個函數前將請求體加入到日志中,執行后將結果加入到日志中。這樣可以在不改變原來代碼的基礎上來實現。接下來就使用上一篇反射的例子繼續擴展。
先寫一個Person的接口:
package ReflectTest;
public interface PersonInterface {
void printName();
void printAge();
}
寫他的實現:
package ReflectTest;
public class Person implements PersonInterface{
private String name = "xiaoming";
private String age = "12";
@Override
public void printName()
{
System.out.println(name);
}
@Override
public void printAge()
{
System.out.println(age);
}
}
然后寫動態代理類:
package ReflectTest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyHandler implements InvocationHandler {
private Object target;
public ProxyHandler(Object target) {
this.target = target;
}
public Object bind() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this);
}
@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 ReflectTest;
public class main {
public static void main(String[] args) {
ProxyHandler proxyHandler = new ProxyHandler(new Person());
PersonInterface person = (PersonInterface)proxyHandler.bind();
person.printName();
}
}
我們看看結果在執行函數前后執行了其他操作:
SpringAOP其實原理就類似這種。
