前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java--代理模式、动态代理

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

作者头像
aruba
发布2021-12-06 17:37:02
2350
发布2021-12-06 17:37:02
举报
文章被收录于专栏:android技术
代理模式是很常见的一种设计模式,如AppCompatActivity兼容方案,Java中代理模式分为静态代理和动态代理,动态代理是JVM帮助我们实现的
一、代理模式
1.代理模式场景

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

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

职能接口:

代码语言:javascript
复制
package delegate;

public interface Function {
    void sign();
}

老板:

代码语言:javascript
复制
package delegate;

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

秘书:

代码语言:javascript
复制
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();
    }
}

员工:

代码语言:javascript
复制
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.代码

职能接口:

代码语言:javascript
复制
package delegate;

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

老板:

代码语言:javascript
复制
package delegate;

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

    @Override
    public void meeting() {
        System.out.println("老板开始开会");
    }
}

秘书:

代码语言:javascript
复制
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();
                }
            }
        }
    }
}

员工:

代码语言:javascript
复制
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.代码

职能接口:

代码语言:javascript
复制
package delegate;

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

老板:

代码语言:javascript
复制
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 + "打报告");
    }
}

秘书:

代码语言:javascript
复制
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();
                }
            }
        }
    }
}

员工:

代码语言:javascript
复制
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
代码语言:javascript
复制
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;
    }
}

员工:

代码语言:javascript
复制
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类中每个方法都相应的添加了业务逻辑后,生成了一个新的类

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/10/26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 代理模式是很常见的一种设计模式,如AppCompatActivity兼容方案,Java中代理模式分为静态代理和动态代理,动态代理是JVM帮助我们实现的
  • 一、代理模式
    • 1.代理模式场景
      • 2.将上面的场景转化为代码
        • 3.代理模式条件
        • 二、虚代理
          • 1.场景
            • 2.代码
            • 三、保护代理
              • 1.场景
                • 2.代码
                • 四、动态代理
                  • 1.创建动态代理Handler
                    • 2.动态代理原理
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档