今天在看Java八股文时,对这里产生了一些疑惑,因为在目前做的练手项目中还没有用到过除了new以外的新建对象方式,在请教了其他前辈后对此有了新的理解,所以专门记录以用于梳理思路和复习基础。这里着重讲解反射机制实现新建对象

这里用很经典的一个框架:Spring IOC容器来举例讲解

========================================================================

Spring的**控制反转(IOC)**容器是反射最经典的应用场景。其核心逻辑是:通过反射动态加载用户定义的类,创建对象,并注入依赖

1. 场景说明

假设我们有一个UserService类,依赖UserDao类(用户定义的类):

// 用户定义的Dao类(数据访问层)
public class UserDao {public void save(User user) {System.out.println("保存用户到数据库:" + user);}
}// 用户定义的Service类(业务层),依赖UserDao
public class UserService {private UserDao userDao; // 依赖注入的属性// 构造器注入(或setter注入)public UserService(UserDao userDao) {this.userDao = userDao;}public void register(User user) {userDao.save(user); // 调用Dao的方法}
}

用户通过Spring配置文件(或注解)声明Bean:

<!-- applicationContext.xml 配置文件 -->
<beans><!-- 声明UserDao Bean:类名是com.example.UserDao --><bean id="userDao" class="com.example.UserDao"/><!-- 声明UserService Bean:依赖userDao --><bean id="userService" class="com.example.UserService"><constructor-arg ref="userDao"/> <!-- 构造器注入userDao --></bean>
</beans>

2. Spring IOC容器的工作流程(反射应用细节)

Spring容器(如ClassPathXmlApplicationContext)启动时,会执行以下反射相关的步骤,创建UserServiceUserDao对象:

步骤1:加载配置文件,解析Bean定义

Spring读取applicationContext.xml,解析出两个Bean定义:

  • userDao:类名com.example.UserDao,无依赖;
  • userService:类名com.example.UserService,依赖userDao
步骤2:通过反射加载类(Class.forName()

① 解析配置文件,获取类名

Spring的XmlBeanDefinitionReader(XML配置解析器)读取applicationContext.xml,解析每个<bean>标签的class属性:

② 加载类的Class对象

  • 对于userDaoclass属性的值是"com.example.UserDao"
  • 对于userServiceclass属性的值是"com.example.UserService"

Spring使用Class.forName()加载每个类的Class对象(运行时动态加载):

// 加载UserDao类(com.example.UserDao)
Class<?> userDaoClass = Class.forName("com.example.UserDao", false, classLoader);
// 加载UserService类(com.example.UserService)
Class<?> userServiceClass = Class.forName("com.example.UserService", false, classLoader);
步骤3:通过反射获取构造器(getConstructor()

Spring需要获取类的构造器,才能创建对象。对于UserDao(无依赖),获取无参构造器;对于UserService(依赖UserDao),获取有参构造器(参数类型为UserDao):

// 获取UserDao的无参构造器(UserDao有默认无参构造器)
Constructor<?> userDaoConstructor = userDaoClass.getConstructor();
// 获取UserService的有参构造器(参数类型为UserDao)
Constructor<?> userServiceConstructor = userServiceClass.getConstructor(UserDao.class);
步骤4:通过反射创建对象(newInstance()
  • 创建UserDao对象:用无参构造器创建:
  •   // 创建UserDao对象(无参构造器)UserDao userDao = (UserDao) userDaoConstructor.newInstance();

  • 创建UserService对象:用有参构造器创建,传入userDao对象(依赖注入):
  •   // 创建UserService对象(有参构造器,注入userDao)UserService userService = (UserService) userServiceConstructor.newInstance(userDao);

步骤5:将对象存入IOC容器

Spring将创建的userDaouserService对象存入IOC容器(如HashMap,键是bean id,值是对象):

// 模拟IOC容器(HashMap)
Map<String, Object> iocContainer = new HashMap<>();
iocContainer.put("userDao", userDao);
iocContainer.put("userService", userService);
步骤6:使用Bean(从容器中获取)

用户通过ApplicationContext从容器中获取userService对象,无需手动new

// 启动Spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 从容器中获取userService对象(无需new)
UserService userService = (UserService) context.getBean("userService");
// 使用userService调用方法(依赖的userDao已注入)
userService.register(new User("zhangsan", 25));

为什么用反射?

  • Spring是通用框架,需要处理任意用户定义的类(如UserServiceOrderServiceProductDao),无法在框架代码中硬编码new UserService()(因为框架开发者不知道用户会定义哪些类)。
  • 反射的动态性Class.forName()加载任意类,newInstance()创建任意对象)满足了这一需求,让Spring能处理无限多的用户类。

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

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

相关文章

TRS(总收益互换)系统架构设计:多市场交易的技术实现分析

一、多市场交易环境的技术特征 1.1 市场机制差异&#xff08;技术视角&#xff09;技术维度典型实现差异交割周期T0/T1/T2等多种结算模式价格稳定机制部分市场存在波动率控制措施系统接入协议FIX 4.4/ITCH/OMD-C等协议族衍生品支持工具种类与中央对手方清算差异1.2 技术挑战分析…

深度学习-卷积神经网络CNN-批量归一化 BatchNorm

为什么需要批量规范化层呢&#xff1f;让我们来回顾一下训练神经网络时出现的一些实际挑战&#xff1a;首先&#xff0c;数据预处理的方式通常会对最终结果产生巨大影响。 回想一下我们应用多层感知机来预测房价的例子。使用真实数据时&#xff0c;我们的第一步是标准化输入特征…

机器学习-支持向量机器(SVM)

0.1 数字识别 from sklearn.svm import SVC from sklearn.metrics import silhouette_score import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.decomposition import PCA from sklearn.feature_extraction import DictVectorizer from sk…

昆山PCB板工厂有哪些?

在长三角电子信息产业版图中&#xff0c;昆山凭借完整的产业链配套和精湛的制造工艺&#xff0c;成为国内PCB&#xff08;印制电路板&#xff09;生产的重要基地。本文精选五家具有代表性的本土工厂&#xff0c;从技术实力到服务特色展开深度剖析&#xff0c;为行业客户提供精准…

rk3588 ubuntu20.04安装包经常出现的问题总结(chatgpt回复)

问题1 问题 我在rk3588 ubuntu20.04安装相关环境的时候经常出现下面类似的问题&#xff0c;如何系统的解决 The following packages have unmet dependencies : openssh-server : Depends: openssh-client ( 1:8.2p1-4ubuntu0.13) but 1:8.2p1-4ubuntu0.11 is to be installed …

从根源到生态:Apache Doris 与 StarRocks 的深度对比 —— 论开源基因与长期价值的优越性

在 OLAP 领域&#xff0c;Apache Doris 与 StarRocks 常被一同提及&#xff0c;两者有着深厚的技术渊源 ——StarRocks 源自 Apache Doris 的代码 Fork&#xff0c;却在后续发展中走向了不同的路径。本文将从代码根源、架构演进、社区生态、功能特性等多维度展开对比。 一、代…

【从零开始学习Redis】项目实战-黑马点评D1

项目实战-黑马点评 项目架构短信登录发送短信验证码 实现思路就是按照上图左一部分&#xff0c; 实现类如下 Slf4j Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {/*** 验证手机号发送验证码** param phone* pa…

自然语言处理的范式转变:从Seq2Seq模型到Transformer架构

Seq2Seq 定义 Seq2Seq是一个Encoder-Decoder结构的网络&#xff0c;它的输入是一个序列&#xff0c;输出也是一个序列&#xff0c; Encoder使用循环神经网络(RNN,GRU&#xff0c;LSTM等)&#xff0c;将一个可变长度的信号序列(输入句子)变为固定维度的向量编码表达&#xff0c;…

【博客系统测试报告】---接口自动化测试

目录 1、需求分析 2、挑选接口 3、设计博客系统的测试用例 4、设计自动化测试框架 test_add.py: test_detail.py: test_getAuthorInfo.py: test_getUserInfo: test_list.py: test_login.py: logger_util.py: request_util.py: yaml_util.py: 1、需求分析 根据业务…

Mysql数据库迁移到GaussDB注意事项

mysql数据库迁移高斯数据库 建议开启高斯数据库M模式&#xff0c;mysql兼容模式&#xff0c;可以直接使用mysql的建表语句&#xff0c;自增主键可以使用AUTO_INCREMENT&#xff0c;如果不开启M模式&#xff0c;只能使用高斯数据库的序列添加自增主键1&#xff1a;如果使用数据库…

苹果正计划大举进军人工智能硬件领域

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Serverless 架构核心解析与应用实践

Serverless 的核心定义与优势‌‌核心定义Serverless&#xff08;无服务器架构&#xff09;是一种云计算模型&#xff0c;开发者无需关注底层服务器管理&#xff0c;由云服务商自动分配资源、弹性扩缩容&#xff0c;并按实际使用量计费‌。其核心特点包括&#xff1a;‌按需计算…

Redis持久化机制详解:RDB与AOF的全面对比与实践指南

目录 一、RDB持久化机制 1.1 RDB概述 1.2 RDB触发机制 1) 手动执行save命令 2) 手动执行bgsave命令 3) Redis正常关闭时 4) 自动触发条件满足时 1.3 RDB详细配置 1.4 RDB实现原理 1.5 RDB的优缺点分析 二、AOF持久化机制 2.1 AOF概述 2.2 AOF工作流程 2.3 AOF同步…

介绍一下jQuery的AJAX异步请求

目录 一、核心方法&#xff1a;$.ajax() 二、简化方法&#xff08;常用场景&#xff09; 1. $.get()&#xff1a;快速发送 GET 请求&#xff08;获取数据&#xff09; 2. $.post()&#xff1a;快速发送 POST 请求&#xff08;提交数据&#xff09; 3. $.getJSON()&#xf…

Win10系统Ruby+Devkit3.4.5-1安装

Win10系统RubyDevkit3.4.5-1安装安装步骤软件工具安装Ruby安装gem mysql2处理libmysql.dll验证mysql2安装步骤 软件工具 mysql-connector-c-6.1.11-winx64.zip rubyinstaller-devkit-3.4.5-1-x64.exe 安装Ruby 执行rubyinstaller-devkit-3.4.5-1-x64.exe&#xff0c;期间可…

社交工程:洞穿人心防线的无形之矛

在网络安全领域&#xff0c;一道无形的裂痕正在迅速蔓延。它不是复杂的零日漏洞&#xff0c;也不是精妙的恶意代码&#xff0c;而是利用人性弱点进行攻击的古老技艺——社交工程。当全球网络安全支出突破千亿美元大关&#xff0c;防火墙筑得越来越高&#xff0c;加密算法越来越…

Go 并发控制利器 ants 使用文档

https://github.com/panjf2000/ants1.1 什么是 ants ants 是一个高性能的 Go 语言 goroutine 池&#xff0c;它能复用已完成任务的 goroutine&#xff0c;避免频繁创建和销毁 goroutine&#xff0c;节省 CPU 与内存开销&#xff0c;并且能限制并发数量防止资源被耗尽。 1.2 安装…

Day57--图论--53. 寻宝(卡码网)

Day57–图论–53. 寻宝&#xff08;卡码网&#xff09; 今天学习&#xff1a;最小生成树。有两种算法&#xff08;Prim和Kruskal&#xff09;和一道例题。 prim 算法是维护节点的集合&#xff0c;而 Kruskal 是维护边的集合。 最小生成树&#xff1a;所有节点的最小连通子图&am…

解决海洋探测数据同步网络问题的新思路——基于智能组网技术的探索

随着海洋探测技术的不断发展&#xff0c;数据同步网络的稳定性和低延迟需求变得愈发重要。海洋探测数据来自多个分布式采集点&#xff0c;这些点需要高效的组网方式来实现实时数据传输。然而&#xff0c;由于海洋环境的特殊性&#xff08;如复杂的网络拓扑、高湿度和极端温度&a…

设计模式笔记_行为型_责任链模式

1. 责任链模式介绍责任链模式&#xff08;Chain of Responsibility&#xff09;是一种行为设计模式&#xff0c;它允许将多个处理器&#xff08;处理对象&#xff09;连接成一条链&#xff0c;并沿着这条链传递请求&#xff0c;直到有一个处理器处理它为止。职责链模式的主要目…