代理设计模式之静态代理与动态代理

本文对比了静态代理和动态代理的区别,重点介绍了动态代理的实现原理及其灵活性优势。通过示例代码展示了如何使用Java反射机制创建动态代理类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

静态代理

静态代理只能服务于一种类型的对象,不利于业务的扩展

    package com.tskpcp.proxy;
    /**
    *业务层接口,定义个save方法
    */
    interface UserSerivce{
        public void saveUser();
    }

    /**
    *代理类
    */

    class UserServiceProxy implements UserService{
            private UserService userService;
            public UserServiceProxy(UserServiec userService){
                super();
                this.userService=userService;
            }
            public void open(){
                System.out.println("1:打开");
            }
            public void close(){
                System.out.println("2:关闭");
            }
            @Override
            public void saveUser(){
                this.open();
                userService.saveUser();
                this.close();
            }
    }
    /**
    *业务层实现类,实现save方法
    */
    class UserServiceImpl implements UserService{
        @Override
        public void saveUser(){
            System.out.println("保存用户信息");
        }
    }
    /**
    *测试类
    */
    public class TestProxy{
        public static void main(String[] args){
            UserService userService=new UserServiceProxy(new UserServiceImpl());
            userService.saveUser();
        }
    }
动态代理

如果要实现动态代理,那么你要编写的那个代理类就需要实现一个InvocationHandle接口.这个接口所在位置是java.lang.reflect.InvocationHandler.看到reflect我们就能知道,动态代理肯定是通过反射来实现的了,这个接口中有一个方法:
Object invoke(Object proxy, Method method, Object[] args) :在代理实例上处理方法调用并返回结果。
invoke方法其实是反射里边的一个方法,在这个方法中有三个参数:

  • Ojbect proxy:表示需要代理的对象
  • Method method:表示要操作的方法
  • Object[] args:method方法所需要传入的参数(可能没有为,null.也可能有多个)
      
      如果要想让代理设计真正可用,我们还必须有一个代理类对象产生,这有用到了另一个类:java.lang.reflect.Proxy.
      
    Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
    在这个类下面,我们找到了这样一个方法:
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException

  该方法返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序.方法中有三个参数:
   参数:
     loader - 定义代理类的类加载器
     interfaces - 代理类要实现的接口列表
     h - 指派方法调用的调用处理程序
   返回:
    一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口

    package com.tskpcp.proxy;
    /**
    *业务层接口,定义个save方法
    */
    interface UserSerivce{
        public void saveUser();
    }

    /**
    *代理类
    */

    class UserServiceProxy implements UserService{
            private UserService userService;
            public UserServiceProxy(UserServiec userService){
                super();
                this.userService=userService;
            }
            public void open(){
                System.out.println("1:打开");
            }
            public void close(){
                System.out.println("2:关闭");
            }
            @Override
            public void saveUser(){
                this.open();
                userService.saveUser();
                this.close();
            }
    }
    /**
    *动态代理类
    */
    class ServiceProxy implements InvocationHandler{
        private Object target=null;//保存真实业务对象
        /**
         * 返回动态代理类的对象,这样用户才可以利用代理类对象去操作真实对象
         * @param obj  包含有真实业务实现的对象
         * @return   返回代理对象
         */
        public Object getProxy(Object obj) {
            this.target=obj;//保存真实业务对象
            return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
                .getClass().getInterfaces(), this);
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
            Object result=method.invoke(target, args);//通过反射调用真实业务对象的业务方法,并且返回
            return result;
        }
    }
    /**
    *业务层实现类,实现save方法
    */
    class UserServiceImpl implements UserService{
        @Override
        public void saveUser(){
            System.out.println("保存用户信息");
        }
    }
    /**
    *测试类
    */
    public class TestProxy{
        public static void main(String[] args){
              UserService service=(UserService) new ServiceProxy().getProxy();
            service.saveUser();
        }
    }

动态代理和静态代理相比较,最大的好处就是接口中声明的所有的方法都被转移到一个集中的方法中去处理,就是invocke()方法.这样在接口中声明的方法比较多的情况下我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。
动态代理只能代理接口,代理类都需要实现InvocationHandler类,实现invoke方法。该invoke方法就是调用被代理接口的所有方法时需要调用的,该invoke方法的返回值是被代理接口的一个实现类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tskpcp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值