最近本着不求甚解的态度重温了一下主流框架的源码,加上之前的笔记,所以趁热打铁的总结一下,学习框架或开发框架所必备的基础知识:
以上是对动态代理的简单介绍,对于AOP使用代理机制会在下一篇文章中进行详细介绍,本文主要将最基本的Java动态代理的实现
上面是动态代理的四个元素,下面一个一个介绍并实现过程。
任意定义一个接口,此接口就问要代理的接口,将需要在运行时动态干涉的方法定义在接口内
/**
* 代理的接口
*/
interface Study {
fun studyEnglish()
fun studyMath()
}
实现了被代理接口的类
/**
* 实现的代理类
*/
class StudyImp : Study {
override fun studyEnglish() {
System.out.println("-----学习英语-----")
}
override fun studyMath() {
System.out.println("-----学习数学-----")
}
}
如果把程序和方法的执行看成从上倒下的过程,所谓的切面就是在某个高度的截面,即运行到此处就会被切断,从而执行其他的部分,类似于中途嫁接的过程,他的使用只需实现系统的InvocationHandler接口
public class StudyInvocationHasndler implements InvocationHandler {
private Object object;
public StudyInvocationHasndler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("studyEnglish")) {
System.out.println("-----今天有外教-----");
}
if (method.getName().equals("studyMath")) {
System.out.println("-----今天外教没来-----");
}
return method.invoke(object, args);
}
}
实现了InvocationHandler接口重写了invoke(),见到这个方法名就应该知道这里用的时反射获取代理的信息(关于反射注解请看 Java 反射、注解),从方法中可以看出,当执行到这两个方法时会插入一条输出语句,然后再继续执行,是不是有一种横插已退的感觉,所以叫切面
fun main(args: Array) {
// 需要代理的类的接口,被代理类实现的每个接口都必须定义
val classes = arrayOf>(Study::class.java)
// 创建 AOP的Advice 传入业务执行的逻辑
val studyHandler = StudyInvocationHasndler(StudyImp())
//生成代理类的字节码加载器
val classLoader = StudyImp::class.java.classLoader
// 织入代码并生成代理类
val study: Study = Proxy.newProxyInstance(classLoader, classes, studyHandler) as Study
//调用方法
study.studyEnglish()
study.studyMath()
}
其实上面的过程很好理解,导致如下:
输出结果:
从运行结果上看,在每个方法执行前都会插入一句话,再执行本身的方法,就相当于代理人先执行,本人再执行,上面的四个元素中还有一个织入器并未介绍,之所以放到最后是因为这个类时系统生成的,最为代理实现的一个桥梁,下面看看生成的植入器:
// 修改系统的设置保存生成的代理类
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
2、运行程序后就会产生代理类:
3、查看代理类
public final class $Proxy0 extends Proxy implements Study { // 实现代理的接口
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m4;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws { // 带有InvocationHandler的构造函数
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 studyEnglish() throws { // 生成代理的方法
try {
super.h.invoke(this, m3, (Object[])null); // 调用实现的InvocationHandler中的invoke()方法
} 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 studyMath() throws {
try {
super.h.invoke(this, m4, (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.example.administrator.apiguide.aop.Study").getMethod("studyEnglish");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m4 = Class.forName("com.example.administrator.apiguide.aop.Study").getMethod("studyMath");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
方法重写了studyMath()、studyEnglish()、toString()、hashCode()方法,studyMath()、studyEnglish()为实现接口方法,在其中都调用了 super.h.invoke(this, m3, (Object[])null); 实际调用实现的InvocationHandler中的invoke()方法,从实现代码的切入;
private static final Class>[] constructorParams =
{ InvocationHandler.class };
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class>[] intfs = interfaces.clone();
/*
* 根据 ClassLoader 和 Class文件 获取代理的类
*/
Class> cl = getProxyClass0(loader, intfs); //利用反射获取代理类
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
// 获取带有InvocationHandler的构造函数
final Constructor> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) { // 判断类是否是私有的
cons.setAccessible(true); // 忽略私有
}
return cons.newInstance(new Object[]{h}); // 创建代理对象
} catch (IllegalAccessException|InstantiationException e) {
...
}
}
执行逻辑:
动态代理的到此结束了,想查看具体在框架中的使用实例可自行阅读Retrofit源码。