JDK动态代理

JDK动态代理

JDK提供的动态代理。Java中提供了一个动态代理类Proxy,proxy提供了一个创建代理对象的静态方法(newProxyInstance方法)来获取代理对象

01 代码

1> 卖票接口
/**
 * 卖票接口
 * @author : lyn
 */
public interface SellTickets {

    /**
     * 卖票
     */
    void sell();
}
2> 火车站
/**
 * 火车站
 * @author : lyn
 */
public class TrainStation implements SellTickets {

    @Override
    public void sell() {
        System.out.println("火车站卖票!");
    }
}
3> 代理工厂

ProxyFactory不是代理模式中所说的代理类,代理类是程序在运行过程中动态的再内存中生成的类

旧版本

public class ProxyFactory {
    private TrainStation trainStation = new TrainStation();

    public SellTickets getProxyObject() {

        SellTickets proxyObject = (SellTickets) Proxy.newProxyInstance(trainStation.getClass().getClassLoader(),
                trainStation.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("代理点收取一定的费用!JDK动态代理的方式");
                        Object result = method.invoke(trainStation, args);
                        return result;
                    }
                });
        return proxyObject;
    }
}

新版本

import java.lang.reflect.Proxy;

/**
 * 代理工厂
 * @author : lyn
 */
public class ProxyFactory {
    private TrainStation trainStation = new TrainStation();

    public SellTickets getProxyObject() {
        final String sell = "sell";
        return (SellTickets) Proxy.newProxyInstance(trainStation.getClass().getClassLoader(),
                trainStation.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    if (method.getName().equals(sell)) {
                        System.out.println("代理点收取一定的费用,JDK动态代理方式");
                    }
                    return method.invoke(trainStation, args);
                });

    }
}
4> 测试类
/**
 * 测试类
 * @author : lyn
 */
public class ProxyClient {
    public static void main(String[] args) {
        SellTickets proxyObject = new ProxyFactory().getProxyObject();
        proxyObject.sell();
    }
}
ps:

newProxyInstance()方法参数说明

ClassLoader loader : 类加载器,用于加载代理类,使用真实对象的类加载器即可

Class<?>[] interfaces : 真实对象所实现的接口,代理模式真实对象和代理对象实现相同的接口

InvocationHandler h : 代理对象的调用处理程序

InvocationHandler中invoke方法参数说明:

proxy : 代理对象

method : 对应于在代理对象上调用的接口方法的 Method 实例

args : 代理对象调用接口方法时传递的实际参数

02 查看代理类结构

1> 截取的重要代码
//程序运行过程中动态生成的代理类
public final class $Proxy0 extends Proxy implements SellTickets {
    private static Method m3;

    public $Proxy0(InvocationHandler invocationHandler) {
        super(invocationHandler);
    }

    static {
        m3 = Class.forName("com.hjxr.test.jdkproxy.SellTickets").getMethod("sell", new Class[0]);
    }

    public final void sell() {
        this.h.invoke(this, m3, null);
    }
}

//Java提供的动态代理相关类
public class Proxy implements java.io.Serializable {
    protected InvocationHandler h;
     
    protected Proxy(InvocationHandler h) {
        this.h = h;
    }
}

可以看出$Proxy0 代理类实现了SellTickets接口

2> 执行流程
  1. 测试类中通过代理对象调用sell()方法

  2. 根据多态的特性,执行的是代理类总的sell()方法

  3. 代理类中的sell()方法中又调用了InvocationHandler接口的子实现对象的invoke方法

  4. invoke方法通过反射执行了真实对象所属类TrainStation的sell()方法

posted @ 2022-03-31 16:56  进击的小蔡鸟  阅读(28)  评论(0编辑  收藏  举报