关于代理模式(Proxy模式)

本文介绍了代理模式的基本概念,涉及真实对象、代理对象和客户端的角色,以及在Java中如何使用Jav-lang-reflect-Proxy实现动态代理。重点讲解了动态代理如何通过InvocationHandler进行方法调用的前置和后置处理,以及其在远程调用、延迟加载和权限控制等场景的应用。
摘要由CSDN通过智能技术生成

代理模式是一种结构型设计模式,它允许通过代理对象控制对真实对象的访问。代理模式在软件开发中经常被使用,以实现额外的功能或控制对对象的访问

在代理模式中,有三个主要角色:

1.真实对象(Real Object):它是代理模式中实际执行业务逻辑的对象。代理模式的目标是控制对真实对象的访问,而真实对象是代理的实际工作对象。

2.代理对象(Proxy Object):它持有对真实对象的引用,并提供与真实对象相同的接口,以便在需要时可以代替真实对象。代理对象可以在调用真实对象之前或之后执行额外的操作,从而实现对真实对象的控制。

3.客户端(Client):它通过代理对象来访问真实对象,并执行相应的操作。客户端只需要知道代理对象的接口,而不需要直接访问真实对象。
代理模式的主要优点包括:

代理模式可以提供额外的功能,例如在访问真实对象之前或之后执行日志记录、权限检查、缓存等操作。

  • 代理模式可以实现对真实对象的保护,控制客户端对真实对象的直接访问。
  • 代理模式可以实现延迟加载(Lazy Loading),即在需要时才创建真实对象,从而提高系统的性能和资源利用率。

代理模式的一些常见应用场景包括:

  • 远程代理(Remote Proxy):用于在不同的地址空间中访问远程对象,例如远程方法调用(Remote Method Invocation)。
  • 虚拟代理(Virtual Proxy):用于延迟加载大对象,以减少系统启动时间和内存消耗。
  • 安全代理(Protection Proxy):用于控制对对象的访问权限,例如在访问敏感信息时进行身份验证。
  • 缓存代理(Caching Proxy):用于缓存对象的结果,以提高系统的性能。

这里介绍一下以基于使用Java java.lang.reflect.Proxy;的动态代理设计

Car类

public class Car implements Vehicle{

    @Override
    public void run() {
        System.out.println("Car is running");
    }
}

上层接口类

public interface Vehicle {
    void run();
}

代理类

    private Vehicle vehicle;//表示真正执行的对象,提供给目标使用

    public VehicleProxyProvider(Vehicle vehicle) {
        this.vehicle = vehicle;
    }

    public Vehicle getProxy() {
        /**
         *     public static Object newProxyInstance(ClassLoader loader,
         *                                           Class<?>[] interfaces,
         *                                           InvocationHandler h)
         * @return
         */
        //获取类加载器-》代理类的类加载器
        ClassLoader classLoader =
                vehicle.getClass().getClassLoader();
        // 2.获取接口类型数组, 为什么是接口信息,而不是方法,是因为我们都是走接口的.
        Class<?>[] interfaces =
                vehicle.getClass().getInterfaces();
        //创建InvocationHandler对象,InvocationHandler是接口不能直接创建
        //需要使用内部类
        // 3. 创 建 InvocationHandler 对 象 - 以 匿 名 内 部 类 的 方 式 方 式 来 获 取
        //这个对象有一个方法是 invoke 到时可以通过反射,动态调用目标对象的方
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws
                    Throwable {
                System.out.println("开始执行代理对象方法...");
                //method:是public abstract void com.klame.Aop1.Vehicle.run()
                Object result = method.invoke(vehicle, args);
                System.out.println("代理对象方法执行结束...");
                return result;
            }
        };
        //newProxyInstance可以返回一个代理对象,代理对象可以实现接口,也可以继承类
        //ClassLoader loader:类的加载器
        //Class<?>[] interfaces:代理对象实现的接口
        //InvocationHandler h:代理对象的方法被调用时,会触发执行h的invoke方法
        Vehicle proxy = (Vehicle) Proxy.newProxyInstance(classLoader, interfaces,
                invocationHandler);

        return  proxy;
    }

}

测试类

public class TestVehcle {
    @Test
    public void testVehicle() {
        Vehicle vehicle = new Car();
        VehicleProxyProvider vehicleProxyProvider =
                new VehicleProxyProvider(vehicle);
        Vehicle proxy = vehicleProxyProvider.getProxy();
        System.out.println("proxy 编译类型是 Vehicle");
        System.out.println("proxy 运行类型" + proxy.getClass());
        proxy.run();
        //执行的是代理对象的public Object invoke(Object proxy, Method method,
        // Object[] args)方法,不会执行Car的run方法。

    }
}
  1. proxy 运行类型是 com.sun.proxy.$Proxy0 该类型被转型成 Vehicle因此可以调用 Vehicle 的接口方法
  2. 当执行 run() 的时候会调用, 根据 Java 的动态绑定机制, 这时直接调用 Car
    的 run(),而是 proxy 对象的 invocationHandler 的 invoke 方法
  3. invoke 方法使用反射机制来调用 run()方法注意这个 run 方法也可以是
    Vehicle 的其它方法),这时就可以在调用 run()方法前,进行前置处理和后置处理
  4. 也就是说 proxy 的 target_vehicle 运行类型只要是实现了 Vehicle 接口 ,就可以去调用不同的方法, 是动态的,变化的,底层就是 使用反射完成的.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值