JDK动态代理
今天在学习MyBatis原理时,又看到熟人动态代理,于是萌生了深扒JDK动态代理源码的念头。参考了一些网上的资料也专门下载了JDK API
- JDK动态代理应用
- 使用Proxy.getProxyInstance生成代理类,实现对被代理类的增强方法
// 上一段copy的demo的代码
public class MyInvocationHandle implements InvocationHandler {
private Object target;
public MyInvocationHandle(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行MyInvocationHandle中的invoke方法");
System.out.print(method.getName());
Object res = null;
System.out.println("我是增强方法before");
res = method.invoke(target, args);
System.out.println("我是增强方法after");
return res;
}
}
public interface SomeService {
void doSome();
void doOther();
}
public class SomeServiceImp implements SomeService{
@Override
public void doSome() {
System.out.println("执行doSome方法");
}
@Override
public void doOther() {
System.out.println("执行doOther方法");
}
}
public class MyApp {
public static void main(String[] args) {
SomeService service = new SomeServiceImp();
MyInvocationHandle invocation = new MyInvocationHandle(service);
//生成代理增强类
SomeService proxy = (SomeService)
Proxy.newProxyInstance(service.getClass().getClassLoader(), service.getClass().getInterfaces(), invocation);
proxy.doOther();
proxy.doSome();
}
}
//运行结果
执行MyInvocationHandle中的invoke方法
toString我是增强方法before
我是增强方法after
执行MyInvocationHandle中的invoke方法
doOther我是增强方法before
执行doOther方法
我是增强方法after
执行MyInvocationHandle中的invoke方法
doSome我是增强方法before
执行doSome方法
我是增强方法after
- 代理类生成原理
- 这里有一个问题,为什么Proxy.newProxyInstance能生成一个SomeService的增强类,又为什么可以使用强制类型转换?
Class<?> cl = getProxyClass0(loader, intfs);
// 从源码不难看出生成代理类对象的是上面这一行,
//百度了一通拿到了$Proxy0类
public final class $Proxy0 extends Proxy implements SomeService {
private static Method m1;
private static Method m4;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(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 doOther() throws {
try {
super.h.invoke(this, m4, (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 void doSome() throws {
try {
super.h.invoke(this, m3, (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"));
m4 = Class.forName("SomeService").getMethod("doOther");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("SomeService").getMethod("doSome");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
- 从上面的Proxy0对象不难看出,这个类继承了Proxy类,实现了SomeService接口,就解释了为什么获取到的对象为什么可以强转为SomeService
- 并且增强类中实现的方法实际代码都是调用的全局变量invocationHandler的invoke方法。
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
/**
Proxy0的构造方法接收了一个InvocationHandler类
对应前文newProxyInstance方法由反射类构造方法对象构建对象实例方法
cons.newInstance(new Object[]{h})
**/
- 到这里还是没有解释清楚JVM是如何生成的增强类对象的,继续尝试深挖一下
/**
* Generate a proxy class. Must call the checkProxyAccess method
* to perform permission checks before calling this.
*/
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
}
点了半天,愣是啥都没看懂,还是JVM相关知识储备不够,以后有机会再琢磨
锻炼一下自己的书写能力,可能文章不够优秀,大家见笑了。
参考文章:
https://blog.youkuaiyun.com/flyfelu/article/details/118354250
还有好多大佬的文章忘记记下来了