【Java基础】反射机制与动态代理机制

news2024/11/16 3:21:43

反射机制与动态代理机制

文章目录

  • 反射机制与动态代理机制
    • 1. 反射(Reflection)的概念
      • 1.1 反射概述
      • 1.2 反射的优缺点
    • 2. 理解Class类并获取Class实例
      • 2.1 Class
      • 2.2 Class类的常用方法
    • 3. 反射的基本应用
      • 3.1 应用1:创建运行时类的对象
      • 3.2 应用2:调用运行时类的指定结构
        • 3.2.1 调用指定的属性
        • 3.2.2 调用指定的方法
    • 4. 动态代理机制

1. 反射(Reflection)的概念

1.1 反射概述

Reflection(反射)被视为动态语言的关键,反射机制允许程序在运行期间借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。

1.2 反射的优缺点

优点:

  • 提高了Java程序的灵活性和扩展性,降低了耦合性,提高自适应能力

  • 允许程序创建和控制任何类的对象,无需提前硬编码目标类

缺点:

  • 反射的性能较低

    • 反射机制主要应用在对灵活性和扩展性要求很高的系统框架上
  • 反射会模糊程序内部逻辑,可读性较差

2. 理解Class类并获取Class实例

要想解剖一个类,必须先要获取到该类的Class对象。而剖析一个类或用反射解决具体的问题就是使用相关API:

  • java.lang.Class
  • java.lang.reflect.*

所以,Class对象是反射的根源。

2.1 Class

在Object类中定义了以下的方法,此方法将被所有子类继承:

public final Class getClass()

以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。

  • Class本身也是一个类
  • Class 对象只能由系统建立对象
  • 一个加载的类在 JVM 中只会有一个Class实例
  • 一个Class对象对应的是一个加载到JVM中的一个.class文件
  • 每个类的实例都会记得自己是由哪个 Class 实例所生成
  • 通过Class可以完整地得到一个类中的所有被加载的结构
  • Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class对象

2.2 Class类的常用方法

方法名功能说明
static Class forName(String name)返回指定类名 name 的 Class 对象
Object newInstance()调用缺省构造函数,返回该Class对象的一个实例
getName()返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称
Class getSuperClass()返回当前Class对象的父类的Class对象
Class [] getInterfaces()获取当前Class对象的接口
ClassLoader getClassLoader()返回该类的类加载器
Class getSuperclass()返回表示此Class所表示的实体的超类的Class
Constructor[] getConstructors()返回一个包含某些Constructor对象的数组
Field[] getDeclaredFields()返回Field对象的一个数组
Method getMethod(String name,Class … paramTypes)返回一个Method对象,此对象的形参类型为paramType

3. 反射的基本应用

有了Class对象,能做什么?

3.1 应用1:创建运行时类的对象

这是反射机制应用最多的地方。创建运行时类的对象有两种方式:

方式1:直接调用Class对象的newInstance()方法

要 求: 1)类必须有一个无参数的构造器。2)类的构造器的访问权限需要足够。

方式2:通过获取构造器对象来进行实例化

方式一的步骤:

1)获取该类型的Class对象 2)调用Class对象的newInstance()方法创建对象

方式二的步骤:

1)通过Class类的getDeclaredConstructor(Class … parameterTypes)取得本类的指定形参类型的构造器
2)向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数。
3)通过Constructor实例化对象。

如果构造器的权限修饰符修饰的范围不可见,也可以调用setAccessible(true)

3.2 应用2:调用运行时类的指定结构

3.2.1 调用指定的属性

在反射机制中,可以直接通过Field类操作类中的属性,通过Field类提供的set()和get()方法就可以完成设置和取得属性内容的操作。

关于setAccessible方法的使用:

  • Method和Field、Constructor对象都有setAccessible()方法。
  • setAccessible启动和禁用访问安全检查的开关。
  • 参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。
    • 提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。
    • 使得原本无法访问的私有成员也可以访问
  • 参数值为false则指示反射的对象应该实施Java语言访问检查。
3.2.2 调用指定的方法

在这里插入图片描述

(1)获取该类型的Class对象

Class clazz = Class.forName(“包.类名”);

(2)获取方法对象

Method method = clazz.getDeclaredMethod(“方法名”,方法的形参类型列表);

(3)创建实例对象

Object obj = clazz.newInstance();

(4)调用方法

Object result = method.invoke(obj, 方法的实参值列表);

如果方法的权限修饰符修饰的范围不可见,也可以调用setAccessible(true)

如果方法是静态方法,实例对象也可以省略,用null代替

4. 动态代理机制

利用Java的反射技术(Java Reflection),在运行时创建一个实现某些给定接口的新类(也称“动态代理类”)及其实例(对象),代理的是接口(Interfaces),不是类(Class),也不是抽象类。在程序运行时才知道具体的实现,spring aop就是运用了该原理

  • 动态代理实际上是JVM在运行期动态创建class字节码并加载的过程

使用动态代理可以实现不修改原方法而增强原方法的功能需求,类似可实现打印入参出参,如果需要去掉改功能,则只要去除代理类的使用即可:

public class Main {

    interface Worker {
        void working();
    }

    static class Man implements Worker {

        @Override
        public void working() {
            System.out.println("业务工作完成");
        }
    }

    static class LogInvocationHandler implements InvocationHandler{

        private final Worker worker;

        public LogInvocationHandler(Worker worker) {
            this.worker = worker;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("记录执行前");
            Object invoke = method.invoke(worker, args);
            System.out.println("记录执行后");
            return invoke;
        }
    }

    public static void main(String[] args) {
        Worker worker = new Man();
        worker.working();

        Worker workerProxy = (Worker)Proxy.newProxyInstance(
                Worker.class.getClassLoader(),
                new Class[]{Worker.class}, new LogInvocationHandler(worker));
        workerProxy.working();
    }
}

标准库的动态代理方法只能增强接口,还可以使用cglib代理,将不再有接口限制

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

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

相关文章

什么是恶意代码?

前言:本文旨在分享交流技术,在这里对恶意代码进行全面的介绍和讲解 目录 一.什么是恶意代码 二.恶意代码的发展史 三.恶意代码的相关定义 四.恶意代码攻击机制 PE病毒 PE文件的格式 脚本病毒 脚本文件隐藏方法 宏病毒 浏览器恶意代码 U盘病毒 …

Go基础——数组、切片、集合

目录 1、数组2、切片3、集合4、范围(range) 1、数组 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整型、字符串或者自定义类型。 Go 语言数组声明需要指定元素类型及元素个数,与…

docker - DockerFile 编写 指令

文章目录 前言docker - DockerFile 编写 指令1. FROM2. MAINTAINER3. RUN4. CMD5. LABEL6. EXPOSE7. ENV8. ADD9. COPY10. ENTRYPOINT11. VOLUME12. USER13. WORKDIR14. ARG15. ONBUILD16. STOPSIGNAL 前言 如果您觉得有用的话,记得给博主点个赞,评论&am…

Virtual DOM

目录 Virtual DOM 前言 用法 代码 理解 Virtual DOM的工作原理: 为什么使用Virtual DOM? 哪些库/框架使用Virtual DOM? 总结 Virtual DOM(虚拟DOM)是一种编程概念,它是对真实DOM的轻量级抽象表示。在前端开发中&#x…

【软考】系统集成项目管理工程师(九)项目成本管理【4分】

一、成本概念 1、产品全生命周期成本 产品或系统的整个使用生命周期内,在获得阶段(设计、生产、安装和测试等活动,即项目存续期间)、运营与维护、生命周期结束时对产品的处置所发生的全部成本 2、成本类型 成本类型描述可变成…

【Matlab2016】Matlab中文版的下载、安装、激活(不建议安装过高版本!!)

这里写目录标题 首先双击R2016_win64.iso加载镜像文件双击setup.exe开始安装选择使用文件密钥安装填入密钥修改安装路径并记住此路径建议全部勾选等待安装完成 激活复制补丁到matlab路径下 创建快捷方式进入bin目录,找到matlab.exe 安装包 首先双击R2016_win64.iso加…

会声会影2023永久激活序列号密钥(支持各版本会声会影注册机)

会声会影2023永久激活序列号密钥(支持各版本)。会声会影2023是一款强大专业的视频编辑软件。会声会影2023产品序列号,支持专业版和旗舰版,可免费激活会声会影2023软件。会声会影2023序列号激活码目前网上很难找到了,这些会声会影序列号是小编…

如何编写一份完整的软件测试报告?

背景 作为测试从业者,编写测试用例,测试计划,测试报告都是必经之路,最近完成了年终述职以及版本准出,感觉测试报告或者各类报告真是职场人不可或缺的一项技能,趁着热乎劲🔥,写下一些…

Spring Cloud 实战 | 解密负载均衡Ribbon底层原理,包含实战源码

专栏集锦,大佬们可以收藏以备不时之需 Spring Cloud实战专栏:https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏:https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏:https:/…

车载音频ADI-ADSP21569音频DSP开发

车载音频ADI-ADSP21489音频DSP开发 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,+群赠送蓝牙音频,车载DSP音频项目核心开发资料, 1 芯片手册 2 电路原理图

fl studio2023最新版本如何设置中文?

FL Studio编曲软件真的是个神器,不过一开始打开看到全是英文,有点头大,对吧?其实切换成中文版超级简单,只需要几个步骤就搞定啦!我自己也是用中文版的,觉得用起来更得心应手,效率也提…

分享一个基于asp.net的供销社农产品商品销售系统的设计与实现(源码调试 lw开题报告ppt)

💕💕作者:计算机源码社 💕💕个人简介:本人七年开发经验,擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等,大家有这一块的问题可以一起交流! 💕&…

MySQL主从复制(基于GTID--事务ID方式)

目录 一、GTID相关概念1.GTID 是什么?2.GTID主从复制方式概念3.GTID的优缺点 二、GTID工作原理三、部署主从复制四、测试同步1.主库上新建数据库2.从库上查看是否同步成功 五、重设从库六、常见故障七、故障切换八、GTID的一些疑问1.为什么基于GTID的同步也要打开bi…

Dataworks API:调取 MC 项目下所有表单

文章目录 前言Dataworks API 文档解读GetMetaDBTableList 接口文档 API 调试在线调试本地调试运行环境账密问题请求数据进一步处理 小结 前言 最近,我需要对公司的数据资产进行梳理,这其中便包括了Dataworks各个项目下的表单。这些表单,作为…

Java进击框架:Spring-Test(六)

Java进击框架:Spring-Test(六) 前言单元测试模拟对象 集成测试上下文管理和缓存事务管理集成测试的支持类执行SQL脚本WebTestClientMockMvc JDBC测试支持其它注释 前言 Spring团队提倡测试驱动开发(TDD)。Spring团队发现,控制反转…

Ai创作系统ChatGPT网站源码+图文搭建教程+支持GPT4.0+支持ai绘画(Midjourney)

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统AI绘画系统,支持OpenAI GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署…

北邮22级信通院数电:Verilog-FPGA(7)第七周实验(1):带使能端的38译码器全加器(关注我的uu们加群咯~)

北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章,请访问专栏: 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客 关注作者的uu们可以进群啦~ 目录 方法一&#xff…

C嘎嘎之类和对象中

> 作者简介:დ旧言~,目前大二,现在学习Java,c,c,Python等 > 座右铭:松树千年终是朽,槿花一日自为荣。 > 目标:掌握c的初始化和销毁,熟练运用拷贝构造…

Tuxera NTFS2024破解版本下载

当您获得一台新 Mac 时,它只能读取 Windows NTFS 格式的 USB 驱动器。要将文件添加、保存或写入您的 Mac,您需要一个附加的 NTFS 驱动程序。Tuxera 的 Microsoft NTFS for Mac 是一款易于使用的软件,可以在 Mac 上打开、编辑、复制、移动或删…