靜態代理
- 創建一個接口,然后創建目標類實現該接口並且實現該接口中的抽象方法。之后再創建一個代理類,同時使其也實現這個接口。在代理類中持有一個目標對象的引用,而后在代理類方法中調用該對象的方法
動態代理
- 利用反射機制在運行時動態創建代理類
- JDK動態代理使用步驟
- 創建被代理的接口和類
- 創建InvocationHandler接口的實現類,重寫invoke方法,在invoke方法中實現代理邏輯
- 通過Proxy的靜態方法newProxyInstance( ClassLoaderloader, Class[] interfaces, InvocationHandler h)創建一個代理對象
- ClassLoaderloader 在哪個類里創建代理對象,就傳入該類的類加載器
- Class[] interfaces 代理類需要實現的接口
- InvocationHandler 代理邏輯對象
- 使用代理對象
實現原理
- 在Proxy.newProxyInstanceProxy方法內部,會調用Generator類的generateProxyClass()方法來生成代理類的字節碼,需要傳入參數:代理類需要實現的接口數組
- generateProxyClass()方法根據傳入的接口數組,動態的成Class文件,包括字段和方法
- JDK動態代理產生的代理類【繼承】Proxy類,java是單繼承,jdk動態代理是以實現接口的方式來執行的,並且【實現】接口數組中所有的接口
- 代理類只有唯一構造方法,參數是InvocationHandlerd對象;構造方法內部邏輯是,把InvocationHandler對象傳給父類Proxy類,也就是把InvocationHandler對象注入到Proxy類當中
- 在創建InvocationHandlerd對象的時候,我們可以選擇把目標對象注入到了InvocationHandler對象中(目標對象注入到InvocationHandler中,InvocationHandler對象注入到Proxy中)
- 在使用代理類時,執行相應方法時,代理對象調用的是父類(Proxy類)中InvocationHandler對象的invoke方法,也就是我們之前重寫的invoke方法:代理邏輯在此方法內
- 在InvocationHandler對象的invoke方法內,除了代理邏輯,還可以調用目標對象的方法(在創建InvocationHandler對象時,目標對象注入到了InvocationHandler中)
示例demo
- 目標接口
package Proxy;
public interface UserService {
public String getName(String userId);
}
- 目標實現類
package Proxy;
public class UserServiceImpl implements UserService{
@Override
public String getName(String userId) {
System.out.println("hello");
return userId;
}
}
- InvocationHandler實現類
package Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
class MyInvocationHandler implements InvocationHandler {
private Object object; //目標對象
//通過構造方法,把目標對象進入進來
public MyInvocationHandler(Object object){
this.object = object;
}
//代理邏輯
/***
* @param proxy 生成的代理對象
* @param method 代理對象中要執行的方法
* @param args 方法參數
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置代理邏輯");
Object object = method.invoke(this.object, args);//除了代理邏輯,還可以選擇調用目標對象的方法;this.object為注入的目標對象
System.out.println("后置代理邏輯");
return object;
}
}
- main方法測試
public class ZhuydProxy {
public static void main(String[] args) throws IOException {
UserService target = new UserServiceImpl(); //創建目標對象
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(target); //創建代理邏輯對象,目標對象注入到InvocationHandler中
UserService userService = (UserService) Proxy.newProxyInstance(ZhuydProxy.class.getClassLoader(),
target.getClass().getInterfaces(),
myInvocationHandler
);//通過JDK動態代理,創建代理對象
userService.getName("123");//運用代理對象
}
- 運行結果
前置代理邏輯
hello
后置代理邏輯
查看動態代理生成的字節碼文件到底張什么樣
- 通過ProxyGenerator.generateProxyClass( 生成的代理類名字 , 代理接口數組 ) 方法生成:代理字節碼文件
- 執行以下代碼
byte[] bytes = ProxyGenerator.generateProxyClass("UserService$proxy",new Class[]{UserService.class});
Path path = new File("C:\\UserService$proxy.class").toPath();
Files.write(path,bytes);
- 生成的字節碼文件
import Proxy.UserService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class UserService$proxy extends Proxy implements UserService {
private static Method m1;
private static Method m2;
private static Method m0;
private static Method m3;
public UserService$proxy(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String getName(String var1) throws {
try {
return (String)super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m3 = Class.forName("Proxy.UserService").getMethod("getName", Class.forName("java.lang.String"));
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
原創,如需轉載請標明出處