从0开始回顾Spring---系列一

简介: IOC1、什么是IOC?什么是DI?IOClOC:控制反转,以前创建对象的时候都需要自己手动的new,而现在创建对象的任务全部交给spring来管理,降低了对象之间的耦合,当我们需要使用这个对象的时候直接从IOC中获取就行了。DIDI(依赖注入):指的是容器在实例化对象的时候把它依赖的类注入给它。2、IOC的实现原理?Spring的IoC的底层实现原理是工厂模式+反射+XML配置文件 。即先写一个接口,再写该接口的一个实现类,通过解析XML配置文件获取该实现类的配置属性,在工厂类中使用反射机制得到实现类相应的对象。3、 说说BeanFactory和ApplicantCon

IOC

1、什么是IOC?什么是DI?


IOC

lOC:控制反转以前创建对象的时候都需要自己手动的new,而现在创建对象的任务全部交给spring来管理,降低了对象之间的耦合,当我们需要使用这个对象的时候直接从IOC中获取就行了。

DI

DI(依赖注入)指的是容器在实例化对象的时候把它依赖的类注入给它。

2、IOC的实现原理?


Spring的IoC的底层实现原理是工厂模式+反射+XML配置文件 。即先写一个接口,再写该接口的一个实现类,通过解析XML配置文件获取该实现类的配置属性,在工厂类中使用反射机制得到实现类相应的对象。

3、 说说BeanFactory和ApplicantContext?

可以这么形容,BeanFactory是Spring的“心脏”ApplicantContext是完整的“身躯”

  • BeanFactory(Bean工厂)是Spring框架的基础设施,面向Spring本身。
  • ApplicantContext(应用上下文)建立在BeanFactoty基础上,面向使用Spring框架的开发者

BeanFactory 接口

BeanFactory是类的通用工厂,可以创建并管理各种类的对象。

ApplicationContext 接口

ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。可以这么说,使用BeanFactory就是手动档,使用ApplicationContext就是自动档。

4、Spring中的bean生命周期?


Spring IOC 中Bean的生命周期大致分为四个阶段:实例化属性赋值初始化销毁

创建过程:

  1. 实例化:第 1 步,实例化一个 Bean 对象;
  2. 属性赋值:第 2 步,为 Bean 设置相关属性和依赖;
  3. 初始化:3、4 步为在初始化前执行,5、6步是真正的初始化,第 7 步在初始化后执行,初始化完成之后,Bean就可以被使用了;
  4. 销毁:第 8~10步,第8步其实也可以算到销毁阶段,但不是真正意义上的销毁,而是先在使用前注册了销毁的相关调用接口,为了后面第9、10步真正销毁 Bean 时再执行相应的方法。


5、什么是依赖注入?依赖注入的方式有哪些?


依赖注入 :指的是容器在实例化对象的时候把它依赖的类注入给它。

依赖注入可以通过三种方式完成:

  1. 构造方法注入
  • 如果只有一个有参数的构造方法并且参数类型与注入的bean的类型匹配,那就会注入到该构造方法中。  
  1. Setter注入
  • 在XML中写入,然后在set方法中注入。
  1. 基于注解的注入
  • @Autowired(构造,接口,方法)
    自动装配,默认根据类型注入  。

6、Spring有哪些自动装配的方式?


自动装配:

  • Spring IOC容器知道所有Bean的配置信息,此外,通过Java反射机制还可以获知实现类的结构信息,如构造方法的结构、属性等信息。掌握所有Bean的这些信息后,Spring IOC容器就可以按照某种规则对容器中的Bean进行自动装配,而无须通过显式的方式进行依赖配置。

Spring提供了哪几种自动装配类型?

Spring提供了4种自动装配类型:

  1. byName:根据名称进行自动匹配;
  2. byType:根据类型进行自动匹配;
  3. constructor:与 byType类似, 只不过它是针对构造函数注入而言的。如果容器中没有找到和构造函数入参匹配类型的Bean,则Spring将抛出异常。
  4. autodetect:根据Bean的自省机制决定采用byType还是constructor进行自动装配,如果Bean提供了默认的构造函数,则采用byType,否则采用constructor。

7、Spring 中的 Bean 的作用域有哪些?

Spring的Bean主要支持五种作用域:

  1. singleton : 单例,在Spring容器仅存在一个Bean实例,Bean以单实例的方式存在,是Bean默认的作用域。
  2. prototype : 多例,每次从容器重调用Bean时,都会返回一个新的实例。
  3. request : 每一次HTTP请求都会产生一个新的Bean,该Bean仅在当前HTTP Request内有效。
  4. session : 同一个HTTP Session共享一个Bean,不同的HTTP Session使用不同的Bean。
  5. globalSession:同一个全局Session共享一个Bean,只用于基于Protlet的Web应用,Spring5中已经不存在了。

8、Spring 中的单例 Bean 会存在线程安全问题吗?


Spring中的单例Bean不是线程安全的

  • 因为单例Bean,是全局只有一个Bean,所有线程共享。如果说单例Bean,是一个无状态的,也就是线程中的操作不会对Bean中的成员变量执行查询以外的操作,那么这个单例Bean是线程安全的。比如Spring mvc 的 Controller、Service、Dao等,这些Bean大多是无状态的,只关注于方法本身。
  • 假如这个Bean是有状态的,也就是会对Bean中的成员变量进行写操作,那么可能就存在线程安全的问题。

单例Bean线程安全问题怎么解决呢?

  • 将Bean中的成员变量保存在ThreadLocal中;
  • 我们知道ThredLoca能保证多线程下变量的隔离,可以在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal里,这是推荐的一种方式。

9、循环依赖?

Spring 循环依赖:简单说就是自己依赖自己,或者和别的Bean相互依赖。

只有单例的Bean才存在循环依赖的情况原型(Prototype)情况下,Spring会直接抛出异常。原因很简单,AB循环依赖,A实例化的时候,发现依赖B,创建B实例,创建B的时候发现需要A,创建A1实例……无限套娃,会直接把系统整垮。

10、Spring如何解决循环依赖?


我们都知道,单例Bean初始化完成,要经历三步:

注入就发生在第二步,属性赋值,结合这个过程,Spring 通过三级缓存解决了循环依赖:

  1. 一级缓存 : Map<String,Object> singletonObjects ,单例池,保存实例化、属性赋值(注入)、初始化完成的 bean 实例;
  2. 二级缓存 : Map<String,Object> earlySingletonObjects ,早期曝光对象,用于保存实例完成的 bean 实例;
  3. 三级缓存 : Map<String,ObjectFactory<?>> singletonFactories ,早期曝光对象工厂,用于保存 bean 创建工厂,以便于后面扩展有机会创建代理对象。

三级缓存解决循环依赖的过程:

  • 当 A、B 两个类发生循环依赖时:

  • A实例的初始化过程:
  1. 创建A实例,实例化的时候把A对象工厂放⼊三级缓存,表示A开始实例化了,虽然我这个对象还不完整,但是先曝光出来让大家知道;

  1. A注⼊属性时,发现依赖B,此时B还没有被创建出来,所以去实例化B;
  2. 同样,B注入属性时发现依赖A,它就会从缓存里找A对象。依次从⼀级到三级缓存查询A,从三级缓存通过对象工厂拿到A,发现A虽然不太完善,但是存在,把A放⼊二级缓存,同时删除三级缓存中的A,此时,B已经实例化并且初始化完成,把B放入⼀级缓存;

  1. 接着A继续属性赋值,顺利从⼀级缓存拿到实例化且初始化完成的B对象,A对象创建也完成,删除二级缓存中的A,同时把A放入⼀级缓存;
  2. 最后,⼀级缓存中保存着实例化、初始化都完成的A、B对象;

11、为什么要三级缓存?二级不行吗?


不行,主要是为了生成代理对象。如果是没有代理的情况下,使用二级缓存解决循环依赖也是OK的。但是如果存在代理,三级没有问题,二级就不行了。

  1. 因为三级缓存中放的是生成具体对象的匿名内部类,获取Object的时候,它可以生成代理对象,也可以返回普通对象。使用三级缓存主要是为了保证不管什么时候使用的都是⼀个对象。
  2. 假设只有二级缓存的情况,往二级缓存中放的显示⼀个普通的Bean对象,Bean初始化过程中,通过 BeanPostProcessor 去生成代理对象之后,覆盖掉二级缓存中的普通Bean对象,那么 可能就导致取到的Bean对象不⼀致了。
相关文章
|
缓存 图形学
游戏通用解决方案之红点设计
游戏通用解决方案之红点设计
1353 0
|
机器学习/深度学习 边缘计算 PyTorch
PyTorch团队为TorchAO引入1-8比特量化,提升ARM平台性能
PyTorch团队推出创新技术,在其低精度计算库TorchAO中引入低位运算符支持,实现1至8位精度的嵌入层权重量化及8位动态量化激活的线性运算符。该技术通过模块化设计和高效硬件利用,优化了资源受限环境下的深度学习计算,提升了计算效率并降低了资源消耗。新内核与PyTorch生态系统无缝集成,支持即时执行、编译优化及边缘计算,为开发者提供全方位性能优势。测试结果显示,多层次量化策略显著提升了计算效率,保持了模型精度。这一突破为深度学习框架优化开辟了多个研究方向,推动了人工智能在边缘计算等领域的广泛应用。
591 11
PyTorch团队为TorchAO引入1-8比特量化,提升ARM平台性能
|
存储 人工智能 数据可视化
拍汉服照,自动调色超厉害的软件是什么?摄影师 2025 新春必备!
在汉服制作与租赁行业蓬勃发展的背景下,2025蛇年新春为摄影师带来了更多机遇。高质量的摄影作品至关重要,合适的自动调色和团队协作软件能极大提升效率。推荐6款软件助力摄影师:板栗看板提供清晰流程管理和实时沟通;Luminar智能调色一键打造古风;Capture One精准色彩管理还原汉服本色;Darktable开源免费且功能强大;On1 Photo RAW综合功能强大并引入AI技术;Polarr移动端便捷调色。这些工具将帮助摄影师在新春期间大放异彩,同时确保团队协作顺畅高效。
560 1
|
存储 前端开发 JavaScript
聊一聊常见的浏览器数据存储方案(下)
聊一聊常见的浏览器数据存储方案(下)
483 0
|
存储 算法 Java
JVM学习日志(十三) G1垃圾回收流程 及 垃圾回收器总结
G1垃圾回收流程 及 垃圾回收器 总结 简述
662 0
JVM学习日志(十三) G1垃圾回收流程 及 垃圾回收器总结
|
存储 人工智能 前端开发
【AI系统】LLVM IR 基本概念
本文深入探讨了LLVM的IR(中间表示)概念,解释了其在编译器工作原理中的重要性及应用方式。LLVM IR作为一种适中抽象级别的表示形式,能有效捕捉源代码信息,支持编译器的灵活操作与优化。文章进一步分析了LLVM IR的不同表现形式,包括内存中的编译中间语言、硬盘上的二进制格式和人类可读的文本格式,以及通过具体示例展示了如何使用Clang将C语言程序编译为LLVM IR。此外,还详细解析了LLVM IR的基本语法、条件语句、循环结构和指针操作等内容。
619 3
|
机器学习/深度学习 人工智能 搜索推荐
AI与未来医疗:重塑健康的双刃剑
【10月更文挑战第6天】 人工智能作为现代科技的巅峰之作,已经渗透进我们生活的方方面面。从语音助手到自动驾驶,AI不仅改变了我们的日常,更在各个专业领域,特别是医疗行业,扮演着愈发重要的角色。本文探讨了AI在未来医疗中的应用及其潜在影响,揭示了这把“双刃剑”的机遇与挑战。
493 1
|
机器学习/深度学习 人工智能 安全
人工智能与机器学习在网络安全中的应用
人工智能与机器学习在网络安全中的应用
537 0
ChatGPT高效提问—prompt基础
ChatGPT高效提问—prompt基础
659 0

热门文章

最新文章