代理模式之动态代理浅谈

134 阅读2分钟

「这是我参与2022首次更文挑战的第30天,活动详情查看:2022首次更文挑战」。

一、动态代理与静态代理

静态代理在使用的过程中,代理对象必须要实现接口的所有方法,为解决这种问题,JDK提供了动态代理,通过JDK提供的方法,在运行过程中动态的创建代理对象,所以动态代理也可以称为JDK代理。

二、动态代理的实现

public interface Shop002 {
    void sell();
}

商店,拥有售卖接口。

public class WholesaleShop002 implements Shop002 {
    @Override
    public void sell() {
        System.out.println("瓶酒售卖价格2元");
    }
}

批发商,实现了售卖接口。

public class ShopProxy002 {
    private final Shop002 target;

    public ShopProxy002(Shop002 target) {
        this.target = target;
    }

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), (proxy, method, args) -> {
            Object invoke = method.invoke(target, args);
            System.out.println("跑腿费2元");
            return invoke;
        });
    }

}

获取动态代理实体的对象,可以称为代理对象的工厂。此处是通过Proxy的newProxyInstance创建代理对象。

public class ShopTest002 {
    public static void main(String[] args) {
        Shop002 shop = new WholesaleShop002();
        ShopProxy002 proxy = new ShopProxy002(shop);
        Shop002 proxyInstance = (Shop002) proxy.getProxyInstance();
        proxyInstance.sell();
    }
}

可以看到,这里先使用ShoProxy002获取代理对象,代理对象是在运行过程中生成的,获取到代理对象后,调用sell方法。

image.png

三、总结

动态代理不需要实现接口的所有方法,动态代理对象在运行时创建,使用java.lang.reflect.Proxy类进行创建。代理对象不需要实现接口,但目标对象需要实现接口。 动态代理主要依据Proxy的静态方法newProxyInstance

image.png

可以看到,这个方法有3个参数,分别代表:

  1. ClassLoader loader:目标对象使用的类加载器。
  2. Class<?>[] interfaces:target对象使用的接口类型,使用泛型的方式确认类型。
  3. InvocationHandler h:事件处理,执行目标对象target的方法时,会触发事件处理器的方法,把当前执行的target的方法作为参数传入。