第十四章 代理模式


文章目录

  • 前言
  • 一、静态代理
    • 完整代码
    • 接口 ITeacherDao (代理类和被代理类都需要实现这个接口)
    • 被代理类 TeacherDao
    • 代理类 TeacherDaoProxy
    • 测试类 Client
  • 二、JDK动态代理
    • 完整代码
    • 接口 ITeacher
    • 实现类TeacherDao
    • 代理工厂 ProxyFacyory
    • client 测试
  • 三、Cglib代理
    • 完整代码
    • 被代理对象
    • 代理工厂
    • 测试
  • 四、代理模式(Proxy)的变体


前言

在这里插入图片描述
在这里插入图片描述


一、静态代理

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

完整代码

接口 ITeacherDao (代理类和被代理类都需要实现这个接口)

package tanchishell.SJMS.staticproxy;

//接口
public interface ITeacherDao {
    void teach(); // 授课的方法
}

被代理类 TeacherDao

//教师类
public class TeacherDao implements ITeacherDao{

    @Override
    public void teach() {
        System.out.println(" 老师授课中 。。。。。");
    }
}

代理类 TeacherDaoProxy


//代理对象,静态代理
public class TeacherDaoProxy implements ITeacherDao {

    private ITeacherDao target; // 目标对象,通过接口来聚合

    //构造器
    public TeacherDaoProxy(ITeacherDao target) {
        this.target = target;
    }

    @Override
    public void teach() {
        System.out.println("开始代理 完成某些操作。。。。。 ");//方法
        target.teach();
        System.out.println("提交。。。。。");//方法

    }
}

测试类 Client

package tanchishell.SJMS.staticproxy;

public class Client {

    public static void main(String[] args) {

        //创建目标对象(被代理对象)
        TeacherDao teacherDao = new TeacherDao();
        //创建代理对象, 同时将被代理对象传递给代理对象
        TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);
        //通过代理对象,调用到被代理对象的方法
        //即:执行的是代理对象的方法,代理对象再去调用目标对象的方法
        teacherDaoProxy.teach();
    }
}

输出

开始代理 完成某些操作。。。。。 
 老师授课中 。。。。。
提交。。。。。

在这里插入图片描述

二、JDK动态代理

在这里插入图片描述
在这里插入图片描述

完整代码

接口 ITeacher

package tanchishell.SJMS.JDKstaticproxy;

public interface ITeacherDao {

    void teach(); // 授课方法
    void sayHello(String name);

}

实现类TeacherDao

package tanchishell.SJMS.JDKstaticproxy;

public class TeacherDao implements ITeacherDao {
    @Override
    public void teach(){

        System.out.println(" 老师授课中.... ");
    }

    @Override
    public void sayHello(String name) {

        System.out.println("hello " + name);
    }

}

代理工厂 ProxyFacyory

package tanchishell.SJMS.JDKstaticproxy;

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

public class ProxyFactory {

    //维护一个目标对象 , Object
    private Object target;

    //构造器 , 对 target 进行初始化
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //给目标对象 生成一个代理对象
    public Object getProxyInstance() {

//说明
/*
* public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
//1. ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定
//2. Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型
//3. InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行
的目标对象方法作为参数传入
*/
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                System.out.println("JDK 代理开始~~");
                //反射机制调用目标对象的方法
                Object returnVal = method.invoke(target, args);
                System.out.println("JDK 代理提交");
                return returnVal;
            }
        });
    }
}

client 测试

package tanchishell.SJMS.JDKstaticproxy;

public class Client {
    public static void main(String[] args) {

        //创建目标对象
        ITeacherDao target = new TeacherDao();
        //给目标对象,创建代理对象, 可以转成 ITeacherDa
        ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();
        // proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象
        System.out.println("proxyInstance=" + proxyInstance.getClass());
        //通过代理对象,调用目标对象的方法
        proxyInstance.teach();
        proxyInstance.sayHello(" tom ");
    }
}


输出

proxyInstance=class com.sun.proxy.$Proxy0
JDK 代理开始~~
 老师授课中.... 
JDK 代理提交
JDK 代理开始~~
hello  tom 
JDK 代理提交

三、Cglib代理

CGlib 代理和 jdk 代理的最大区别是不需要 被代理类实现接口,使用方法拦截的形式进行动态代理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

完整代码

被代理对象

package CgLibstaticproxy;

public class TeacherDao {
    public String teach() {
        System.out.println(" 老师授课中 , 我是 cglib 代理,不需要实现接口 ");
        return "hello";
    }
}

代理工厂

package CgLibstaticproxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class ProxyFactory implements MethodInterceptor {
    //维护一个目标对象
    private Object target;

    //构造器,传入一个被代理的对象
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //返回一个代理对象: 是 target 对象的代理对象
    public Object getProxyInstance() {
        //1. 创建一个工具类
        Enhancer enhancer = new Enhancer();

        //2. 设置父类
        enhancer.setSuperclass(target.getClass());
        //3. 设置回调函数
        enhancer.setCallback(this);
        //4. 创建子类对象,即代理对象
        return enhancer.create();
    }

    //重写 intercept 方法,会调用目标对象的方法
    @Override
    public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {

        System.out.println("Cglib 代理模式 ~~ 开始");
        Object returnVal = method.invoke(target, args);
        System.out.println("Cglib 代理模式 ~~ 提交");
        return returnVal;
    }
}

测试

package CgLibstaticproxy;

public class Client {
    public static void main(String[] args) {

        //创建目标对象
        TeacherDao target = new TeacherDao();
        //获取到代理对象,并且将目标对象传递给代理对象
        TeacherDao proxyInstance = (TeacherDao)new ProxyFactory(target).getProxyInstance();
        //执行代理对象的方法,触发 intecept 方法,从而实现 对目标对象的调用
        String res = proxyInstance.teach();
        System.out.println("res=" + res);
    }
}

输出

Cglib 代理模式 ~~ 开始
 老师授课中 , 我是 cglib 代理,不需要实现接口 
Cglib 代理模式 ~~ 提交
res=hello

四、代理模式(Proxy)的变体

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/15158.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

企业本地文档如何实现规范在线管理?

随着企业数字化生产方式的不断推进&#xff0c;网络办公和在线协作越来越普遍&#xff0c;企业内部可能出现大量的文件和文档&#xff0c;这些文档多存在于不同的设备和存储介质上&#xff0c;这给企业的信息管理带来了一定程度的困难。为了提高企业的知识管理效率&#xff0c;…

Go基础篇:类型系统

目录 前言✨一、什么是类型&#xff1f;二、类型特性1、静态类型检查2、类型推断 三、类型别名和自定义类型1、类型别名2、自定义类型3、类型别名和自定义类型的区别 四、类型底层结构1、类型元数据2、其他描述信息3、uncommontype 五、小结 前言✨ 前段时间忙着春招面试&#…

移动端事件

文章目录 移动端事件概述兼容性Touch触摸事件事件类型是否支持事件使用event对象touch对象阻止浏览器默认行为单指拖拽 Pointer指针事件事件类型是否支持事件使用event对象阻止浏览器默认行为单指拖拽 移动端事件 概述 移动端事件可分为&#xff1a; Touch触摸事件Pointer指…

【Bard】谷歌的人工智能工具—Bard初体验

文章目录 一、Bard介绍二、Bard体验1、加入Bard的候补名单2、登入Bard篇3、使用Bard篇&#xff08;1&#xff09;提供三种预选方式✨&#xff08;2&#xff09;创作生成各类文案&#xff08;3&#xff09;无生成图画能力&#xff08;4&#xff09;支持语音转文本输入✨&#xf…

实景区剧本杀系统开发

实景区剧本杀系统开发需要考虑以下几个方面&#xff1a; 场地选取&#xff1a;选择合适的场地&#xff0c;足够容纳游戏人数和游戏内容&#xff0c;同时需要考虑安全性和便利性。 剧情设定&#xff1a;根据场地和游戏类型设计剧情&#xff0c;包括人物角色、任务目标、…

SpringBoot日志文件

文章目录&#xff1a;一.日志的作用 二.日志的使用&#xff08;1&#xff09;系统默认日志输出 &#xff08;2&#xff09;自定义日志输出 三.日志级别的分类 &#xff08;1&#xff09;默认级别 &#xff08;2&#xff09;自定义级别 四.日志的持久化 &#xff08;1&…

又一次503 service unavailable处理

出现了&#xff1a;503 service unavailable 1&#xff09;查看系统日志 通过事件查看器&#xff0c;查看iis的日志,如下&#xff1a; 在错误信息中提示是 应用程序池提供服务的进程中出现错误。 其他警告也可通过日志目录查看 C:\inetpub\ 出现上述问题的可能是&#xf…

Node第三方包 【Request】

文章目录 &#x1f31f;前言&#x1f31f;Request&#x1f31f;安装与使用&#x1f31f;流&#xff08;stream&#xff09;操作&#x1f31f;Form表单&#x1f31f;application/x-www-form-urlencoded (URL编码的Form)&#x1f31f;multipart/form-data (Multipart Form 上传) …

http协议(一)/应用层

学习目标&#xff1a;⭐理解应用层的作用&#xff0c;理解协议&#xff0c;理解序列化和反序列化&#xff0c;并且实现网络版计算器⭐HTTP协议。⭐手写一个简单的http协议。 应用层 我们写的一个个解决实际问题, 满足我们日常需求的网络程序, 都是在应用层。 协议/序列化与反…

ChatGPT原理剖析

文章目录 ChatGPT常见误解1. 罐头回应2. 网络搜寻重组 ChatGPT真正做的事——文字接龙ChatGPT背后的关键技术——预训练&#xff08;Pre-train&#xff09;一般机器是怎样学习的&#xff1f; ChatGPT带来的研究问题1. 如何精准提出需求2. 如何更改错误3. 侦测AI生成的物件4. 不…

十、v-model的基本使用

一、v-model的基本使用 表单提交是开发中非常常见的功能&#xff0c;也是和用户交互的重要手段&#xff1a; 比如用户在登录、注册时需要提交账号密码&#xff1b;比如用户在检索、创建、更新信息时&#xff0c;需要提交一些数据&#xff1b; 这些都要求我们可以在代码逻辑中…

系统分析师《企业信息化战略与实施》高频知识点

企业信息化战略与实施---企业信息化与电子商务 业务流程重组&#xff08;Business Process Reengineering BPR&#xff09;是针对企业业务流程的基本问题进行反思&#xff0c;并对它进行彻底的重新设计&#xff0c;使业绩取得显著性提高。与目标管理、全面质量管理、战略管理等…

输入捕获实验

实验内容 用TIM5 的通道 1&#xff08;PA0&#xff09;来做输入捕获&#xff0c;捕获 PA0 上高电平的脉宽&#xff08;用 WK_UP 按键输入高电平&#xff09;&#xff0c;通过串口打印高电平脉宽时间。 输入捕获简介 输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32 的…

快速搭建Electron+Vite3+Vue3+TypeScript5脚手架 (无需梯子,快速安装Electron)

一、介绍 &#x1f606; &#x1f601; &#x1f609; Electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 嵌入 Chromium 和 Node.js 到 二进制的 Electron 允许您保持一个 JavaScript 代码代码库并创建 在Windows上运行的跨平台应用 macOS和Linux——不需…

宝塔面板搭建自己的网站,并发布公网远程访问

文章目录 1. 环境安装2. 安装cpolar内网穿透3. 内网穿透4.固定http地址5. 配置二级子域名6.创建一个测试页面 宝塔面板简单几步搭建本地web站点&#xff0c;并做内网穿透&#xff0c;实现公网用户也可以正常远程访问&#xff0c;无需公网IP&#xff0c;无需设置路由器。 1. 环…

Volatile系列(一):Volatile测试案例一可见性

系列文章 Volatile测试案例一可见性 目录 前言 测试1 逻辑 代码 结果 测试2 逻辑 代码 结果 结论 原理探讨&#xff08;可见性&#xff09; 前言 多线程是 JAVA 并发编程的主要应用&#xff0c;并发环境能大幅提高应用性能&#xff0c;提高 CPU 使用率&#xff0c…

优雅的接口防刷处理方案

前言 本文为描述通过Interceptor以及Redis实现接口访问防刷Demo 这里会通过逐步找问题&#xff0c;逐步去完善的形式展示 原理 通过ip地址uri拼接用以作为访问者访问接口区分 通过在Interceptor中拦截请求&#xff0c;从Redis中统计用户访问接口次数从而达到接口防刷目的 …

不应使用Excel进行项目资源规划的 7 个原因

项目资源规划早期仅限于基本分配和调度。因此&#xff0c;企业使用自制工具或excel表来执行这一简单功能。然而&#xff0c;随着技术和业务流程的发展&#xff0c;资源规划变得复杂&#xff0c;并包括其他组成部分&#xff0c;如预测和容量规划&#xff0c;优化等。 由于传统…

掌握好这几款TikTok数据分析工具,让你轻松提高曝光率!

为什么别人在TikTok发的普普通通的视频却有那么高的流量、几天内疯狂涨粉&#xff0c;而自己想破脑袋装饰自己的视频&#xff0c;结果却不如人意。 其实原因很简单&#xff0c;TikTok不像国内的抖音只面向中华民族&#xff0c;而是覆盖了150多个国家和75种语言用户&#xff0c…

【通信接口】UART、IIC、SPI

目录 一、预备知识 1、串行与并行 2、单工与双工 3、波特率 二、UART 三、IIC 四、SPI &#xff08;一对一、一对多&#xff09; 五、IIC、SPI异同点 参考文章&#xff1a;这些单片机接口&#xff0c;一定要熟悉&#xff1a;UART、I2C、SPI、TTL、RS232、RS422、RS485…