(四)Spring教程——控制反转或依赖注入与Java的反射技术

        IoC的底层实现技术是反射技术,目前Java、C#、PHP 等语言均支持反射技术。

        在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法;对任意一个对象,都能够调用它的任意方法和属性(包括私有的方法和属性)。这种动态获取信息以及动态调用对象对象和对象方法的功能就被称作反射机制。

        通俗来讲,反射技术就是根据给出的类名(字符串方式)来动态生成对象。这种编程方式可以在生成对象时再决定到底生成哪一种对象。反射的应用是很广泛的,很多成熟的框架都离不开反射技术,比如Java中的Hibernate、Spring框架。

        反射技术很早就出现了,初期的反射编程速度相对于传统对象生成速度至少要慢10倍,目前的反射技术经过优化,反射方式生成对象和传统对象生成方式的速度相差不大,大约有1~2被的差距。由于IoC容器通过反射方式生成对象时,在运行效率上有一定的损耗,因此,如果系统追求运行效率,就必须权衡是否使用反射技术。

        在Java语言中,可以通过Class类的forName()方法获取类的信息,同Class类的newInstance()方法获得一个具体的实例。在java.lang.reflect包里,Java语言提供了Field、Method、Modifier、Constructor、InvocationHandler等类,可以轻松实现反射技术。

        为了让大家了解依赖注入的基础,示例展示了使用Java实现的一个反射应用:通过Class类来实现类的定义,通过Field来获取类的属性,通过Method类来获取方法,并通过invoke来调用方法,设置类的某个属性。

        首先我们创建一个InnerPerson类,InnerPerson类的代码如下

class InnerPerson {private String name;private int age;public String pub;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "reflect.InnerPerson{" +"name='" + name + '\'' +", age=" + age +'}';}};

        然后我们创建一个ReflectDemo01类,在该类中我们使用三种方式来实现类的实例化。ReflectDemo1的代码如下图所示

public class ReflectDemo01 {public static void main(String[] args) {//三种不同类实例化方法//第一种实例Class<?> firstInstance = null;//第二种实例Class<?> secondInstance = null;//第三种实例Class<?> thirdInstance = null;//通过类名实例化的方法try {firstInstance = Class.forName("com.example.servlet001.InnerPerson");} catch (ClassNotFoundException e) {e.printStackTrace();}//通过Object类中的方法实例化secondInstance=new InnerPerson().getClass();//通过类.class实例化thirdInstance=InnerPerson.class;System.out.println("类名称:"+firstInstance.getName());System.out.println("类名称:"+secondInstance.getName());System.out.println("类名称:"+thirdInstance.getName());}}

        运行该程序后得到的结果如下图所示

        继续修改ReflectDemo01 的代码,代码内容如下

public class ReflectDemo01 {public static void main(String[] args) {//三种不同类实例化方法//第一种实例Class<?> firstInstance = null;//第二种实例Class<?> secondInstance = null;//第三种实例Class<?> thirdInstance = null;//通过类名实例化的方法try {firstInstance = Class.forName("com.example.servlet001.InnerPerson");} catch (ClassNotFoundException e) {e.printStackTrace();}//通过Object类中的方法实例化secondInstance = new InnerPerson().getClass();//通过类.class实例化thirdInstance = InnerPerson.class;//        System.out.println("类名称:"+firstInstance.getName());//        System.out.println("类名称:"+secondInstance.getName());//        System.out.println("类名称:"+thirdInstance.getName());//获取类实例中的字段并输出//获得public的所有字段数组Field[] fields = firstInstance.getFields();//获取任何权限的所有字段Field[] allFields = firstInstance.getDeclaredFields();System.out.println("---------------所有public字段----------------");for (Field fx : fields) {System.out.println(fx);}System.out.println("---------------所有字段----------------");for (Field fx : allFields) {System.out.println(fx);}//获取方法并输出Method[] m1 = firstInstance.getMethods();Method[] m2 = firstInstance.getDeclaredMethods();System.out.println("---------------所有public方法----------------");for (Method method : m1) {System.out.println(method);}System.out.println("---------------所有方法----------------");for (Method method : m2) {System.out.println(method);}//执行方法并输出System.out.println("---------------使用invoke执行方法----------------");//反射式的,只需要写入方法名,不需要加括号Method m = null;try {Object o = firstInstance.newInstance();try {m = firstInstance.getDeclaredMethod("setName", String.class);try {m.invoke(o, new Object[]{"John"});System.out.println("当前对象为:" + o);} catch (InvocationTargetException e) {e.printStackTrace();}} catch (NoSuchMethodException e) {e.printStackTrace();}} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}

       完整的代码如下所示

package com.example.servlet001;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class ReflectDemo01 {public static void main(String[] args) {//三种不同类实例化方法//第一种实例Class<?> firstInstance = null;//第二种实例Class<?> secondInstance = null;//第三种实例Class<?> thirdInstance = null;//通过类名实例化的方法try {firstInstance = Class.forName("com.example.servlet001.InnerPerson");} catch (ClassNotFoundException e) {e.printStackTrace();}//通过Object类中的方法实例化secondInstance = new InnerPerson().getClass();//通过类.class实例化thirdInstance = InnerPerson.class;
//        System.out.println("类名称:"+firstInstance.getName());
//        System.out.println("类名称:"+secondInstance.getName());
//        System.out.println("类名称:"+thirdInstance.getName());//获取类实例中的字段并输出//获得public的所有字段数组Field[] fields = firstInstance.getFields();//获取任何权限的所有字段Field[] allFields = firstInstance.getDeclaredFields();System.out.println("---------------所有public字段----------------");for (Field fx : fields) {System.out.println(fx);}System.out.println("---------------所有字段----------------");for (Field fx : allFields) {System.out.println(fx);}//获取方法并输出Method[] m1 = firstInstance.getMethods();Method[] m2 = firstInstance.getDeclaredMethods();System.out.println("---------------所有public方法----------------");for (Method method : m1) {System.out.println(method);}System.out.println("---------------所有方法----------------");for (Method method : m2) {System.out.println(method);}//执行方法并输出System.out.println("---------------使用invoke执行方法----------------");//反射式的,只需要写入方法名,不需要加括号Method m = null;try {Object o = firstInstance.newInstance();try {m = firstInstance.getDeclaredMethod("setName", String.class);try {m.invoke(o, new Object[]{"John"});System.out.println("当前对象为:" + o);} catch (InvocationTargetException e) {e.printStackTrace();}} catch (NoSuchMethodException e) {e.printStackTrace();}} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}
}class InnerPerson {private String name;private int age;public String pub;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "reflect.InnerPerson{" +"name='" + name + '\'' +", age=" + age +'}';}
};

        运行该示例后的输出如下图所示

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

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

相关文章

python的标准数据类型

四、标准数据类型 1、为什么编程语言中要有类型 类型有以下几个重要角色&#xff1a; 对机器而言&#xff0c;类型描述了内存中的电荷是怎么解释的。 对编译器或者解释器而言&#xff0c;类型可以协助确保上面那些电荷、字节在程序的运行中始终如一地被理解。 对程序员而言…

vLLM推理服务库

一、定义 定义与目的为什么Cache只存储K、V&#xff0c;而不存储Q&#xff1f;为什么vllm和HF推理结果不一致&#xff1f;vLLM 实现原理pagedAttention 实现原理模型部署demo 二、实现 定义与目的 目的&#xff1a;减少显存、提高吞吐量。如何优化KV cache&#xff0c;节省显…

基于大模型训练的数字识别

创作原因 现在写电赛题&#xff0c;题目有识别数字的要求。但使用设备openmv使用模板匹配的算法帧率很低&#xff0c;且识别效果不是很好&#xff0c;于是我们就想到了利用神经网络训练模型来识别数字 正文部分 内容介绍 本文内容是基于openmv使用Edge Impulse训练大模型。…

爬虫工作量由小到大的思维转变---<第七十五章 > Scrapy爬虫回调函数在请求重试中的应用研究

前言&#xff1a; 在Scrapy框架中&#xff0c;利用回调函数进行请求重试的实践方法与其优劣势&#xff0c;与传统的中间件重试机制进行对比。通过深入分析回调函数的工作原理及其在网络爬虫项目中的应用&#xff0c;旨在提高网络爬虫的效率和稳健性。同时&#xff0c;本文将探讨…

服务攻防——应用协议ssh,rsync,proftpd,openssh,libssh

1.口令猜解 ftp-拿来文件传输的 rdp-windows远程连接 3389 ssh-linux远程连接 工具hydra 口令 1.windows 这就爆破成功了&#xff0c;现在&#xff0c;我们就可以ftp爆破&#xff0c;爆破出ftp的密码 爆破出来后 访问 2.ssh Rsync&#xff08;配置不当&#xff0c;未授权…

【Docker】docker-compose简单实战

1、首先要准备好Jar包 docker-compose.yml version: "2.2.4" services:redis:image: rediscontainer_name: redisvolumes:- /redis/data:/data- /redis/redis.conf://usr/local/etc/redis/redis.confnetworks:- kewu-networkkewu:build:context: .dockerfile: dock…

[NOI Online #2 入门组] 未了

[NOI Online #2 入门组] 未了 题目描述 由于触犯天神&#xff0c;Sisyphus 将要接受惩罚。 宙斯命 Sisyphus 推一块巨石上长度为 L L L 的山坡。Sisyphus 匀速向上推的速度为每年 v v v 的长度&#xff08;由于是匀速&#xff0c;故经过 1 2 \frac{1}{2} 21​ 年将能向上…

Gooxi发布最新AI服务器:加速生成式AI落地 更懂AI

近日&#xff0c;Gooxi发布最新训推一体AI服务器&#xff0c;以大容量内存和灵活的高速互连选项满足各种AI应用场景&#xff0c;最大可能支持扩展插槽&#xff0c;从而大幅提升智能算力性能&#xff0c;以最优的性能和成本为企业的模型训练推理落地应用提供更好的通用算力。 AI…

主从Reactor服务器

目录&#xff1a; 目录&#xff1a; 目标&#xff1a; 本文讲解思路&#xff1a; 各模块的功能以及代码&#xff1a; 1.服务器相关模块&#xff1a;服务器模块的功能是对所有的连接以及线程进⾏管理 2.协议相关模块&#xff1a;协议模块是对当前的Reactor模型服务器提供应…

【HarmonyOS】Stage 模型 - 应用配置文件

如图所示&#xff1a; Stage 模型应用配置文件主要有两类&#xff1a; 全局配置文件。放在 AppScope 目录下&#xff0c;app.json5。用来配置应用全局的信息。模块配置文件&#xff0c;放在每个模块里&#xff0c;module.json5。用来配置模块的信息。 一、全局配置文件 示…

python的取余与计算商的关系

在Python中&#xff0c;取余数使用的是 % 运算符。它计算一个数除以另一个数的余数&#xff0c;并将结果返回。 例如&#xff0c;如果你执行 a % b&#xff0c;它将返回 a 除以 b 的余数。 这在编程中有很多用途&#xff0c;其中一些包括&#xff1a; 判断奇偶性&#xff1a…

LeetCode1657确定两个字符串是否接近

题目描述 如果可以使用以下操作从一个字符串得到另一个字符串&#xff0c;则认为两个字符串 接近 &#xff1a; 操作 1&#xff1a;交换任意两个 现有 字符。例如&#xff0c;abcde -> aecdb操作 2&#xff1a;将一个 现有 字符的每次出现转换为另一个 现有 字符&#xff0…

【数据可视化01】matplotlib实例3之数据统计

目录 一、引言二、实例介绍1.百分位数为横条形图2.箱线图定制化3.带有自定义填充颜色的箱线图4.箱线图5.箱线图和小提琴图6.二维数据集的置信椭圆 一、引言 matplotlib库 可以用来创建各种静态、动态、交互式的图形&#xff0c;并广泛应用于数据分析和数据可视化领域。 二、实…

通过Doxygen+Breathe+Sphinx生成代码文档

环境 CentOS Linux 7DoxygenBreathe, Sphinx (安装在同一python 环境下) ➜ build yum install doxygen # 安装最新版本的 Sphinx 及依赖。 # -U 将所有指定的软件包升级到最新的可用版本, 依赖项的处理取决于所使用的升级策略。 ➜ build pip3 install -U Sphinx ➜ buil…

Java并发编程——线程基础

Java并发编程的核心之一就是线程&#xff08;Thread&#xff09;。线程是程序执行流的最小单元&#xff0c;Java通过线程来实现并发编程。以下是Java线程的一些基础概念&#xff1a; 1. 线程的创建 在Java中&#xff0c;创建线程主要有两种方式&#xff1a; 继承Thread类&am…

贷款中介CRM管理系统解决方案

一、贷款中介行业背景介绍 随着贷款中介行业的快速发展&#xff0c;贷款中介业务逐渐成为企业和个人融资的重要渠道。然而&#xff0c;贷款中介行业存在信息不对称、风险控制不力等难题。给金融稳定带来潜在风险。 二、方案目的和意义 鑫鹿贷款中介系统解决方案旨在规范贷款中…

蓝桥杯单片机组——国赛1 各模块的基础模板

本文为续写个人专栏&#xff1a;蓝桥杯单片机组基础专栏 由于国赛代码体量较为庞大&#xff0c;各个模块涉及时序、消影、去鬼影、消冲突等操作 因此本文基于小蜜蜂老师代码风格编写&#xff0c;并根据实际有改动 本文用于汇总基础的模块程序&#xff0c;更进阶的操作请查看…

Elasticsearch查看集群信息,设置ES密码,Kibana部署

Elasticsearch查看集群信息&#xff0c;设置ES密码&#xff0c;Kibana部署 查看集群信息查看节点信息查看集群健康状态查看分片信息查看其他集群信息 Kibana部署安装设置ES密码 查看集群信息 查看节点信息 curl http://127.0.0.1:9200/_cat/nodes?v 参数说明&#xff1a; ip…

研究生学习---找工作

规划 研一~研二上学期完成小论文&#xff0c;实习&#xff0c;秋招 竞赛&#xff1a;kaggle&#xff1f; 面试题一般简单且为原题&#xff0c;笔试题目很难&#xff0c;不会出原题 项目 找工作软件

SwiftUI中三大渐变色的介绍

在SwiftUI中&#xff0c;渐变色是一种常用的视觉效果&#xff0c;用于创建平滑过渡的颜色变化。通过使用渐变色&#xff0c;我们可以实现丰富多彩的界面设计&#xff0c;增强用户体验。 1. 渐变色的种类和用途 种类&#xff1a; 线性渐变&#xff08;Linear Gradient&#x…