jdk动态代理

Java通过Proxy类实现的动态代理,使用上是比较简单的,但是内部实现比较复杂,这里是一个思路整理。

//1.真实对象
RealSubject realSubject = new RealSubject();
//handler对象
InvocationHandler handler = new DynamicSubject(realSubject);
//代理对象
Subject subject = (Subject) Proxy.newProxyInstance(classType.getClassLoader(),
                  realSubject.getClass().getInterfaces(),handler);
//代理对象执行方法                  
subject.work();

(主要是针对网友博客的理解,后续自己深入研究源码)

  • Proxy.newProxyInstance()方法,通过参数一(loader),参数二(真实类的接口数组),动态生成一个代理类$Proxy0,继承了Proxy,实现Subject(真实类的接口数组)。

public final class $Proxy0 extends Proxy implements Subject

  • 返回的代理对象subject是Subject接口类型的对象,该对象会有Subject接口中定义的work()方法,所以可以执行subject.work();

  • 类$Proxy的work方法实现如下,调用了我们在Proxy.newProxyInstance()方法的第三个参数(handler)的invoke方法,至此,即是调用了我们在实现InvocationHandler接口时,自己写的逻辑(h.invoke())。

super.h.invoke(this, m3, null);

  • 需要解释的是,$Proxy继承了Proxy,在调用Proxy.newProxyInstance()生成代理对象时,第三个参数会通过构造方法注入到代理对象中,从而会有上一步的h.invoke()执行。

代码:

public $Proxy0(InvocationHandler invocationhandler)
{
  super(invocationhandler);
}
========================================================
class Proxy
{
   protected InvocationHandler h;
   protected Proxy(InvocationHandler h) 
   {
         this.h = h;
   }
}
  • 动态生成$Proxy0,这块应该是源码研究的难点,后续自己可以挑战下。

代码展示

package com.kevinlsui.proxy;

public interface Subject {
    void work();
}

package com.kevinlsui.proxy;

public class RealSubject implements Subject{
    @Override
    public void work() {
        System.out.println("需要代理的方法...");

    }
}

package com.kevinlsui.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyHandler implements InvocationHandler{

    Object object ;
    public Object blind(Object obj){
        object = obj;
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("真正执行前,做一些处理,比如日志记录");
        Object obj = method.invoke(object, args);//实际执行的方法
        System.out.println("真正执行后,做一些处理");
        return obj;
    }

}

package com.kevinlsui.proxy;

public class ProxyTest {

    public static void main(String[] args) {
        RealSubject real = new RealSubject();//实际业务代码
        ProxyHandler handler = new ProxyHandler();//帮助类,把切片方法写在这个类中
        //代理类的对象,动态生成的代理类实现Subject接口,继承Proxy类,在生成对象时,把handler对象作为属性注入到代理对象
        Subject proxy = (Subject) handler.blind(real);
        //在代理对象执行对应方法时,实际是使用handler中的invoke方法,达到代理的效果。
        proxy.work();
    }

}
文章目录
  1. 1. 代码展示
|