JDK動態代理的原理

JDK動態代理的原理

Object proxy = Proxy.newProxyInstance(ClassLoader loader, Class>[]interfaces, InvocationHandler h)

上面代碼會生成一個代理類對象proxy, 通過代理類就可以訪問到 realSubject的行為(method),具體怎麼訪問的,咱們接著說。

Proxy.class
// InvocationHandler是Proxy的屬性
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
......
/*
* Look up or generate the designated proxy class.
*/
Class> cl = getProxyClass0(loader, intfs);
......
}


/**
* A factory function that generates, defines and returns the proxy class given
* the ClassLoader and array of interfaces.
*/
private static final class ProxyClassFactory
implements BiFunction<classloader>[], Class>>
{
// 代理類的名稱前綴
private static final String proxyClassNamePrefix = "$Proxy";

@Override
public Class> apply(ClassLoader loader, Class>[] interfaces) {

......

/*
* 生成代理類.

*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);

return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);

......

}

}
/<classloader>

通過上面的源碼,我們可以看到:

  1. InvocationHandler是Proxy的屬性;
  2. 使用ProxyGenerator.generateProxyClass 可以生成代理類對象;

接下來我們通過實例來說明原理:

// 定義一個接口
public interface UserService {
void query();
}

// 接口的實現類
public class UserServiceImpl implements UserService{
@Override
public void query() {
System.out.println("Query user ...");
}
}

// InvocationHandler的實現
public class InvocationHandlerImpl implements InvocationHandler {
private UserService userService;
// 傳入真實的對象
public InvocationHandlerImpl(UserService userService) {
this.userService = userService;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before method invoke ...");
method.invoke(userService, null);
System.out.println("after method invoke ...");
return null;
}
}

// 通過代理類調用方法
public class JdkProxy {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
UserService us = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(),
new InvocationHandlerImpl(userService));
us.query();
}
}

上面代碼的執行結果:

before method invoke ...
Query user ...
after method invoke ...

還有個問題,就是上面的Proxy怎麼可以直接轉化為UserService,我們上面也說過,使用ProxyGenerator.generateProxyClass 可以生成代理類對象,那麼不妨我們生成代理類看一下源碼:

byte[] proxyClassFile = ProxyGenerator.generateProxyClass("UserServiceProxy", UserServiceImpl.class.getInterfaces());

把上面的字節保存到某個地方,生成UserServiceProxy.class 文件,然後反編譯這個文件,內容如下:

public final class UserServiceProxy extends Proxy implements UserService {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;

public UserServiceProxy(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 void query() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
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);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("com.proxy.sample.service.UserService").getMethod("query");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}

}
}

通過上面的代碼,我們可以很明瞭的看到:

  1. 代理類也實現了UserService接口;
  2. 代理類的所有方法調用都是通過 InvocationHandler.invoke 方法實現;

至此,JDK動態代理的原理已很清晰:

實際的調用鏈如下:

Proxy -> InvocationHandler -> RealSubject

而且Proxy含有handler屬性, InvocationHandler 含有subject屬性。


分享到:


相關文章: