java-动态代理

news2024/11/17 13:41:16

为什么需要代理?

在这里插入图片描述

如何创建代理

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

在这里插入图片描述

接口

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();
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024Mac系统热门游戏排行榜 Mac支持的网络游戏有哪些?mac能玩哪些大型网游 苹果电脑Mac游戏资源推荐 Mac玩Windows游戏

“游戏是这个世界上唯一能和女性争夺男朋友的东西&#xff08;/滑稽&#xff0c;有不少女生也喜欢玩游戏&#xff09;。” 虽然只是一句玩笑话&#xff0c;不过也可以看出游戏对大多数男生来说是必不可少的一项娱乐活动了。而网络游戏是游戏中的一大分支&#xff0c;能让玩家们…

uniapp问题归类

最近使用uniapp中&#xff0c;遇到了一些问题&#xff0c;这边mark下。 1. 启动页变形 设置启动页的时候发现在部分android手机上启动页被拉伸了&#xff0c;最后看了下官方建议使用9.png图 生成9.png地址&#xff0c;推荐图片大小为1080x2340 uniapp推荐官方地址传送门 我…

Thread类的基本用法

1.线程创建 这里介绍线程创建常用的五种方法 1.继承Thread&#xff0c;重写run class MyThread extends Thread{public void run(){//这里写的代码就是线程要完成的任务while (true){System.out.println("hello thread");try {Thread.sleep(1000);//线程会休眠一秒…

Springboot+Vue项目-基于Java+MySQL的家政服务平台系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

FreeRTOS:3.信号量

FreeRTOS信号量 参考链接&#xff1a;FreeRTOS-信号量详解_freertos信号量-CSDN博客 目录 FreeRTOS信号量一、信号量是什么二、 FreeRTOS信号量1、二值信号量1、获取信号量2、释放信号量 2、计数信号量3、互斥信号量1、优先级反转2、优先级继承3、源码解析1、互斥量创建2、获取…

[蓝桥杯2024]-PWN:fd解析(命令符转义,标准输出重定向)

查看保护 查看ida 这里有一次栈溢出&#xff0c;并且题目给了我们system函数。 这里的知识点没有那么复杂 完整exp&#xff1a; from pwn import* pprocess(./pwn) pop_rdi0x400933 info0x601090 system0x400778payloadb"ca\\t flag 1>&2" print(len(paylo…

2024.04.28 Typecho管理视频文件,出现预览功能

需求原因原版的Typecho不支持在线视频预览,只有一个图片预览功能, 所以为了实现可以在线预览视频功能, 修改 typecho/admin/media.php 在大概19行的时候,追加如下内容 <?php if ($attachment->attachment->isImage): ?><p><img src"<?php $att…

装饰器模式【结构型模式C++】

1.概述 装饰器模式是一种结构型设计模式&#xff0c; 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。 2.结构 抽象构件&#xff08;Component&#xff09;角色&#xff1a;定义一个抽象接口以规范准备接收附加责任的对象。具体构件&#xff08;Concre…

关于文档中心的英文快捷替换方案

背景&#xff1a;文档中心需要接入国际化&#xff0c;想节省时间做统一英文方案处理&#xff1b; 文档中心是基于vuepress框架编写的&#xff1b; 1、利用百度翻译 API 的接口去做底层翻译处理&#xff0c;https://api.fanyi.baidu.com/需要在该平台上注册账号&#xff0c;个人…

决策树学习笔记

一、衡量标准——熵 随机变量不确定性的度量 信息增益&#xff1a;表示特征X使得类Y的不确定性减少的程度。 二、数据集 14天的打球情况 特征&#xff1a;4种环境变化&#xff08;天气、温度等等&#xff09; 在上述数据种&#xff0c;14天中打球的天数为9天&#xff1b;不…

docker部署的nacos2.2x开启鉴权功能

注意在2.2.0版本之后如果不开启鉴权&#xff0c;那么默认不需要登录就可以访问 所以我们需要手动开启鉴权&#xff0c;nacos启动好以后来到容器内部修改 docker exec -it nacos /bin/shvim conf/application.properties在第34行下面添加 nacos.core.auth.enabledtrue nacos.cor…

编译GTSAM库时报错undefined reference to `_dl_vsym@GLIBC_PRIVATE‘

/home/alex/miniforge3/envs/ros_py39_env/bin/ld: /home/alex/miniforge3/envs/ros_py39_env/bin/../x86_64-conda-linux-gnu/sysroot/lib64/libdl.so.2: undefined reference to _dl_vsymGLIBC_PRIVATE SOLUTION&#xff1a;在CMakeLists.txt里加入&#xff1a; set (CMAKE…

信号分解 | RLMD(鲁棒性局部均值分解)-Matlab

分解效果 RLMD(鲁棒性局部均值分解) RLMD(鲁棒性局部均值分解)-Matlab 代码实现 % %% 清除所有变量 关闭窗口 clc clear all close all%% 导入数据 % data = xlsread(Data.xlsx);%% 输入信号%% RLMD分解 %参数进行设置 % options.display =

OPPO Reno10Pro/Reno11/K10手机强解BL刷root权限KSU内核抓包刷机救砖

OPPO Reno10Pro/Reno11/K10手机虽然发布时间并不久&#xff0c;但由于天玑处理器的体质&#xff0c;已经支持强制解锁BL了&#xff0c;该漏洞来自第三方工具适配&#xff0c;支持OPPO天机8100/8200刷机救砖解锁BL不需要等待官方深度测试直接实现。解锁BL后的OPPO Reno10Pro/Ren…

会声会影2024Win版64位电脑下载及系统配置要求

会声会影是一款专业的视频编辑软件&#xff0c;至今也推出了多版软件&#xff0c;深受用户的喜爱&#xff0c;这不&#xff0c;最近会声会影又要出2024版了&#xff0c;相信有很多用户都想知道新版本有哪些变化&#xff0c;新增了什么功能。下面我就为大家带来会声会影2024美颜…

web前端学习笔记4

4. 盒子模型 4.0 代码地址 https://gitee.com/qiangge95243611/java118/tree/master/web/day044.1 什么是盒子模型(Box Model) 所有HTML元素可以看作盒子,在CSS中,"box model"这一术语是用来设计和布局时使用。 CSS盒模型本质上是一个盒子,封装周围的HTML元素,…

MySQL双层游标嵌套循环方法

文章目录 1、需求描述2、思路3、创建存储过程 1、需求描述 1、在项目中&#xff0c;需要将A表中主键id&#xff0c;逐个取出&#xff0c;作为条件&#xff0c;在B表中去逐一查询&#xff0c;将B表查询到的结果集&#xff08;A表B表关系&#xff1a;一对多&#xff09;&#xf…

【软件开发规范篇】Git分支使用规范

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0c;产…

TCP/IP协议族中的TCP(一):解析其关键特性与机制

⭐小白苦学IT的博客主页⭐ ⭐初学者必看&#xff1a;Linux操作系统入门⭐ ⭐代码仓库&#xff1a;Linux代码仓库⭐ ❤关注我一起讨论和学习Linux系统 前言 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字…

vue项目npm run build 打包之后如何在本地访问

vue项目npm run build 打包之后如何在本地访问 如果直接访问时&#xff0c;则会报错如下的信息&#xff1a; 报错码&#xff1a; Access to script at file:///D:/assets/index-DDVBfHVo.js from origin null has been blocked by CORS policy: Cross origin requests are on…