代理模式--动态代理--jdk代理

2023-11-15

动态代理

jdk代理--基于接口代理

cglib--基于类代理

javassist --基于字节码

一个jdk动态代理类代理的是一个接口,一般归属于一个业务。在不改动源代码的同时可以很方便的低成本的进行加工附属改造。

jdk代理主要是通过java.lang.reflect 包中的 Proxy类 和 InvacationHandler接口,实现的。首先看下这两个类的源码。

InvacationHandler interface

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

只有一个invoke 方法。这个方法是处理代理实例并返回结果。在里面要用反射方法调用,method.invoke(Object obj ,Object[] args) 第一个参数就是要代理的接口类。第二个就是对应方法有关的参数。

回到源代码,第一个参数理论上就是要代理的对象,但是实际上并没有用到,第二个就是接口中对应的方法,第三个就是对应的参数。

其次看Proxy类

里面包含着一个重要也是常用的方法

    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

获得一个对应代理类的实例。通常要用这个方法动态的获得代理实例。

使用jdk代理的步骤

1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法
2.创建被代理的类以及接口
3.通过Proxy的静态方法
newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)创建一个代理
4.通过代理调用方法
实现代码:

真实角色(要被代理的对象):

package com.heaboy.proxyExcise.JDkProxy;

/**
 * @Author:XK
 * @Date: Created in 11:23 2022/2/19
 * @Description:
 **/
public class Host implements Rent {

    @Override
    public void rent() {
        System.out.println("房东出租房子");
    }

    @Override
    public void run() {
        System.out.println("房东跑了");
    }
}

抽象角色(要被代理的接口)

package com.heaboy.proxyExcise.JDkProxy;

/**
 * @Author:XK
 * @Date: Created in 11:20 2022/2/19
 * @Description:
 **/
public interface Rent {
    public void rent();
    public void run();
}

继承InvacationHanler并动态生成代理对象的角色

package com.heaboy.proxyExcise.JDkProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Author:XK
 * @Date: Created in 15:45 2022/2/19
 * @Description:
 **/
public class RentProxy implements InvocationHandler {

    private Rent target;

    public  RentProxy(Rent target) {
        this.target = target;
    }

    //动态生成代理对象
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }

    //处理实例的方法,并且加以附属操作
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        Object result=method.invoke(target,args);
        fare();
        return result;
    }
    public void seeHouse(){
        System.out.println("中介带你去看房");
    }
    public void fare(){
        System.out.println("中介带你收费");
    }
}

客户角色;调用代理

package com.heaboy.proxyExcise.JDkProxy;
/**
 * @Author:XK
 * @Date: Created in 15:52 2022/2/19
 * @Description:
 **/
public class client {
    public static void main(String[] args) {
        Host host = new Host();

        RentProxy rentProxy = new RentProxy(host);

        Rent proxy = (Rent)rentProxy.getProxy();

        //proxy.rent();

        proxy.run();
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

代理模式--动态代理--jdk代理 的相关文章

随机推荐

  • transformer位置编码最详细的解析

    位置编码positional encoding 1 位置编码是什么 为什么需要它 2 transformer提出的位置编码方法 3 直觉 4 其他细节 5 相对位置 6 常见问题解答 1 位置编码是什么 为什么需要它 位置和词语的顺序是任何
  • STL——set容器、map容器

    初识STL set容器 multiset容器 set容器 构造和赋值 set容器 大小和交换 set容器 插入和删除 set容器的查找和统计 set和multiset的区别 set的相关操作源码 multiset的相关操作源码 pair使用
  • Acwing算法基础课知识点

    知识点基础算法 代码模板链接 常用代码模板1 基础算法 排序 二分 高精度 前缀和与差分 双指针算法 位运算 离散化 区间合并 数据结构 代码模板链接 常用代码模板2 数据结构 链表与邻接表 树与图的存储 栈与队列 单调队列 单调栈 kmp
  • Android插件化的探索

    简介 对于App而言 所谓的插件化 个人的理解就是把一个完整的App拆分成宿主和插件两大部分 我们在宿主app运行时可以动态的载入或者替换插件的部分 插件不仅是对宿主功能的扩展而且还能减小宿主的负担 所谓的宿主就是运行的app 插件即宿主运
  • 几种本地存储方式

    浏览器本地存储的容器 1 cookie 2 sessionStorage 3 localStorage cookie cookie 浏览器早期存储数据容器 主要用于 存放用户名和密码 特点 容量小 4kb 操作繁琐 name zs pass
  • android studio安装automotive模拟器

    添加源 打开android studio的SDK Manager 选择SDK Update Sites选项卡 点击Add 弹出地址设置界面 添加polestar2 sys img Name填写 Polestar 2 System Image
  • RabbitMQ如何保证消息的顺序性【重点】

    1 1 保证顺序性的意义 消息队列中的若干消息如果是对同一个数据进行操作 这些操作具有前后的关系 必须要按前后的顺序执行 否则就会造成数据异常 举例 比如通过mysql binlog进行两个数据库的数据同步 由于对数据库的数据操作是具有顺序
  • SQLi LABS Less-12 联合注入+报错注入

    第十二关是双引号 括号的字符型注入 推荐使用联合注入 报错注入 方式一 联合注入 参考文章 联合注入使用详解 原理 步骤 实战教程 第一步 判断注入类型 用户名输入 a or 1 a 密码随便输入 1 页面正常显示 用户名输入 a or 0
  • 【C++】crypto++加密库简单使用

    crypto 加密库简单使用 目录 crypto 密码学库简单使用 一 简介 二 配置 三 使用示例 1 CRC32校验 2 Base64编码 3 Blake2b 4 AES 5 RSA 一 简介 crypto 是一个免费开源 公共领域 的
  • 功能测试之单元测试

    功能测试之单元测试 单元测试 理论 实例 单元测试 理论 简介 1 单元测试的基本概念 2 单元测试的策略 3 单元测试的步骤 4 Junit测试简单Java程序 1 单元测试概念 什么是单元测试 单元测试是一种验证行为 是指对软件中的最小
  • 第1章 多线程概述

    学习多线程之前 我们先要了解几个关于多线程有关的概念 A 进程 进程指正在运行的程序 确切的来说 当一个程序进入内存运行 即变成一个进程 进程是处于运行过程中的程序 并且具有一定独立功能 B 线程 线程是进程中的一个执行单元 负责当前进程中
  • Java经典面试题详解:springframework框架

    一面 1 自我介绍和项目 2 Java的内存分区 3 Java对象的回收方式 回收算法 4 CMS和G1了解么 CMS解决什么问题 说一下回收的过程 5 CMS回收停顿了几次 为什么要停顿两次 6 Java栈什么时候会发生内存溢出 Java
  • unity3d人物碰撞提示文字

    设置碰撞体 例如cube 将脚本挂载在物体上 碰撞显示text using System Collections using System Collections Generic using UnityEngine using Unity
  • 深度学习环境配置:2080Ti+Ubuntu16.04+CUDA10+cuDNN7.3+TensorFlow-gpu1.12

    目录 第一步 系统安装 Ubuntu16 04 第二步 连接校园网 第三步 cuda10 0 cudnn7 3安装
  • ES6 语法之 Iterator

    一 概念 Iterator 遍历器 为不同的数据类型提供统一的访问机制 只要部署了 Iterator 接口 原型上有 Symbol iterator 方法 就可以完成遍历操作 遍历操作主要通过 for of 完成 let arr 1 2 3
  • 【SQL基础】SQL查询语句实例

    参考自 https www w3school com cn sql index asp 下面举实例 员工表 部门表 薪资等级表 附上sql语句 薪资等级表SALGRADE 部门表DEPT 员工表EMP CREATE TABLE DEPT D
  • Python 安装Python-Jenkins 报错No matching distribution found for python-jenkins

    1 报错情况 报错原因 找不到与python jenkins匹配的分布 pip 安装使用的是外国源镜像 导致获取超时 安装失败 获取不到新版本 解决办法 切换至 pip 源到国内镜像 2 切换pip源的方法 可以直接通过Pycharm 设置
  • Windows Server 2016搭建文件服务器

    1 进入系统在服务器管理器仪表盘中添加角色和功能 2 下一步 3 继续下一步 4 下一步 5 勾选Web服务器 IIS 6 添加功能 7 下一步 8 下一步 9 下一步 10 角色服务没有特殊要求 保持默认 下一步 我这里多选了IP和域限制
  • 2020年4月蓝桥杯第二次模拟赛解题报告(本科组)Java语言描述__2021/3/21

    3 单词重排 问题描述 将LANQIAO中的字母重新排列 可以得到不同的单词 如LANQIAO AAILNOQ等 注意这7个字母都要被用上 单词不一定有具体的英文意义 请问 总共能排列如多少个不同的单词 答案提交 这是一道结果填空的题 你只
  • 代理模式--动态代理--jdk代理

    动态代理 jdk代理 基于接口代理 cglib 基于类代理 javassist 基于字节码 一个jdk动态代理类代理的是一个接口 一般归属于一个业务 在不改动源代码的同时可以很方便的低成本的进行加工附属改造 jdk代理主要是通过java l