Java代理详解

Java代理详解

1. 静态代理

1.1 实现方式

  1. 为每个需要被代理的类都写一个对应的代理类,并实现目标类中想要代理的方法接口
  2. 创建代理对象时,通过构造器放入一个目标对象作为成员变量
  3. 实现被代理的方法,根据需要处理添加业务逻辑

1.2 代码示例

public class StaticProxyDemo {

    public static void main(String[] args) {
        // 一般在bean注入时用代理对象替换掉被代理的对象, 所以代理时一般以接口维度处理
        DemoInterface demoInterface = new DemoProxy(new DemoImpl());
        demoInterface.say();
    }

    /**
     * 接口
     */
    public interface DemoInterface {
        void say();
    }

    /**
     * 被代理类
     */
    public static class DemoImpl implements DemoInterface {
        @Override
        public void say() {
            System.out.println("impl");
        }
    }

    /**
     * 静态代理类
     */
    public static class DemoProxy implements DemoInterface {
        private final DemoInterface demoInterface;
        public DemoProxy(DemoInterface demoInterface) {
            this.demoInterface = demoInterface;
        }

        @Override
        public void say() {
            System.out.println("proxy before");
            demoInterface.say();
            System.out.println("proxy after");
        }
    }

}

1.3 静态代理的缺点

  1. 手动编写目标类:如果是针对单个对象的特殊逻辑还好,但如果是希望针对大范围的代理,工作量就会很大,代码也很臃肿
  2. 修改不便:当代理的对应接口出现调整时,代理类也需要跟随调整,即使调整的逻辑跟代理类的逻辑完全没关系

使用代理的场景基本是为了实现一些通用逻辑,个性化逻辑大部分情况下没必要使用代理来处理。

2. JDK动态代理

2.1 实现方式

Java内置的一种代理方式,通过反射来在运行时动态地创建代理类。

JDK动态代理要求目标对象必须实现接口。

实现流程:

  1. 实现InvocationHandler接口 或 使用Proxy类生成代理类对象
  2. 利用反射执行代理类中的方法

2.2 代码示例

import java.lang.reflect.*;

public class JdkProxyDemo {

    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        DemoInterface demoInterface = (DemoInterface) JdkProxyDemo.getProxy(new DemoImpl());
        System.out.println(demoInterface.say());

        DemoInterface demoInterface2 = (DemoInterface) JdkProxyDemo.getInvocationHandlerProxy(new DemoImpl());
        System.out.println(demoInterface2.say());
    }

    /**
     * 接口
     */
    public interface DemoInterface {
        String say();
    }

    /**
     * 被代理类
     */
    public static class DemoImpl implements DemoInterface {
        @Override
        public String say() {
            return "impl";
        }
    }

    /**
     * Proxy对象代理
     *
     * @param proxyTarget 被代理对象
     * @return 代理对象
     */
    public static Object getProxy(Object proxyTarget) {
        return Proxy.newProxyInstance(
                // 类加载器, 无特殊情况使用与目标对象相同的类加载器
                proxyTarget.getClass().getClassLoader(),
                // 代理对象实现的接口, 一般与代理对象保持一致, 保证所有接口方法被代理
                proxyTarget.getClass().getInterfaces(),
                (proxy1, method, args) -> {
                    System.out.println(method.getName() + "JDK Proxy Before");
                    Object result = method.invoke(proxyTarget, args);
                    System.out.println(method.getName() + "JDK Proxy After");
                    return result;
                }
        );
    }

    /**
     * Proxy对象代理
     *
     * @param proxyTarget 被代理对象
     * @return 代理对象
     */
    public static Object getInvocationHandlerProxy(Object proxyTarget) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?> proxyClazz = Proxy.getProxyClass(proxyTarget.getClass().getClassLoader(), proxyTarget.getClass().getInterfaces());
        Constructor<?> constructor = proxyClazz.getConstructor(InvocationHandler.class);
        return constructor.newInstance((InvocationHandler) (proxy1, method, args) -> {
            System.out.println(method.getName() + "JDK InvocationHandler Proxy Before");
            Object result = method.invoke(proxyTarget, args);
            System.out.println(method.getName() + "JDK InvocationHandler Proxy After");
            return result;
        });
    }

}

3. CGLIB动态代理

CGLIB代理(Code Generation Library)是一个高性能代码生成库。可以创建各种类型代码,其中包含了代理。

在代理方面,CGLIB代理不要求目标对象实现接口,因此它的使用范围更广,不过性能相比JDK动态代理要差一点(但不多)

CGLIB 动态代理的实现机制是生成目标类的子类,通过调用父类(目标类)的方法实现,在调用父类方法时在代理中进行增强。

PS:由于是继承方式实现的,所以final类和final方法无法被代理

实现流程:

  1. 导入CGLIB依赖包;
  2. 代理类实现MethodInterceptor
  3. 使用Enhancer类得到动态代理的实例,并执行指定方法

4. Javassist动态代理

Javassist是一个用于操作Java字节码的指令库,可以分析、编辑和创建Java字节码,通过对.class文件的修改,实现对类的修改和创建。

一般在开发中不会用到,主要是用于封装框架,比如struts2和hibernate。

Javassist动态代理主要有以下两种方式:

  1. 代理工厂创建:实现MethodHandler,处理代理逻辑,与CGLIB类似
  2. 动态代码创建:通过Java代码,分析class文件结构,动态的去创建代理代码,可以在运行时生成业务逻辑

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

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

相关文章

Zombie Animations Set

僵尸动画合集,包括成对攻击/抓取、各种移动方式、爬行、击中反应、死亡动画等。 生产说明 动画总数:99(包括22个位置变化) 配对动画:36 攻击次数:6次 爬网:9 命中反应:6 空转:14 行程2 跑步次数:9次 短跑:2 匝数:3 步行次数:12次 免责声明 任何游戏玩法蓝图都不包…

【计算机毕业设计】240基于微信小程序的校园综合服务平台

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

禁止methtype联网

mathtype断网_如何禁止mathtype联网-CSDN博客https://blog.csdn.net/qq_41060221/article/details/128144783

StarNet实战:使用StarNet实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整策略设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试完整的代码 在上…

微服务开发与实战Day09 - Elasticsearch

一、DSL查询 Elasticsearch提供了DSL&#xff08;Domain Specific Language&#xff09;查询&#xff0c;就是以JSON格式来定义查询条件。类似这样&#xff1a; DSL查询可以分为两大类&#xff1a; 叶子查询&#xff08;Leaf query clauses&#xff09;&#xff1a;一般是在特…

局域网内怎么访问另一台电脑?(2种方法)

案例&#xff1a;需要在局域网内远程电脑 “当我使用笔记本电脑时&#xff0c;有时需要获取保存在台式机上的文件&#xff0c;而两者都连接在同一个局域网上。我的台式机使用的是Windows 10企业版&#xff0c;而笔记本电脑则是Windows 10专业版。我想知道是否可以通过网络远程…

JVM 性能分析——jdk 自带命令分析工具(jps/jstat/jinfo/jmap/jhat/jstack)

文章目录 jps&#xff08;Java Process Status&#xff09;&#xff1a;查看正在运行的Java进程jstat&#xff08;JVM Statistics Monitoring Tool&#xff09;&#xff1a;查看 JVM 的统计信息jinfo&#xff08;Configuration Info for Java&#xff09;&#xff1a;实时查看和…

zip加密txt文件后,暴力破解时会有多个解密密码可以打开的疑问??

最近在做一个关于zip压缩文件解密的测试&#xff0c;发现通过暴力解密时&#xff0c;会有多个解密密码可以打开&#xff0c;非常疑惑&#xff0c;这里做个问题&#xff0c;希望能有大佬解惑。 1、首先在本地创建一个113449.txt的文件&#xff0c;然后右键txt文件选择压缩&…

AI赋能软件测试

AI赋能软件测试 AI赋能软件测试软件测试分类软件质量模型:用来衡量软件质量的维度AI赋能软件测试 随着AI时代的到来,如何轻松掌握软件测试新趋势,将AI技术应用于软件测试行业,提高测试速度与测试效率~~ 传智星云AI助手:https://nebula.itcast.cn tips:各种AI工具应有尽有…

图像处理方向信息

前言 Exif 规范 定义了方向标签&#xff0c;用于指示相机相对于所捕获场景的方向。相机可以使用该标签通过方向传感器自动指示方向&#xff0c;也可以让用户通过菜单开关手动指示方向&#xff0c;而无需实际转换图像数据本身。 在图像处理过程中&#xff0c;若是原图文件包含…

jeecg快速启动(附带本地运行可用版本下载)

版本整理&#xff08;windows x64位&#xff09;&#xff1a; redis&#xff1a;3.0.504 MYSQL&#xff1a;5.7 Maven&#xff1a;3.9.4(setting文件可下载) Nodejs&#xff1a;v16.20.2&#xff08;建议不要安装默认路径下&#xff0c;如已安装在c盘&#xff0c;运行yarn报…

MySQL之优化服务器设置(五)

优化服务器设置 高级InnoDB设置 innodb_old_blocks_time InnoDB有两段缓冲池LRU(最近最少使用)链表&#xff0c;设计目的是防止换出长期很多次的页面。像mysqldump产生的这种一次性的(大)查询&#xff0c;通常会读取页面到缓冲池的LRU列表&#xff0c;从中读取需要的行&…

安装wsl

安装wsl 先决条件&#xff1a; 打开控制面板->选择程序与功能->选择启动或关闭windows功能&#xff0c;将以下框选的勾选上 二、到Mircosoft store下载Ubuntu 三、如果以上都勾选了还报以下错误 注册表错误 0x8007019e Error code: Wsl/CallMsi/REGDB_E_CLASSNOTREG…

机器学习周报第46周

目录 摘要Abstract一、文献阅读1.1 摘要1.2 研究背景1.3 论文方法1.4 模块分析1.5 网络规格1.6 高效的端到端对象检测1.7 mobile former模块代码 目录 摘要Abstract一、文献阅读1.1 摘要1.2 研究背景1.3 论文方法1.4 模块分析1.5 网络规格1.6 高效的端到端对象检测1.7 mobile f…

9. 文本三剑客之awk

文章目录 9.1 什么是awk9.2 awk命令格式9.3 awk执行流程9.4 行与列9.4.1 取行9.4.2 取列 9.1 什么是awk 虽然sed编辑器是非常方便自动修改文本文件的工具&#xff0c;但其也有自身的限制。通常你需要一个用来处理文件中的数据的更高级工具&#xff0c;它能提供一个类编程环境来…

JVM-GC-什么是垃圾

JVM-GC-什么是垃圾 前言 所谓垃圾其实是指&#xff0c;内存中没用的数据&#xff1b;没有任何引用指向这块内存&#xff0c;或者没有任何指针指向这块内存。没有的数据应该被清除&#xff0c;垃圾的处理其实是内存管理问题。 JVM虽然不直接遵循冯诺依曼计算机体系架构&#…

SAP HCM 员工供应商过账详解 财务角度理解员工供应商过账

导读 INTRODUCTION 员工供应商:在某些情况下,特别是在大型组织或集团公司中,员工可能同时扮演着供应商的角色,为组织内部的其他部门或子公司提供产品或服务。例如,一个技术部门的员工可能为销售部门提供技术支持或定制开发服务。,还有一种,就是员工在公司挂账的欠款,每…

SpringBoot如何自定义启动Banner 以及自定义启动项目控制台输出信息 类似于若依启动大佛 制作教程

前言 Spring Boot 项目启动时会在控制台打印出一个 banner&#xff0c;下面演示如何定制这个 banner。 若依也会有相应的启动动画 _ooOoo_o8888888o88" . "88(| -_- |)O\ /O____/---\____. \\| |// ./ \\||| : |||// \/ _||||| -:- |||||- \| | \\…

GraogGNSSLib学习

GraogGNSSLib学习 程序编译环境版本项目编译结果问题 程序编译 GraphGNSSLib 环境版本 程序开源是在ubuntu16.04-kinetic环境跑通的&#xff0c;但是我的环境是UBUNTU20.04&#xff0c;所以&#xff0c;先进行了ROS的安装&#xff0c;因为我的系统是ubuntu20.04所以&#xf…

Hadoop 2.0:主流开源云架构(四)

目录 五、Hadoop 2.0访问接口&#xff08;一&#xff09;访问接口综述&#xff08;二&#xff09;浏览器接口&#xff08;三&#xff09;命令行接口 六、Hadoop 2.0编程接口&#xff08;一&#xff09;HDFS编程&#xff08;二&#xff09;Yarn编程 五、Hadoop 2.0访问接口 &am…