Spring底层篇

一、什么是Spring?谈谈你对IOC和AOP的理解。

Spring: 是一个企业级java应用框架,他的作用主要是简化软件的开发以及配置过程,简化项目部署环境。

Spring的有点:

1、Spring低侵入设计,对业务代码的污染非常低。

2、Spring的DI机制将对象之间的关系交由框架处理,减少组件的耦合。

3、Spring提供了AOP技术,支持将一些通用的功能进行集中式管理,从而提供更好的复用。

4、Spring对于主流框架提供了非常好的支持。

IOC就是控制反转,指创建对象的控制权转移给Spring来进行管理。简单来说,就是应用不用去new对象了,而全部交由Spring自动生产。
IOC有三种注入方式:1、 构造器注入 2、setter方法注入 3、根据注解注入。
AOP 面向切面。用于将那些与业务无关,但却对多个对象产生影响的公共行为。抽取并封装成一个可重用的模块。AOP的核心就是动态代理。JDK的动态代理 和 CGLIB动态代理。

二、Spring容器的启动流程是怎么样的?

使用AnnotationConfigApplicationContext 来跟踪一下启动流程:

this(); 初始化reader和scanner

scan(basePackages); 使用scanner组件扫描basePackage下的所有对象,将配置类的BeanDefinition注册到容器中。

refresh(); 刷新容器。

​ prepareRefresh 刷新前的预处理

​ obtainFreshBeanFactory: 获取在容器初始化时创建的BeanFactory

​ prepareBeanFactory: BeanFactory的预处理工作,会向容器中添加一些组件。

​ postProcessBeanFactory: 子类重写该方法,可以实现在BeanFactory创建并预处理完成后做进一步的设置。

​ invokeBeanFactoryPostProcessors: 在BeanFactory初始化之后执行BeanFactory的后处理器。

​ registerBeanPostProcessors: 向容器中注册Bean的后处理器,他的主要作用就是干预Spring初始化Bean的流程,完成代理、自动注入、循环依赖等这些功能。

​ initMessageSource: 初始化messagesource组件,主要用于国际化。

​ initApplicationEventMulticaster: 初始化事件分发器

​ onRefresh: 留给子容器,子类重写的方法,在容器刷新的时候可以自定义一些逻辑。

​ registerListeners: 注册监听器。

​ finishBeanFactoryInitialization: 完成BeanFactory的初始化,主要作用是初始化所有剩下的单例Bean。
​ finishRefresh: 完成整个容器的初始化,发布BeanFactory容器刷新完成的事件。

三、Spring框架中Bean的创建过程是怎样的?

首先,简单来说,Spring框架中的Bean经过四个阶段: 实例化 -》 属性赋值 -》 初始化 -》 销毁

然后: 具体来说,Spring中Bean 经过了以下几个步骤:

​ 1、实例化: new xxx(); 两个时机: 1、当客户端向容器申请一个Bean时,2、当容器在初始化一个Bean时发现还需要依赖另一个Bean。 BeanDefinition 对象保存。-到底是new一个对象还是创建一个动态代理?

​ 2、设置对象属性(依赖注入):Spring通过BeanDefinition找到对象依赖的其他对象,并将这些对象赋予当前对象。

​ 3、处理Aware接口:Spring会检测对象是否实现了xxxAware接口,如果实现了,就会调用对应的方法。

​ BeanNameAware、BeanClassLoaderAware、BeanFactoryAware、ApplicationContextAware

​ 4、BeanPostProcessor前置处理: 调用BeanPostProcessor的postProcessBeforeInitialization方法

​ 5、InitializingBean: Spring检测对象如果实现了这个接口,就会执行他的afterPropertiesSet()方法,定制初始化逻辑。

​ 6、init-method: 如果Spring发现Bean配置了这个属性,就会调用他的配置方法,执行初始化逻辑。@PostConstruct

​ 7、BeanPostProcessor后置处理: 调用BeanPostProcessor的postProcessAfterInitialization方法

到这里,这个Bean的创建过程就完成了, Bean就可以正常使用了。

​ 8、DisposableBean: 当Bean实现了这个接口,在对象销毁前就会调用destory()方法。

​ 9、destroy-method: @PreDestroy

四、Spring框架中的Bean是线程安全的吗?如果线程不安全,要如何处理?

Spring容器本身没有提供Bean的线程安全策略,因此,也可以说Spring容器中的Bean不是线程安全的。
​ 要如何处理线程安全问题,就要分情况来分析。

Spring中的作用域: 1、 sington 2、prototype: 为每个Bean请求创建给实例。 3、request:为每个request请求创建一个实例,请求完成后失效。 4、 session: 与request是类似的。 5、global-session:全局作用域。

对于线程安全问题:

1> 对于prototype作用域,每次都是生成一个新的对象,所以不存在线程安全问题。

2>sington作用域: 默认就是线程不完全的。但是对于开发中大部分的Bean,其实是无状态的,不需要保证线程安全。所以在平常的MVC开发中,是不会有线程安全问题的。

无状态表示这个实例没有属性对象, 不能保存数据,是不变的类。比如: controller、service、dao

有状态表示示例是有属性对象,可以保存数据,是线程不安全的, 比如 pojo.

​ 但是如果要保证线程安全,可以将Bean的作用域改为prototype 比如像 Model View。
​ 另外还可以采用ThreadLocal来解决线程安全问题。ThreadLocal为每个线程保存一个副本变量, 每个线程只操作自己的副本变量。

五、Spring如何处理循环依赖问题?

循环依赖: 多个对象之间存在循环的引用关系,在初始化过程当中,就会出现"先有蛋还是先有鸡"的问题。

一种是使用@Lazy注解: 解决构造方法造成的循环依赖问题
另一种是使用三级缓存
一级缓存:缓存最终的单例池对象: private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

二级缓存:缓存初始化的对象:private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

三级缓存:缓存对象的ObjectFactory: private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

对于对象之间的普通引用,二级缓存会保存new出来的不完整对象,这样当单例池中找到不依赖的属性时,就可以先从二级缓存中获取到不完整对象,完成对象创建,在后续的依赖注入过程中,将单例池中对象的引用关系调整完成。

三级缓存:如果引用的对象配置了AOP,那在单例池中最终就会需要注入动态代理对象,而不是原对象。而生成动态代理是要在对象初始化完成之后才开始的。于是Spring增加三级缓存,保存所有对象的动态代理配置信息。在发现有循环依赖时,将这个对象的动态代理信息获取出来,提前进行AOP,生成动态代理。

核心代码就在DefaultSingletonBeanRegistry的getSingleton方法当中。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {// Quick check for existing instance without full singleton lockObject singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {synchronized (this.singletonObjects) {// Consistent creation of early reference within full singleton locksingletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}}}return singletonObject;}

六、Spring如何处理事务?

Spring当中支持编程式事务管理和声明式事务管理两种方式:

1、编程式事务可以使用TransactionTemplate。

2、声明式事务: 是Spring在AOP基础上提供的事务实现机制。他的最大优点就是不需要在业务代码中添加事务管理的代码,只需要在配置文件中做相关的事务规则声明就可以了。但是声明式事务只能针对方法级别,无法控制代码级别的事务管理。

Spring中对事务定义了不同的传播级别: Propagation

1、 PROPAGATION_REQUIRED:默认传播行为。 如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入到事务中。

2、PROPAGATION_SUPPORTS: 如果当前存在事务,就加入到该事务。如果当前不存在事务,就以非事务方式运行。

3、PROPAGATION_MANDATORY: 如果当前存在事务,就加入该事务。如果当前不存在事务,就抛出异常。

4、PROPAGATION_REQUIRES_NEW: 无论当前存不存在事务,都创建新事务进行执行。

5、PROPAGATION_NOT_SUPPORTED: 以非事务方式运行。如果当前存在事务,就将当前事务挂起。

6、PROPAGATION_NEVER : 以非事务方式运行。如果当前存在事务,就抛出异常。

7、PROPAGATION_NESTED: 如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则按REQUEIRED属性执行。

Spring中事务的隔离级别:

1、ISOLATION_DEFAULT: 使用数据库默认的事务隔离级别。

2、ISOLATION_READ_UNCOMMITTED: 读未提交。允许事务在执行过程中,读取其他事务未提交的数据。

3、ISOLATION_READ_COMMITTED: 读已提交。允许事务在执行过程中,读取其他事务已经提交的数据。

4、ISOLATION_REPEATABLE_READ: 可重复读。 在同一个事务内,任意时刻的查询结果是一致的。

5、ISOLATION_SERIALIZABLE: 所有事务依次执行。

七、SpringMVC中的控制器是不是单例模式?如果是,如何保证线程安全?

控制器是单例模式。

单例模式下就会有线程安全问题。

Spring中保证线程安全的方法

1、将scop设置成非singleton。 prototype, request。

2、最好的方式是将控制器设计成无状态模式。在控制器中,不要携带数据。但是可以引用无状态的service和dao。

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

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

相关文章

python游戏开发pygame初步

文章目录 安装和示例移动物体优化 安装和示例 顾名思义&#xff0c;PyGame就是用来做游戏的Python库&#xff0c;提供了许多游戏开发功能&#xff0c;如图像处理、音频播放、事件处理、碰撞检测等等。从这个角度来说&#xff0c;pygame不仅是一个游戏库&#xff0c;同时也是一…

卷积,是什么?

其实就是对事物的作用&#xff0c;或者说作用力&#xff0c;比如说&#xff0c;石板上没有字&#xff0c;我们刻上字&#xff0c;便于识别&#xff0c;从机器视觉角度来说&#xff0c;就是对图像的作用力&#xff0c;这种作用使得能看清想要的东西&#xff0c;感觉还是很主观&a…

Redis面试题:redis做为缓存,mysql的数据如何与redis进行同步呢?(双写一致性)

目录 强一致性&#xff1a;延迟双删&#xff0c;读写锁。 弱一致性&#xff1a;使用MQ或者canal实现异步通知 面试官&#xff1a;redis做为缓存&#xff0c;mysql的数据如何与redis进行同步呢&#xff1f;&#xff08;双写一致性&#xff09; 候选人&#xff1a;嗯&#xff…

为什么淘宝取消双12活动?

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 淘宝取消双12活动了&#xff0c;这条消息犹如一颗重磅炸弹&#xff0c;在整个电商圈中引发了轩然大波。 不过呢&#xff0c;淘宝为了过度&#xff0c;把双12改了个名字叫“好价节”。估计是官方都…

使用skforecast进行时间序列预测

时间序列预测是数据科学和商业分析中基于历史数据预测未来价值的一项重要技术。它有着广泛的应用&#xff0c;从需求规划、销售预测到计量经济分析。由于Python的多功能性和专业库的可用性&#xff0c;它已经成为一种流行的预测编程语言。其中一个为时间序列预测任务量身定制的…

栈详解(C语言)

文章目录 写在前面1 栈的定义2 栈的初始化3 数据入栈4 数据出栈5 获取栈顶元素6 获取栈元素个数7 判断栈是否为空8 栈的销毁 写在前面 本片文章详细介绍了另外两种存储逻辑关系为 “一对一” 的数据结构——栈和队列中的栈&#xff0c;并使用C语言实现了数组栈。 栈C语言实现源…

Vue3中Composition API介绍

在Vue 3中&#xff0c;引入了Composition API&#xff0c;它是一种新的组合式函数API&#xff0c;用于更灵活地组织和重用组件逻辑。Composition API相比于Vue 2中的Options API&#xff0c;提供了更好的可组合性和代码复用性。下面是对Vue 3中Composition API的介绍和用法&…

【自主探索】基于 rrt_exploration 的单个机器人自主探索建图

文章目录 一、rrt_exploration 介绍1、原理2、主要思想3、拟解决的问题4、优缺点 二、安装环境三、安装与运行1、安装2、运行 四、配置说明1、Robots Network2、Robots frame names in tf3、Robots node and topic names4、Setting up the navigation stack on the robots5、A …

【数据库】执行计划中二元操作对一趟扫描算法的应用,理解代价评估的应用和优化,除了磁盘代价还有CPU计算代价不容忽略

二元操作的一趟算法 ​专栏内容&#xff1a; 手写数据库toadb 本专栏主要介绍如何从零开发&#xff0c;开发的步骤&#xff0c;以及开发过程中的涉及的原理&#xff0c;遇到的问题等&#xff0c;让大家能跟上并且可以一起开发&#xff0c;让每个需要的人成为参与者。 本专栏会定…

C#,《小白学程序》第十九课:随机数(Random)第六,随机生成任意长度的大数(BigInteger)

1 文本格式 using System; using System.Linq; using System.Text; using System.Collections.Generic; /// <summary> /// 大数的&#xff08;加减乘除&#xff09;四则运算、阶乘运算 /// 乘法计算包括小学生算法、Karatsuba和Toom-Cook3算法 /// 除法运算为 Truffer…

车载以太网-ICMP

文章目录 ICMP协议ICMP报文格式ICMP报文的示例ICMP协议流程ICMP协议报文示例车载以太网ICMP协议测试内容ICMP协议 车载以太网(Ethernet)是一种用于在车辆内部传输数据的网络协议。Internet控制消息协议(ICMP)是一种用于在IP网络上发送错误消息和操作消息的协议。在车载以太…

Leetcode—167.两数之和 II - 输入有序数组【中等】

2023每日刷题&#xff08;四十一&#xff09; Leetcode—167.两数之和 II - 输入有序数组 实现代码 /*** Note: The returned array must be malloced, assume caller calls free().*/ int* twoSum(int* numbers, int numbersSize, int target, int* returnSize) {*returnSiz…

Java多线程-面试题+答案——第6期

当准备Java多线程面试时&#xff0c;更多的问题可能涉及到线程池、并发集合、并发工具、锁、原子操作等更深层次的概念。 Java中的CountDownLatch和CyclicBarrier的区别&#xff1a; 答案&#xff1a; CountDownLatch用于等待多个线程完成某个任务&#xff0c;计数器递减到零…

小程序中的大道理之四--单元测试

在讨论领域模型之前, 先继续说下关于测试方面的内容, 前面为了集中讨论相应主题而对此作了推迟, 下面先补上关于测试方面的. 测试覆盖(Coverage) 先回到之前的一些步骤上, 假设我们现在写好了 getPattern 方法, 而 getLineContent 还处于 TODO 状态, 如下: public String ge…

网络视频播放卡顿原因分析

一、问题描述 某项目通过拉摄像机rtsp流转rtmp/http-flv/ws-flv的方案&#xff0c;使用户可以在网页中观看摄像机的视频画面。在 观看视频时偶发出现卡顿现象。 二、卡顿现象分析和解决 此问题涉及的原因较多&#xff0c;所以得考虑各环节的问题可能性&#xff0c;并根据现场实…

Apache多后缀解析漏洞分析

漏洞介绍 该漏洞与用户的配置有密切的关系,严格来说属于用户配置问题。Apache文件解析漏洞涉及到 Apache 解析文件的特性。在默认情况下,Apache 允许一个文件具有多个以点分割的后缀,在处理文件时会从右向左识别后缀名。(就是右边的后缀名无法识别,则继续识别左边的) 如果…

C#与C++进行字段内存对齐

通过预留字段来补齐内存分配。在实际项目中采用这种方法较多&#xff0c;即保证了长度一致&#xff0c;也为以后的扩展提供了容错的可能性。 unsafe struct StructSequential{public fixed float x[8];public fixed float y[8];public fixed float z[8];public fixed float ti…

在CentOS 7.9上搭建高性能的FastDFS+Nginx文件服务器集群并实现外部远程访问

文章目录 引言第一部分&#xff1a;FastDFS介绍与安装1.1 FastDFS简介1.2 FastDFS安装1.2.1 安装Tracker Server1.2.2 安装Storage Server 1.3 FastDFS配置1.3.1 配置Tracker Server1.3.2 配置Storage Server1.3.3 启动FastDFS服务 第二部分&#xff1a;Nginx配置2.1 Nginx安装…

Redis IO多路复用之select、poll和epoll

Redis 性能好除了它是基于内存的数据库外,还因为Redis 是基于IO多路复用机制。以下总结一下曾经遇到过的一个面试题:你了解IO多路复用机制吗?实现IO多路复用机制的方式有哪些?有什么区别? 是的,我了解Redis的IO多路复用机制。Redis使用IO多路复用来实现高效的异步非阻塞I…

Docker容器化部署若依微服务ruoyi-cloud项目

系统环境 接下来的内容以 Ubuntu 22.04.1 操作系统为例。 下载安装Docker Ubuntu hihi-IdeaCentre-GeekPro-15ICK:~$ sudo su [sudo] hi 的密码&#xff1a; roothi-IdeaCentre-GeekPro-15ICK:/home/hi# docker ps 找不到命令 “docker”&#xff0c;但可以通过以下软件包安…