美文网首页
Java--代理模式、动态代理

Java--代理模式、动态代理

作者: aruba | 来源:发表于2021-10-26 17:06 被阅读0次

    代理模式是很常见的一种设计模式,如AppCompatActivity兼容方案,Java中代理模式分为静态代理和动态代理,动态代理是JVM帮助我们实现的

    一、代理模式

    1.代理模式场景

    有一名员工A,他出于某些原因需要公司签字,老板和秘书都可以执行公司签字的职能,但是秘书没有直接签字的权力,真正签字的必须是老板,而员工并不能直接找老板签字,只能和秘书打交道。由此看出,秘书只是一个代理者,他和老板拥有相同的职能,但是最终执行职能的还是老板,是员工和老板中间的窗口


    2.将上面的场景转化为代码

    职能接口:

    package delegate;
    
    public interface Function {
        void sign();
    }
    
    

    老板:

    package delegate;
    
    class Boss implements Function {
        @Override
        public void sign() {
            System.out.println("老板开始签字");
        }
    }
    
    

    秘书:

    package delegate;
    
    public class Secretary implements Function {
        private final Boss boss;
    
        public Secretary() {
            this.boss = new Boss();
        }
    
        @Override
        public void sign() {
            System.out.println("秘书交由老板签名");
            boss.sign();
        }
    }
    
    

    员工:

    package delegate.other;
    
    
    import delegate.Secretary;
    
    public class Employee {
        public static void main(String[] args) {
            Secretary secretary = new Secretary();
    
            System.out.println("请求签名");
            secretary.sign();
        }
    }
    
    

    结果:
    请求签名
    秘书交由老板签名
    老板开始签字

    3.代理模式条件

    根据上面的代码,我们可以发现,代理模式有两个条件:

    • 代理类和被代理类必须有同一个父类或接口
    • 代理对象持有被代理对象

    二、虚代理

    kotlin中我们常常使用懒加载,只有在对象用到时,才实例化创建它,虚代理就是这种模式

    1.场景

    老板很忙,不一定一直都在公司,现在秘书也可以签名了,但是老板在的时候,还是优先老板签名。公司职能新增了开会,开会必须要等待老板在场


    2.代码

    职能接口:

    package delegate;
    
    public interface Function {
        void sign();
        void meeting();
    }
    
    

    老板:

    package delegate;
    
    class Boss implements Function {
        @Override
        public void sign() {
            System.out.println("老板开始签字");
        }
    
        @Override
        public void meeting() {
            System.out.println("老板开始开会");
        }
    }
    
    

    秘书:

    package delegate;
    
    public class Secretary implements Function {
        private volatile Boss boss;
    
        @Override
        public void sign() {
            if (boss != null) {
                System.out.println("秘书交由老板签名");
                boss.sign();
            } else {
                System.out.println("秘书开始签名");
            }
        }
    
        @Override
        public void meeting() {
            waitBoss();
            boss.meeting();
        }
    
        public void waitBoss() {
            if (boss == null) {
                synchronized (this) {
                    if (boss == null) {
                        System.out.println("等待老板回公司");
                        boss = new Boss();
                    }
                }
            }
        }
    }
    
    

    员工:

    package delegate.other;
    
    
    import delegate.Secretary;
    
    public class Employee {
        public static void main(String[] args) {
            Secretary secretary = new Secretary();
    
            System.out.println("请求签名");
            secretary.sign();
    
            System.out.println("\n请求开会");
            secretary.meeting();
    
            System.out.println("\n请求签名");
            secretary.sign();
        }
    }
    
    

    结果:
    请求签名
    秘书开始签名

    请求开会
    等待老板回公司
    老板开始开会

    请求签名
    秘书交由老板签名
    老板开始签字

    三、保护代理

    保护代理在对象访问时进行权限检查

    1.场景

    老板的老婆可以问公司的效益,但员工不能问


    2.代码

    职能接口:

    package delegate;
    
    public interface Function {
        void sign();
        void meeting();
        void report(String who);
    }
    
    

    老板:

    package delegate;
    
    class Boss implements Function {
        @Override
        public void sign() {
            System.out.println("老板开始签字");
        }
    
        @Override
        public void meeting() {
            System.out.println("老板开始开会");
        }
    
        @Override
        public void report(String who) {
            System.out.println("老板开始给" + who + "打报告");
        }
    }
    
    

    秘书:

    package delegate;
    
    public class Secretary implements Function {
        private volatile Boss boss;
    
        @Override
        public void sign() {
            if (boss != null) {
                System.out.println("秘书交由老板签名");
                boss.sign();
            } else {
                System.out.println("秘书开始签名");
            }
        }
    
        @Override
        public void meeting() {
            waitBoss();
            boss.meeting();
        }
    
        @Override
        public void report(String who) {
            if (who == null) return;
    
            if (who.equals("老婆")) {
                waitBoss();
                boss.report(who);
            } else {
                System.out.println(who + "被开除了");
            }
        }
    
        public void waitBoss() {
            if (boss == null) {
                synchronized (this) {
                    if (boss == null) {
                        System.out.println("等待老板回公司");
                        boss = new Boss();
                    }
                }
            }
        }
    }
    

    员工:

    package delegate.other;
    
    
    import delegate.Secretary;
    
    public class Employee {
        public static void main(String[] args) {
            Secretary secretary = new Secretary();
    
            System.out.println("老婆请求报告");
            secretary.report("老婆");
    
            System.out.println("\n张三请求报告");
            secretary.report("张三");
        }
    }
    
    

    结果:
    老婆请求报告
    等待老板回公司
    老板开始给老婆打报告

    张三请求报告
    张三被开除了

    四、动态代理

    以上我们都是使用了静态代理,每次接口新增方法,那么其实现类都需要改动,JVM提供了动态代理的方式

    1.创建动态代理Handler
    package dynamicdelegate;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class DynamicInvocationHandler implements InvocationHandler {
        private Function boss;
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getName().equals("report")) {
                if (args[0] == null) {
                    return null;
                }
                if (args[0].equals("老婆")) {
                    return method.invoke(boss, args);
                } else {
                    System.out.println(args[0] + "被开除了");
                    return null;
                }
            }
    
            return method.invoke(boss, args);
        }
    
        /**
         * 设置被代理对象
         *
         * @param boss
         */
        public void setTarget(Function boss) {
            this.boss = boss;
        }
    }
    
    

    员工:

    package dynamicdelegate.other;
    
    
    import dynamicdelegate.Boss;
    import dynamicdelegate.DynamicInvocationHandler;
    import dynamicdelegate.Function;
    
    import java.lang.reflect.Proxy;
    
    public class Employee {
        public static void main(String[] args) {
            DynamicInvocationHandler handler = new DynamicInvocationHandler();
            Boss boss = new Boss();
            handler.setTarget(boss);
    
            Function proxy = (Function) Proxy.newProxyInstance(
                    boss.getClass().getClassLoader(),
                    boss.getClass().getInterfaces(),
                    handler);
    
            proxy.report("老婆");
            proxy.report("张三");
        }
    }
    
    

    结果:
    老板开始给老婆打报告
    张三被开除了

    2.动态代理原理

    动态代理实际上是生成class字节码,根据InvocationHandler的invoke方法中业务逻辑,在Boss类中每个方法都相应的添加了业务逻辑后,生成了一个新的类

    相关文章

      网友评论

          本文标题:Java--代理模式、动态代理

          本文链接:https://www.haomeiwen.com/subject/fabealtx.html