(四)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.rhkb.cn/news/327740.html

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

相关文章

【JavaEE】HTTP 协议

文章目录 一、HTTP 协议1、HTTP 是什么2、理解 "应用层协议"3、理解 HTTP 协议的工作过程4、HTTP 协议格式5、HTTP 请求 (Request)5.1 认识 URL 6、 二、HTTPS1、HTTPS是什么2、"加密" 是什么3、HTTPS 的工作过程3.1 对称加密3.2 非对称加密3.3 证书3.4 完…

VBA_NZ系列工具NZ06:VBA创建PDF文件说明

我的教程一共九套及VBA汉英手册一部&#xff0c;分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的入门&#xff0c;到数据库&#xff0c;到字典&#xff0c;到高级的网抓及类的应用。大家在学习的过程中可能会存在困惑&#xff0c;这么多知识点该如何组织…

Llama 3 超级课堂 -笔记

课程文档&#xff1a; https://github.com/SmartFlowAI/Llama3-Tutorial 课程视频&#xff1a;https://space.bilibili.com/3546636263360696/channel/series 1 环境配置 1.1 创建虚拟环境,名为&#xff1a;llama3 conda create -n llama3 python3.10 1.2 下载、安装 pyt…

论文解读:Self-Prompt Mechanism for Few-Shot Image Recognition

文章汇总 存在的问题 由于提示文本和图像特征之间固有的模态差异&#xff0c;常规的提示方法的性能受到限制。 动机 让视觉信息自己给自己提示 解决办法 SPM涉及到图像编码器跨空间和通道维度产生的固有语义特征的系统选择&#xff0c;从而产生自提示信息。随后&#xff…

nginx反向代理使用(详细版)

1. 下载nginx&#xff0c;解压&#xff1b;&#xff08;随便放在哪里&#xff09; 2. 在nginx-1.26.0文件夹下创建web文件夹&#xff0c;继续在web文件夹下创建abcd.test.cn文件夹&#xff08;文件夹的名字就叫abcd.test.cn&#xff09;&#xff1b; 3. 配置前端代理&#xff…

人工智能应用正在改变我们的生活

在这个AI蓬勃发展的时代&#xff0c;你如何使用人工智能&#xff1f;如果您认为还没有&#xff0c;请再想一想。人工智能已经为我们的许多日常活动提供了动力&#xff0c;尽管您可能还没有有意将其用作工具&#xff0c;但这种情况可能会在不久的将来发生变化。随着顶尖科技公司…

二叉树的前序遍历(leetcode)

144. 二叉树的前序遍历 - 力扣&#xff08;LeetCode&#xff09; 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 这道题的启发性真的很强 &#xff0c;这里必须传入i的指针进去&#xff0c;下一次栈帧i&#xff0c;但回到了上一层i又变回到了原来的i&#…

霍廷格电源 Tru plasma DC3030 通快DC3040 MF3030

霍廷格电源 Tru plasma DC3030 通快DC3040 MF3030

(十)Python基础练习题一(50道选择题)#Python

本文整理了Python基础知识相关的练习题&#xff0c;共50道&#xff0c;适用于刚入门初级Python想巩固基础的同学。来源&#xff1a;如荷学数据科学题库&#xff08;技术专项-Python一&#xff09;。 1&#xff09; 2&#xff09; 3&#xff09; 4&#xff09; 5&#xff09; 6…

LeetCode题练习与总结:不同的二叉搜索树--96

一、题目描述 给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;5示例 2&#xff1a; 输入&#xff1a;n 1 输出&…

【平衡二叉树】AVL树(双旋)

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; C进阶 &#x1f389;其它专栏&#xff1a; C初阶 | Linux | 初阶数据结构 小伙伴们大家好&#xff0c;本片文章将会讲解AVL树的左双选和右双旋的相关内容。 如果看到最后您觉得这篇文章写…

k8s 理论知识基本介绍

目录 一 k8s 理论前言 &#xff08;一&#xff09;微服务是什么 1&#xff0c;应用场景 2&#xff0c;API 是什么 &#xff08;二&#xff09;&#xff0c;微服务 如何做版本迭代 1. Docker镜像构建 2. 版本标记 3. Docker Registry 4. 环境一致性 5. 滚动更新…

C#中json数据序列化和反序列化的最简单方法(C#对象和字符串的相互转换)

文章目录 将C#对象转换为json字符串Newtonsoft模块的安装用Newtonsoft将对象转换为json字符串 将json字符串转换为C#对象 将C#对象转换为json字符串 本介绍将基于C#中的第三方库Newtonsoft进行&#xff0c;因此将分为Newtonsoft模块的安装和使用两部分。该模块的优势在于只需要…

等保2.0的全面解读与实施策略

《网络安全等级保护基本要求》&#xff08;等保2.0&#xff09;是中华人民共和国国家安全部于2019年6月发布的网络安全等级保护标准。该标准规定了我国关键信息基础设施的网络安全等级保护要求和评估标准&#xff0c;对于保障我国网络安全具有重要的意义。下面是对等保2.0的全面…

安全风险 - 如何解决 setAccessible(true) 带来的安全风险?

可能每款成熟的金融app上架前都会经过层层安全检测才能执行上架&#xff0c;所以我隔三差五就能看到安全检测报告中提到的问题&#xff0c;根据问题的不同级别&#xff0c;处理的优先级也有所不同&#xff0c;此次讲的主要是一个 “轻度问题” &#xff0c;个人认为属于那种可改…

利用一段代码轻松绕过PHP授权系统

利用一段代码轻松绕过PHP授权系统 第一步&#xff1a;首先你需要改名全局文件 比如说全局文件 common.php&#xff0c;那么 你将他改为core.php 第二步&#xff1a;创建文件 创建一个文件&#xff0c;和改名前的全局文件名称一样&#xff0c;然后把以下代码复制进去就OK了 …

SpringBoot解决CORS跨域——WebMvcConfigurationSupport

前端请求后端报错了。 状态码&#xff1a;403 返回错误&#xff1a;Invalid coRs request 增加配置类WebMvcConfig Configuration public class WebMvcConfig extends WebMvcConfigurationSupport {Overridepublic void addCorsMappings(CorsRegistry registry) {// 允许跨域…

【java】异常与错误

Throwable包括Error和Expected。 Error Error错误是程序无法处理的&#xff0c;由JVM产生并抛出的。 举例&#xff1a;StackOverflowError \ ThreadDeath Expected Expected异常包括两类&#xff0c;即受检异常(非运行时异常)和非受检异常(运行时异常)&#xff0c;异常往往…

6. RedHat认证-基于公钥的认证方式

6. RedHat认证-基于公钥的认证方式 主要学习客户端访问服务端的时候&#xff0c;免密登录这一方式 注意: 免密登录只是基于公钥认证的一个附带属性(基于公钥认证的方式更加安全&#xff0c;防止黑客暴力破解) 第一步&#xff1a;将客户端生成的秘钥传送到服务器 在客户端通过…

MIT 6.5840(6.824) Lab1:MapReduce 设计实现

1 介绍 本次实验是实现一个简易版本的MapReduce&#xff0c;你需要实现一个工作程序&#xff08;worker process&#xff09;和一个调度程序&#xff08;coordinator process&#xff09;。工作程序用来调用Map和Reduce函数&#xff0c;并处理文件的读取和写入。调度程序用来协…