java-动态代理

为什么需要代理?

在这里插入图片描述

如何创建代理

注意:实现类和代理需要实现同一个接口

在这里插入图片描述

接口

public interface Star {
    String sing(String song);

    void dance();
}

实现类

public class BigStar implements Star {
    private String name;

    public BigStar(String name) {
        this.name = name;
    }

    public String sing(String song) {
        System.out.println(name + " is singing " + song);
        return "success";
    }

    public void dance() {
        System.out.println(name + " is dancing " );
    }
}

代理类

public class ProxyUtil {
    public static Star createProxy(Star target) {
        /**
         * ClassLoader loader, 加载类的类加载器 一般使用当前类的类加载器
         * Class<?>[] interfaces, 代理类要实现的接口列表 有哪些方法需要代理
         * InvocationHandler h 代理类的调用处理程序 实现接口 怎么代理这些方法
         */
        Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
                new Class[]{Star.class},
                // 代理类的调用处理程序
                new InvocationHandler() {
                    @Override
                    // 参数一:代理对象 参数二:当前调用的方法 参数三:方法的参数
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object result = null;
                        if ("sing".equals(method.getName())) {
                            beforeSing();
                            result = method.invoke(target, args);
                            afterSing();
                        } else if ("dance".equals(method.getName())) {
                            beforeDance();
                            result = method.invoke(target, args);
                            afterDance();
                        }
                        return result;
                    }});
        return starProxy;
    }

    // 前置增强
    public static void beforeSing() {
        System.out.println("唱歌之前");
    }

    // 后置增强
    public static void afterSing() {
        System.out.println("唱歌之后");
    }

    // 前置增强
    public static void beforeDance() {
        System.out.println("跳舞之前");
    }

    // 后置增强
    public static void afterDance() {
        System.out.println("跳舞之后");
    }
}

使用代理对象

  • 生成实现类对象
  • 将实现类对象传递给代理对象
  • 使用代理对象调用对应的方法(代理对象不仅会调用原本实现类的方法,还会调用前置增强和后置增强)
// 生成具体的类
Star star = new BigStar("Jay");
// 生成代理类
Star proxy = ProxyUtil.createProxy(star);

String sing = proxy.sing("七里香");
System.out.println(sing );
proxy.dance();

实际案例

需求

在这里插入图片描述

接口

public interface UserService {

    // 登录功能
    void login(String username, String password) throws Exception;

    // 删除功能
    void delete() throws Exception;

    // 查询功能
    String[] selectUsers() throws Exception;
}

实现类

public class UserServiceImpl implements UserService{
    @Override
    public void login(String username, String password) throws Exception {


        if ("admin".equals(username) && "123456".equals(password)) {
            System.out.println("登录成功");
        } else {
            System.out.println("登录失败");
        }

        Thread.sleep(1000);

    }

    @Override
    public void delete() throws Exception {


        System.out.println("删除用户");

        Thread.sleep(1500);


    }

    @Override
    public String[] selectUsers() throws Exception {

        System.out.println("查询用户");
        String[] users = new String[]{"张三", "李四", "王五"};

        Thread.sleep(2000);


        return users;
    }
}
 

代理类

public class ProxyUtil {
    public static  UserService createProxy(UserService target) {

        // 如果只执行了原本的方法,但是没有执行前置增强和后置增强,那么就是没有代理成功
        // 原因一般是返回了最开始的target对象,而不是代理对象
        return (UserService) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
                new Class[]{UserService.class},
                (proxy, method, args) -> {
                    Object result = null;
                    long start = before();
                    result = method.invoke(target, args);
                    long end = after();
                    takeTime(start, end);
                    return result;
                });

    }

    private static long before() {
        System.out.println("前置增强");
        return System.currentTimeMillis();
    }

    private static long  after() {
        System.out.println("后置增强");
        return System.currentTimeMillis();
    }

    private static void takeTime(long start,long end) {
        System.out.println("耗时:" + (end - start)/1000 + "s");
    }

}

使用

public class Main {
    public static void main(String[] args) throws Exception {
        UserService userService = new UserServiceImpl();
        UserService proxy = ProxyUtil.createProxy(userService);
        proxy.login("admin", "123456");
        proxy.delete();
        proxy.selectUsers();
    }
}

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

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

相关文章

开源博客项目Blog .NET Core源码学习(20:App.Hosting项目结构分析-8)

本文学习并分析App.Hosting项目中后台管理页面的个人资料页面、修改密码页面。 个人资料页面 个人资料页面用于显示和编辑个人信息&#xff0c;支持从本地上传个人头像。整个页面使用了layui中的表单、日期与时间选择、上传等样式或模块&#xff0c;通过layui.css文件设置样式…

精彩回顾|从 AI 到银幕:顶尖对话揭秘 AI 如何塑造影视新格局

4月17日&#xff0c;由万合天宜、三次元影业、NOVATECH、微软中国极客天团、微软 Reactor 共同推出的「从 AI 到银幕」顶尖对话在上海微软紫竹园区举办。中国内地著名导演、编剧、监制黄建新&#xff0c;微软&#xff08;中国&#xff09;有限公司首席技术官韦青&#xff0c;与…

基于SpringBoot+Vue高校实习管理系统的设计与实现

项目介绍&#xff1a; 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统高校实习管理系统信息管理难度大&#xf…

atlas 500容器(ubuntu20.04)搭建

1.docker 及环境搭建略 2.宿主机驱动安装略 3.宿主机中能正确使用npu-smi 4.docker 拉取略 5.docker 容器启动 docker run -itd --device/dev/davinci0 --device/dev/davinci_manager --device/dev/devmm_svm --device/dev/hisi_hdc -v /run/board_cfg.ini:/run/b…

吴恩达2022机器学习专项课程(一)7.2 逻辑回归的简化成本函数

问题预览/关键词 本节课内容逻辑回归的损失函数简化之后的形式是&#xff1f;为什么可以简化&#xff1f;成本函数的通用形式是&#xff1f;逻辑回归成本函数的最终形式是&#xff1f;逻辑回归为什么用对数损失函数计算成本函数&#xff1f;为什么不直接给出逻辑回归损失函数的…

银河麒麟V10 ARM64 离线安装 新版Docker

查询当前发行版本 nkvers下载最新版本 卸载旧依赖 卸载已经安装的老版本 yum remove docker \containerd.io \docker-runc \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine \docker-compo…

【数据结构7-1-查找-线性-二分法-二叉树-哈希表】

目录 1 查找基本概念2 线性表的查找2.1 顺序查找2.2 二分法查找2.3 分块查找 3 树表的查询3.1 二叉排序树3.1.1 定义3.1.2 二叉树的建立、遍历、查找、增加、删除&#xff1a;3.1.3 代码实现&#xff1a; 3.2 平衡二叉树3.2.1 平横因子3.2.2 不平横树的调整-左旋3.2.3 不平横树…

c++高级篇(三) ——Linux下IO多路复用之poll模型

poll模型 前言 poll模型与select的实现原理相近&#xff0c;所以绝大数的原理其实可以参考select&#xff0c;我们这里对二者的相同点不做过多探究&#xff0c;如果有需要可以去看一下博主的上一篇文章&#xff1a; c高级篇(二) ——Linux下IO多路复用之select模型 这里我们只…

【Jenkins】持续集成与交付 (三):有关报错解决(Jenkins (2.387.3) or higher required)

🟣【Jenkins】持续集成与交付 (三):有关报错解决Jenkins (2.387.3) or higher required 一、Jenkins主页报错二、安装Jenkins插件报错三、解决过程(解压替换jenkins.war)四、重新访问登录💖The Begin💖点点关注,收藏不迷路💖 一、Jenkins主页报错 New version …

51单片机两个中断及中断嵌套

文章目录 前言一、中断嵌套是什么&#xff1f;二、两个同级别中断2.1 中断运行关系2.2 测试程序 三、两个不同级别中断实现中断嵌套3.1 中断运行关系3.2 测试程序 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 课程需要&#xff1a; 提示&#x…

【电路笔记】-RC振荡器电路

RC振荡器电路 文章目录 RC振荡器电路1、概述2、RC 相移网络3、基本RC振荡器电路4、运算放大器RC振荡器5、运算放大器相位滞后RC振荡器电路6、RC振荡器示例11、概述 RC 振荡器使用放大器和 RC 反馈网络的组合,由于级之间的相移而产生输出振荡。 当单级晶体管放大器作为共发射…

疯狂的爬虫案例(2)文末附源码

软件版本号&#xff1a; python --version Python 3.8.0 pip show selenium Version: 4.20.0 chromedriver.exe -version 109.0.5414.74 主题&#xff1a;爬取10条动态网页内容&#xff08;电影票房&#xff09; 1.根据xpath获取网页节点&#xff08;CtrlF&#xff09; 2.…

spring高级篇(五)

1、参数解析器 前篇提到过&#xff0c;参数解析器是HandlerAdapters中的组件&#xff0c;用于解析controller层方法中加了注解的参数信息。 有一个controller&#xff0c;方法的参数加上了各种注解&#xff1a; public class Controller {public void test(RequestParam("…

Python-100-Days: Day06 Functions and Modules

函数的作用 编程大师Martin Fowler先生曾经说过&#xff1a;“代码有很多种坏味道&#xff0c;重复是最坏的一种&#xff01;”&#xff0c;要写出高质量的代码首先要解决的就是重复代码的问题。可以将特定的功能封装到一个称之为“函数”的功能模块中&#xff0c;在需要的时候…

MyBatis(环境配置+基本CRUD)

文章目录 1.基本介绍1.为什么需要MyBatis&#xff1f;2.MyBatis介绍3.MyBatis工作示意图4.MyBatis的优势 2.快速入门文件目录1.需求分析2.数据库表设计3.父子模块环境配置1.创建maven父项目2.删除父项目的src目录3.pom.xml文件文件解释 4.创建子模块1.新建一个Module2.创建一个…

面向对象编程三大特征:封装、继承、多态

封装、继承、多态 1. 封装 1.1 介绍 封装(encapsulation)就是把抽象出的数据 [属性] 和对数据的操作 [方法] 封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作 [方法] ,才能对数据进行操作。 1.2 封装的理解和好处 1) 隐藏实现细节:方法(连接数据库)<…

UE Snap03 启动参数设置

UE Snap03 启动参数设置 UE打包后传入自定义参数及解析。 void UGameInstance::StartGameInstance() {Super::StartGameInstance();UE_LOG(LogTemp, Warning, TEXT("--StartGameInstance--"));FString param;FParse::Value(FCommandLine::Get(), TEXT("-UserN…

Python | Leetcode Python题解之第50题Pow(x,n)

题目&#xff1a; 题解&#xff1a; class Solution:def myPow(self, x: float, n: int) -> float:def quickMul(N):ans 1.0# 贡献的初始值为 xx_contribute x# 在对 N 进行二进制拆分的同时计算答案while N > 0:if N % 2 1:# 如果 N 二进制表示的最低位为 1&#xf…

新手一文掌握 ea怎么注册?ea官网注册账号的详细教程

新手一文掌握 ea怎么注册&#xff1f;ea官网注册账号的详细教程 知名游戏平台EA平台&#xff0c;说到这个各位游戏玩家肯定不会陌生是全球知名的互动娱乐软件公司美国艺电&#xff08;Electronic Arts&#xff09;旗下的游戏平台。该平台主营电子游戏的开发、出版和销售业务&…

万兆以太网MAC设计(10)UDP协议解析以及模块设计

文章目录 前言&#xff1a;UDP报文格式一、UDP模块设计二、仿真总结&#xff1a; 前言&#xff1a;UDP报文格式 参考&#xff1a;https://sunyunqiang.com/blog/udp_protocol/ UDP (User Datagram Protocol) 是常用的传输层协议之一, 它向应用层提供无连接, 不可靠, 尽最大努力…