动态代理就是对目标对象的方法做不同的代理实现,通俗点说就是在一个方法的执行前后加上对应的处理逻辑。例如spring的事务处理,在插入一条数据的前面开启事务,插入完成后提交事务。
现在我们解析一下动态代理底层的执行方式,直接上代码:
public interface Parent {
public void create();
}
public class Sub implements Parent {
public void create() {
System.out.println("sub create");
}
}
public class Log {
public static void before(){
System.out.println("before");
}
public static void after(){
System.out.println("after");
}
}
public class ProxyHandler implements InvocationHandler {
public Object obj;
public ProxyHandler(Object obj) {
this.obj=obj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.before();
Object result=method.invoke(obj,args);
Log.after();
return result;
}
public static T execute(Class clazz,T t){
ClassLoader classLoader = clazz.getClassLoader();
ProxyHandler handler=new ProxyHandler(t);
Class>[] classes=new Class[]{clazz};
return (T) Proxy.newProxyInstance(classLoader,classes,handler);
}
}
public class Main {
public static void main(String[] args) throws Exception {
Parent p = new Sub();
Parent proxy = ProxyHandler.execute(Parent.class, p);
proxy.create();
}
}
我们定义了一个Parent 接口和它的实现类Sub. Log 是一个代理类,ProxyHandler是封装的一个通用代理处理器。
我们直接从 Proxy.newProxyInstance(classLoader,classes,handler) 这一段开始看起,底层 它首先是通过传入的类加载器将生成的class文件加载到jvm中, 然后创建了一个代理对象com.sun.proxy.$Proxy0,$Proxy0 的大致代码如下:
public class $Proxy0 implements Parent{
InvocationHandler h;
public $Proxy0(InvocationHandler h){
this.h=h;
}
@Override
public void create() {
try{
Method m=Parent.class.getMethod("create");
h.invoke(this,m,null);
}catch (Throwable e){
e.printStackTrace();
}
}
}
代理类其实就是 实现了目标类的接口,然后再方法里面调用 InvocationHandler 的实现类,最后在 invoke 方法中实现对目标方法的代理。
invoke(Object proxy, Method method, Object[] args) 方法中的三个参数:
proxy : 动态生成的代理类,即 $Proxy0
method : 目标对象的方法,即 create
args : 目标方法的参数值
最后我们看一下 proxy.create() 的运行流程:
我们可以看到底层其实是创建一个代理对象,利用多态的方式,通过注入 InvocationHandler ,再采用反射的方式调用目标方法完成动态代理的实现
动态代理还有一种实现方式就是cglib,它是可以代理class类,java自带的只能代理 interface 接口,它的实现方式是采用继承的方式生成proxy代理类,其它流程基本一样
总结:
平时我们更多的是做的crud之类的业务开发,习惯了编译运行的这种方式,而动态代理打破了这种思维定势,采用了运行时动态生成代理类加载运行的实现方式,我们可以多多理解这种思考方式