过几天我会分享spring AOP 的相关的代理的源码,为了让大家学好springAOP ,今天先分析jdk 的动态代理
1、首先创建一个接口和一个被代理的对象:
package com.nandao.proxy;
public interface People {
public void zdx();
}
package com.nandao.proxy;
/*
* 被代理实例
* */
public class Nandao implements People {
//1、nandao找到对象的业务场景
@Override
public void zdx() {
System.out.println("我在北京工作,没有时间找对象!");
}
//2、如果父母帮助南道找到了对象等等
}
然后创建一个增强类
package com.nandao.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/*
* 这个是一个增强类,实现InvocationHandler通用接口,是对目标对象的一个方法增强
* */
public class ParentInvocationHandler implements InvocationHandler {
private People people;
//持有people接口的引用
public ParentInvocationHandler(People people) {
this.people = people;
}
/*
* 找到对象以后,帮助南道操持婚礼等
* */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//帮他找到对象
before();
//这个invoke就会掉到被代理类中的method
method.invoke(people,args);
after();
return null;
}
/*
* 这个方法是南道在找到对象之前,父母帮助他做得事情
* */
private void before() {
System.out.println("我是南道父母,我需要帮助他找对象!!");
}
/*
* 找到对象之前,父母帮助他操持婚礼,带小孩
* */
private void after() {
System.out.println("我是南道的父母,我们需要帮助ta操持婚礼,帮他带小孩等等");
}
}
2、我们写一个测试方法
import sun.misc.ProxyGenerator;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Proxy;
public class TestProxy {
public static void main(String[] args) {
//proxy对象就是nandao这个对象的一个代理实例,nandao这个对象就是一个被代理,参数 ClassLoader 是类加载器
//new Class<?>[]{People.class} 这是接口数组
//new ParentInvocationHandler(new Nandao()) 通用接口实现类持有被代理对象的引用
People people = (People)Proxy.newProxyInstance(TestProxy.class.getClassLoader(),new Class<?>[]{People.class},
new ParentInvocationHandler(new Nandao()));
people.zdx();
//是否要将生成代理类的字节码.class文件保存到磁盘中,和项目文件在相同目录
createProxyClassFile();
}
public static void createProxyClassFile() {
//$Proxy0 执行后此class文件生成到项目得我根目录里,比如:D:\spring-source\$Proxy0.class,然后把这个文件直接拉到IDEA中就看到相应的java代码,这个类就是代理类。
byte[] $Proxy0s = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{People.class});
try {
FileOutputStream fileOutputStream = new FileOutputStream("$Proxy0.class");
fileOutputStream.write($Proxy0s);
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3、执行结果如下,并且生成代理类的class文件
执行过程查看people的类名
执行测试结果:
4、$Proxy0.class文件直接拉到IDEA中或者通过jd-gui.exe反编译后 如下
import com.enjoy.jack.test.People;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements People {
private static Method m1;
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 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);
}
}
//核心接口在这里,测试类TestProxy调用people.zdx();就是走的这里
public final void zdx() 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"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.enjoy.jack.test.People").getMethod("zdx");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
我们分析代理类中,我们需要被代理的方法zdx()的实现中,都是InvovationHandler中直接调用的invoke方法,如图证明:
5、我们追踪一下源码,点击Proxy.newProxyInstance 方法-->
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* 获取到代理类的class 对象
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* 使用指定的调用处理程序调用其构造函数
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//根据相应的参数获取有参构造函数
// private static final Class<?>[] constructorParams =
// {InvocationHandler.class };
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});//点击进入
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
参数进来
继续生成代理类的类名
获取有参构造函数;
下个环节开始调用
进入到这里
@CallerSensitive
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers);
}
}
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
//获取构造函数所需要的声明类
ConstructorAccessor ca = constructorAccessor; // read volatile
if (ca == null) {
ca = acquireConstructorAccessor();//点击进入获取 ca 声明类
}
@SuppressWarnings("unchecked")
T inst = (T) ca.newInstance(initargs);//创建单例实体
return inst;
}
点击 acquireConstructorAccessor()
private ConstructorAccessor acquireConstructorAccessor() {
// First check to see if one has been created yet, and take it
// if so.
ConstructorAccessor tmp = null;
if (root != null) tmp = root.getConstructorAccessor();
if (tmp != null) {
constructorAccessor = tmp;
} else {
// Otherwise fabricate one and propagate it up to the root
tmp = reflectionFactory.newConstructorAccessor(this);
setConstructorAccessor(tmp);
}
return tmp;
}
参数如图
5、流程总结如下:
$Proxy0此代理类在JVM内存里面动态生成,同我们的被代理实例一样实现相同的接口People。
今天jdk 动态代理解析完了,源码也简要分析了,大家应该也有了初步了解;下一篇,我们自己手写一个自己的动态代理实现业务流程(替换掉JDK的源码),让大家有更深入的理解。