10Bean的循环依赖+反射机制

A对象中有B属性。B对象中有A属性。这就是循环依赖。我依赖你,你也依赖我。
比如:丈夫类Husband,妻子类Wife。Husband中有Wife的引用。Wife中有Husband的引用。
在这里插入图片描述

package com.sunsplanter.spring6.bean;public class Husband {private String name;private Wife wife;
}
package com.sunsplanter.spring6.bean;public class Wife {private String name;private Husband husband;
}

Spring解决循环依赖的机理十、回顾反射机制

Spring只能解决setter方法注入的单例bean之间的循环依赖。
1.set方法+两个单例Bean存在循环依赖(即ClassA依赖ClassB,ClassB又依赖ClassA,形成依赖闭环):可以解决。Spring在创建ClassA对象后,不需要等给属性赋值,直接将其曝光到bean缓存当中。在解析ClassA的属性时,又发现依赖于ClassB,再次去获取ClassB,当解析ClassB的属性时,又发现需要ClassA的属性,但此时的ClassA已经被提前曝光加入了正在创建的bean的缓存中,则无需创建新的的ClassA的实例,直接从缓存中获取即可。从而解决循环依赖问题。

Spring为什么可以解决set + singleton模式下循环依赖?“提前曝光,往后赋值”
根本的原因在于:这种方式可以做到将“实例化Bean”和“给Bean属性赋值”这两个动作分开去完成。
实例化Bean的时候:调用无参数构造方法来完成。此时可以先不给属性赋值,可以提前将该Bean对象“曝光”给外界。
给Bean属性赋值的时候:调用setter方法来完成。
两个步骤是完全可以分离开去完成的,并且这两步不要求在同一个时间点上完成。
也就是说,Bean都是单例的,我们可以先把所有的单例Bean实例化出来,放到一个集合当中(我们可以称之为缓存),所有的单例Bean全部实例化完成之后,以后我们再慢慢的调用setter方法给属性赋值。这样就解决了循环依赖的问题。

2.set方法+1个单例Bean和1个多例Bean存在循环依赖可以解决,同1。
3.set方法+2个多例Bean存在循环依赖无法解决。Spring只对scope为singleton的Bean提前曝光,多例Bean无法提前曝光
4.。构造方法注入:不论单例、多例,均可能创建对象失败。

测试Set注入解决两个单例Bean存在的循环依赖问题:

package com.circular_dependency;public class Husband {private String name;private Wife wife;public void setName(String name) {this.name = name;}public String getName() {return name;}public void setWife(Wife wife) {this.wife = wife;}// toString()方法重写时需要注意:若直接输出husband,会去调用husband的toString方法,而Husband的toString方法又要输出Wife,转而调用调用Wife的toString方法// 导致出现递归导致的栈内存溢出错误。输出husband.getName()。@Overridepublic String toString() {return "Husband{" +"name='" + name + '\'' +", wife=" + wife.getName() +'}';}
}
package com.circular_dependency;public class Wife {private String name;private Husband husband;public void setName(String name) {this.name = name;}public String getName() {return name;}public void setHusband(Husband husband) {this.husband = husband;}// toString()方法重写时需要注意:若直接输出husband,会去调用husband的toString方法,而Husband的toString方法又要输出Wife,转而调用调用Wife的toString方法// 导致出现递归导致的栈内存溢出错误。输出husband.getName()。@Overridepublic String toString() {return "Wife{" +"name='" + name + '\'' +", husband=" + husband.getName() +'}';}
}

回顾反射机制

1.不使用反射机制调用方法

//用system对象调用login方法登录,成功则boolean为true
boolean success = systemService.login("admin", "admin123");

若不使用反射机制,调用一个方法,一般涉及到4个要素:
● 调用哪个对象的(systemService)
● 哪个方法(login)
● 传什么参数(“admin”, “admin123”)
● 返回什么值(success)


2.1使用反射机制调用方法
假设存在一个类:

public class SystemService {public void logout(){System.out.println("退出系统");}public boolean login(String username, String password){if ("admin".equals(username) && "admin123".equals(password)) {return true;}return false;}public boolean login(String password){if("110".equals(password)){return true;}return false;}
}

目标:获取login(String,String) 方法并调用

第一步:创建对象(四要素之首:调用哪个对象的)。首先需要获取这个类Class。

Class clazz = Class.forName("com.powernode.reflect.SystemService");
//先获取构造方法,用构造方法创建对象
Constructor<?> con = clazz.getDeclaredConstructor();
con.newInstance();

第二步:获取方法login(String,String)(四要素之一:哪个方法)。拿到Class之后,调用getDeclaredMethod()方法可以获取到方法并赋值给loginMethod。

//第二,第三个参数指定方法的参数类型
Method loginMethod = clazz.getDeclaredMethod("login", String.class, String.class);

第三步:调用方法

Object retValue = loginMethod.invoke(obj, "admin", "admin123");

在上述三步中,四要素为:
● 哪个对象:obj
● 哪个方法:loginMethod
● 传什么参数:“admin”, “admin123”
● 返回什么值:retValue

2.2使用反射机制调用set方法给属性赋值
假设有如下类:

package com.sunsplanter.reflect;public class User {private String name;private int age;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 "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}

知道以下这几条信息:
● 类名是:com.sunsplanter.reflect.User
● 该类中有String类型的name属性和int类型的age属性。
● 另外你也知道该类的设计符合javabean规范。(也就是说属性私有化,对外提供setter和getter方法)

目标:通过反射机制给User对象的name属性赋值zhangsan,给age属性赋值20岁。

package com.sunsplanter.reflect;import java.lang.reflect.Method;public class UserTest {public static void main(String[] args) throws Exception{// 已知类名String className = "com.sunsplanter.reflect.User";// 已知属性名String propertyName = "age";// 创建对象Class<?> clazz = Class.forName(className);Object obj = clazz.newInstance(); // 根据属性名获取setter方法名,而方法名必然符合规范,也即setAge//先将age全部转大写AGE,截取第一个A,再用subString获取age第一个以后的字母ge,一起拼成Age.String setMethodName = "set" + propertyName.toUpperCase().charAt(0) + propertyName.substring(1);// 获取MethodMethod setMethod = clazz.getDeclaredMethod(setMethodName, int.class);// 调用MethodsetMethod.invoke(obj, 20);System.out.println(obj);}
}

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

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

相关文章

亿尚网:撤柜上线电商+直播将成为美妆行业发展的绝佳组合

亿尚网&#xff1a;撤柜上线电商直播将成为美妆行业发展的绝佳组合 来源&#xff1a; 编辑&#xff1a;亿尚风范 时间&#xff1a;2024-01-09 随着社交媒体的兴起&#xff0c;网红经济逐渐成为市场中的一股不可忽视的力量。而在这其中&#xff0c;直播电商的模式更是为网红们…

没有货源是不是就没办法在家做抖店?打包发货怎么完成?解答如下

我是王路飞。 有人问了我一个问题&#xff1a;无货源模式的抖店&#xff0c;自己一个人在家里做不了是吧&#xff1f;毕竟打包发货这些问题怎么解决呢&#xff1f; 店铺要是发货不及时被平台罚款怎么办&#xff1f;产品有质量问题怎么解决呢&#xff1f;店铺一直不出单怎么办…

kubernetes RBAC Authentication 详解

开头语 写在前面&#xff1a;如有问题&#xff0c;以你为准&#xff0c; 目前24年应届生&#xff0c;各位大佬轻喷&#xff0c;部分资料与图片来自网络 内容较长&#xff0c;页面右上角目录方便跳转 Kubernetes 安全架构 K8S安全控制框架主要由下面3个阶段进行控制&#xf…

二分查找

二分查找(binary search)是一种基于分治策略的高效搜索算法。它利用数据的有序性&#xff0c;每轮缩小一半搜索范围&#xff0c;直至找到目标元素或搜索区间为空为止。 例&#xff1a;给定一个n 的数组 nums &#xff0c;元素按从小到大的顺序排列且不重复。请查找并返回元素 …

一键转换,创新无限:将HTML轻松转化为PDF!

在数字时代&#xff0c;HTML与PDF已成为信息传递的两大主流格式。然而&#xff0c;在这两者之间转换常常让人感到困扰。现在&#xff0c;有了我们的创新工具&#xff0c;您只需轻点一下&#xff0c;即可一键将HTML转化为PDF&#xff01; 首先&#xff0c;我们要进入首助编辑高…

【产品人卫朋】硬件产品经理:从入门到精通

目录 本文目录 1. 前言说明 2. 内容说明 3. 资料包说明 作者简介 本文目录 1. 前言说明 2. 内容说明 3. 资料包说明 1. 前言说明 本篇内容节选自实体书《硬件产品经理&#xff1a;从入门到精通》。 2. 内容说明 鉴于硬件产品的特殊性&#xff0c;不同产品阶段的时间间…

react输入框检索树形(tree)结构

input搜索框搜索树形子级内容1. input框输入搜索内容2. 获取tree结构数据3. 与tree匹配输入的内容&#xff0c;tree是多维数组&#xff0c;一级一级的对比输入的内容是否匹配&#xff0c;用forEach循环遍历数据&#xff0c;匹配不到在往下找&#xff0c;直到找到为null &#x…

MIT_线性代数笔记:第 25 讲 对称矩阵和正定性

目录 对称矩阵 Symmetric matrices实特征值 Real eigenvalues正定矩阵 Positive definite matrices 对称矩阵是最重要的矩阵之一&#xff0c;其特征值为实数并且拥有一套正交特征向量。正定矩阵的性质则更好。 对称矩阵 Symmetric matrices 包含特殊性质的矩阵&#xff0c;例如…

Probabilistic Forecasting with Temporal Convolutional Neural Network

Abstract 我们提出了一种基于卷积神经网络&#xff08;CNN&#xff09;的概率预测框架&#xff0c;用于多个相关时间序列预测。该框架可用于估计参数和非参数设置下的概率密度。更具体地说&#xff0c;构建基于扩张因果卷积网络的堆叠残差块来捕获序列的时间依赖性。与表示学习…

Certum与Geotrust的SSL证书区别

Certum和GeoTrust都是知名的CA认证机构&#xff0c;这两个品牌下的SSL证书在多个方面存在一些差异。今天就随SSL盾小编了解Certum与Geotrust证书的区别。 一、Certum机构背景 Certum是波兰的一家CA认证机构&#xff0c;成立于2002年&#xff0c;至今已有近20多年的历史。旗下有…

LeetCode-棒球比赛(682)

题目描述&#xff1a; 你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成&#xff0c;过去几回合的得分可能会影响以后几回合的得分。 比赛开始时&#xff0c;记录是空白的。你会得到一个记录操作的字符串列表 ops&#xff0c;其中 ops[i] 是你需要记录的第…

基于ZU19EG的100G-UDP解决方案

概述 本文档介绍ZU19EG与Mellanox CX6 100G网卡通信解决方案。 环境配置 FPGA硬件&#xff1a;519-ZU19EG的4路100G光纤PCIe加上计算卡 电脑&#xff1a;国产国鑫主板&#xff08;双PCU&#xff09;&#xff1a;Gooxi G2DA-B CPU:Intel Xeon Silver 2.2GHz 内存&#xff1…

Asp .Net Web应用程序(.Net Framework4.8)网站发布到IIS

开启IIS 如果已开启跳过这步 打开控制面板-程序 打开IIS 发布Web程序&#xff08;.Net Framework 4.8 web网页&#xff09; 进入IIS管理器新建一个应用池 新建一个网站 网站创建完毕 为文件夹添加访问权限 如果不添加访问权限&#xff0c;运行时将会得到如下错误 设置权限 勾…

kubernetes ResourceQuotas Limits(资源配额)

开头语 写在前面&#xff1a;如有问题&#xff0c;以你为准&#xff0c; 目前24年应届生&#xff0c;各位大佬轻喷&#xff0c;部分资料与图片来自网络 内容较长&#xff0c;页面右上角目录方便跳转 简介 当多个用户或团队共享具有固定节点数目的集群时&#xff0c;人们会…

使用串口 DMA 模式接收不定长数据

一、简介 曾经遇到客户有一个需求&#xff0c;需要用串口 DMA 的方式接收不定长度的数据&#xff0c;DMA 有个缺点就是在每次传输前需要设定好传输的字节长度&#xff0c;这种方式显然对于接收不定长度的数据来说没有那么灵活。但 DMA 也有着显著的优点&#xff0c;如可直接访…

JS新手入门笔记整理:对象

对象可以分为两种&#xff1a;一种是“自定义对象”&#xff0c;另外一种是“内置对象”。自定义对象&#xff0c;指的是需要我们自己定义的对象。内置对象&#xff0c;指的是不需要我们自己定义的&#xff08;即系统已经定义好的&#xff09;、可以直接使用的对象。在JavaScri…

abp vnext 下载指定版本的项目

开发环境 Win11 vs2022 abp vnext 下载地址&#xff1a;Get Started | ABP.IO 下载abp框架之前&#xff0c;需要先安装CLI&#xff0c;打开命令提示符&#xff0c;执行以下命令即可&#xff0c;这个也可以指定版本下载&#xff0c;这里就不做介绍了&#xff0c;以及删除命令…

【MySQL】数据库之Redis的持久化

目录 一、Redis的高可用 1.1什么是高可用 1.2Redis的高可用技术 1.3持久化功能 1.4Redis持久化的方式 二、Redis的持久化之RDB 2.1RDB持久化的触发方式 触发条件 RDB持久化的触发分为手动触发和自动触发两种。 &#xff08;1&#xff09;手动触发 &#xff08;2&…

‘pip‘ 不是内部或外部命令、ImportError: cannot import name ‘SCHEME_KEYS‘

错误一&#xff1a;启动程序中出现致命错误:无法使用“f:\pythonv\scripts\python.exe” G:\pythonv\scripts\ pip.exe” 错误二&#xff1a;‘pip‘ 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 错误三&#xff1a;ImportError: cannot import name SCH…

九、分布式锁 —— 超详细操作演示!!!

九、分布式锁 —— 超详细操作演示&#xff01; 九、分布式锁9.1 分布式锁的工作原理9.2 问题引入9.2.1 场景9.2.2 实现9.2.3 分析 9.3 setnx 实现方式9.3.1 原理9.3.2 实现9.3.3 问题 9.4 为锁添加过期时间9.4.1 原理9.4.2 实现9.4.3 问题 9.5 为锁添加标识9.5.1 原理9.5.2 实…