白话解析动态代理设计模式

       动态代理就是对目标对象的方法做不同的代理实现,通俗点说就是在一个方法的执行前后加上对应的处理逻辑。例如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> T execute(Class<T> 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() 的运行流程:

扫描二维码关注公众号,回复: 10590719 查看本文章

 我们可以看到底层其实是创建一个代理对象,利用多态的方式,通过注入 InvocationHandler ,再采用反射的方式调用目标方法完成动态代理的实现

动态代理还有一种实现方式就是cglib,它是可以代理class类,java自带的只能代理 interface 接口,它的实现方式是采用继承的方式生成proxy代理类,其它流程基本一样

总结:

   平时我们更多的是做的crud之类的业务开发,习惯了编译运行的这种方式,而动态代理打破了这种思维定势,采用了运行时动态生成代理类加载运行的实现方式,我们可以多多理解这种思考方式

发布了25 篇原创文章 · 获赞 51 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Royal_lr/article/details/88883876