Need to know


同学给我说的,我记录下都要学,针对Java的。


1.Httpclient

2.爬虫

3.解析字符串url

4.对数据库的增删改查

5.RPC框架

6.网络(数据传输,协议,数据加密)

7.操作系统


自己感觉跟个小白痴一样,大学四年哗哗地过去,没走过的路到底还是要一个坑一个坑地再过一过。开始了就比没开始的强。有技术才能不会被人小看。


最近刚开始学Python,和同学聊了之后,感觉有必要把Java系统重新学习下,都不能半途而废,要经常回看下自己的知识网,一个接一个稳着点亮技术栈。



课程设计报告:总体方案设计说明 一、软件开发环境配置 本系统采用C++作为核心编程语言,结合Qt 5.12.7框架进行图形用户界面开发。数据库管理系统选用MySQL,用于存储用户数据与小精灵信息。集成开发环境为Qt Creator,操作系统平台为Windows 10。 二、窗口界面架构设计 系统界面由多个功能模块构成,各模块职责明确,具体如下: 1. 起始界面模块(Widget) 作为应用程序的入口界面,提供初始导航功能。 2. 身份验证模块(Login) 负责处理用户登录与账户注册流程,实现身份认证机制。 3. 游戏主大厅模块(Lobby) 作为用户登录后的核心交互区域,集成各项功能入口。 4. 资源管理模块(BagWidget) 展示用户持有的全部小精灵资产,提供可视化资源管理界面。 5. 精灵详情模块(SpiritInfo) 呈现选定小精灵的完整属性数据与状态信息。 6. 用户名录模块(UserList) 系统内所有注册用户的基本信息列表展示界面。 7. 个人资料模块(UserInfo) 显示当前用户的详细账户资料与历史数据统计。 8. 服务器精灵选择模块(Choose) 对战准备阶段,从服务器可用精灵池中选取参战单位的专用界面。 9. 玩家精灵选择模块(Choose2) 对战准备阶段,从玩家自有精灵库中筛选参战单位的操作界面。 10. 对战演算模块(FightWidget) 实时模拟精灵对战过程,动态呈现战斗动画与状态变化。 11. 对战结算模块(ResultWidget) 对战结束后,系统生成并展示战斗结果报告与数据统计。 各模块通过统一的事件驱动机制实现数据通信与状态同步,确保系统功能的连贯性与数据一致性。界面布局遵循模块化设计原则,采用响应式视觉方案适配不同显示环境。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
<think>我们正在讨论Spring Boot开发中的循环依赖机制。虽然引用内容没有直接解释循环依赖,但我们可以结合Spring框架的设计理念和已知知识来阐述。 注意:Spring Boot基于Spring框架,因此循环依赖的处理机制与Spring框架一致。 循环依赖是指两个或多个Bean相互依赖,形成闭环。例如:BeanA依赖BeanB,BeanB又依赖BeanA。 Spring通过三级缓存解决单例Bean的循环依赖问题。三级缓存分别是: 1. singletonObjects:存储完全初始化好的Bean。 2. earlySingletonObjects:存储提前暴露的Bean(尚未完成属性注入和初始化方法)。 3. singletonFactories:存储Bean的工厂对象(用于创建提前暴露的Bean)。 解决循环依赖的步骤(以BeanA和BeanB相互依赖为例): 1. 创建BeanA:实例化BeanA(调用构造函数),此时BeanA还未设置属性,处于“早期状态”。将BeanA的工厂对象放入singletonFactories缓存。 2. 填充BeanA的属性:发现需要注入BeanB。 3. 创建BeanB:实例化BeanB,将BeanB的工厂对象放入singletonFactories。 4. 填充BeanB的属性:发现需要注入BeanA。 5. 从缓存中获取BeanA:此时在singletonFactories中找到了BeanA的工厂对象,通过工厂对象获取BeanA的早期引用(即使BeanA还未完成初始化),并将BeanA从singletonFactories升级到earlySingletonObjects(同时移除singletonFactories中的对应工厂)。 6. 将获取到的BeanA早期引用注入到BeanB中,完成BeanB的初始化,并将BeanB放入singletonObjects(同时移除earlySingletonObjects和singletonFactories中的BeanB)。 7. 此时BeanA就能成功注入BeanB(此时BeanB已经初始化完成),完成BeanA的初始化,并将BeanA放入singletonObjects。 注意:Spring只能解决单例作用域且通过setter方法注入(或字段注入)的循环依赖。如果使用构造函数注入,则无法解决循环依赖,因为构造函数注入需要先完成构造函数的调用,而这时Bean尚未创建完成,无法提前暴露引用。 在Spring Boot中,如果出现无法解决的循环依赖(比如构造函数注入的循环依赖),启动时会抛出BeanCurrentlyInCreationException异常。 另外,Spring Boot 2.6版本之后默认禁止循环依赖(可以通过spring.main.allow-circular-references=true开启),因此建议在开发中避免循环依赖。 示例代码: ```java @Component public class BeanA { @Autowired private BeanB beanB; } @Component public class BeanB { @Autowired private BeanA beanA; } ``` 这种情况下,Spring能够通过三级缓存解决循环依赖。 但是构造函数注入的循环依赖无法解决: ```java @Component public class BeanA { private BeanB beanB; @Autowired public BeanA(BeanB beanB) { this.beanB = beanB; } } @Component public class BeanB { private BeanA beanA; @Autowired public BeanB(BeanA beanA) { this.beanA = beanA; } } ``` 这段代码会导致启动失败。 引用说明: 虽然引用中没有直接关于循环依赖的说明,但我们知道Spring框架的创新和发展中包含了对依赖注入机制的完善[^2]。同时,Spring框架的设计哲学强调高标准的代码质量和无循环依赖的包结构[^3],但在Bean级别上,Spring通过三级缓存机制巧妙地解决了循环依赖问题。 最后,关于循环依赖的检测,在Spring Boot应用启动时,如果出现循环依赖且无法解决,会抛出异常。我们也可以通过IDE的插件或静态代码分析工具来检测潜在的循环依赖。 §§相关问题§§ 1. Spring的三级缓存具体如何工作?请详细描述各级缓存的作用。 2. 为什么构造函数注入的循环依赖无法解决? 3. 如何在Spring Boot中禁止循环依赖?禁止后如何避免启动失败? 4. 除了循环依赖,Spring Bean的创建过程中还有哪些关键步骤? </think>在Spring Boot开发中,循环依赖的解决机制基于Spring框架的三级缓存设计,这是Spring容器初始化单例Bean时的核心处理逻辑。以下是详细机制分析: ### 一、三级缓存机制 Spring通过三级缓存解决循环依赖问题,具体结构如下: 1. **singletonObjects**(一级缓存) `ConcurrentHashMap<String, Object>` 存储**已完成全部初始化**的Bean实例(属性注入、初始化方法已完成)。 ```java /** Cache of singleton objects: bean name to bean instance */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); ``` 2. **earlySingletonObjects**(二级缓存) `HashMap<String, Object>` 存储**提前暴露的早期引用**(已实例化但未完成属性注入的Bean)。 ```java /** Cache of early singleton objects: bean name to bean instance */ private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); ``` 3. **singletonFactories**(三级缓存) `HashMap<String, ObjectFactory<?>>` 存储**Bean工厂对象**(用于生成Bean的早期引用)。 ```java /** Cache of singleton factories: bean name to ObjectFactory */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); ``` ### 二、解决流程示例(以BeanA和BeanB循环依赖为例) 假设存在以下代码: ```java @Component public class BeanA { @Autowired private BeanB beanB; // 依赖BeanB } @Component public class BeanB { @Autowired private BeanA beanA; // 依赖BeanA } ``` 容器处理流程: 1. **创建BeanA** - 实例化`BeanA`(调用构造函数) - 将`BeanA`的工厂对象存入**三级缓存**(`singletonFactories`) - 开始注入`BeanA`的属性,发现需要`BeanB` 2. **创建BeanB** - 实例化`BeanB`(调用构造函数) - 将`BeanB`的工厂对象存入**三级缓存** - 开始注入`BeanB`的属性,发现需要`BeanA` 3. **解决BeanB对BeanA的依赖** - 从**三级缓存**获取`BeanA`的工厂对象 - 通过工厂生成`BeanA`的早期引用(未完成初始化的对象) - 将此早期引用放入**二级缓存**(`earlySingletonObjects`) - 将早期引用注入到`BeanB`中 - `BeanB`完成初始化,移入**一级缓存** 4. **完成BeanA初始化** - 获取已初始化的`BeanB`实例(来自一级缓存) - 将`BeanB`注入`BeanA` - `BeanA`完成初始化,移入**一级缓存** - 清理二级和三级缓存中的相关条目 > 💡 **关键点**:通过提前暴露未完成初始化的Bean引用(三级缓存),打破循环依赖的死锁,此机制仅支持**单例Bean**和**字段/Setter注入**的场景。 ### 三、Spring Boot的特殊处理 1. **版本差异** - Spring Boot 2.6+ 默认**禁止循环依赖**(可通过配置启用): ```properties spring.main.allow-circular-references=true ``` - 早期版本默认允许但会输出警告日志 2. **启动检测** Spring Boot启动时通过`BeanCurrentlyInCreationException`明确标识循环依赖链: ``` Requested bean is currently in creation: Is there an unresolvable circular reference? ``` ### 四、无法解决的场景 1. **构造函数注入循环依赖** ```java @Component public class BeanA { private final BeanB beanB; public BeanA(BeanB beanB) { // 构造函数注入 this.beanB = beanB; } } ``` 原因:实例化前无法提前暴露对象引用。 2. **原型作用域(Prototype) Bean** Spring不缓存原型Bean,无法通过三级缓存解决循环依赖。 3. **AOP代理对象** 需通过`SmartInstantiationAwareBeanPostProcessor`特殊处理(如`AbstractAutoProxyCreator`)[^4]。 > Spring框架的设计哲学强调代码质量与无循环依赖的包结构[^3],建议优先通过代码重构(如提取公共逻辑、使用事件驱动)避免循环依赖。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值