掌握 Spring:从新手到高手的常见问题汇总

一提起Spring,总感觉有太多知识,无法详尽,有些基础理解就先不说了,相信大家都已经用过Spring了
下面简单针对常见Spring面试题做些回答

核心特性

  • IOC容器
  • spring事件
  • 资源管理
  • 国际化
  • 校验
  • 数据绑定
  • 类型转换
  • spirng表达式
  • 面向切面编程
  • ……

SpringMVC流程

1、 用户发送请求至前端控制器DispatcherServlet。

2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。

3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。

4、 DispatcherServlet调用HandlerAdapter处理器适配器。

5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。

6、 Controller执行完成返回ModelAndView。

7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。

8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。

9、 ViewReslover解析后返回具体View。

10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。

11、 DispatcherServlet响应用户。

实例化Bean的方法initializeBean,该方法在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory类下

Bean生命周期

  1. Spring 容器根据配置中的 bean 定义 实例化 bean。

  2. Spring 使用依赖注入填充所有属性,如 bean 中所定义的配置。

  3. invokeAwareMethods:如果 bean 实现BeanNameAware 接口,则工厂通过传递 bean 的 ID 来调用setBeanName()。如果bean实现BeanClassLoaderAware,则调用setBeanClassLoader()

  4. 如果 bean 实现 BeanFactoryAware 接口,工厂通过传递自身的实例来调用 setBeanFactory()。

  5. 如果存在与 bean 关联的任何BeanPostProcessors,则调用 preProcessBeforeInitialization() 方法

  6. 如果为 bean 指定了 init 方法( 的 init-method 属性),那么将调用它。

  7. 最后,如果存在与 bean 关联的任何 BeanPostProcessors,则将调用 postProcessAfterInitialization() 方法

  8. 如果 bean 实现DisposableBean 接口,当 spring 容器关闭时,会调用 destory()。

  9. 如果为bean 指定了 destroy 方法( 的 destroy-method 属性),那么将调用它。

在这里插入图片描述

SPI机制

基于接口的编程+策略模式+配置文件

在Springboot的自动装配过程中,最终会加载META-INF/spring.factories文件,而加载的过程是由SpringFactoriesLoader加载的。从CLASSPATH下的每个jar包中搜索所有META-INF/spring.factories

配置文件,其实这里不仅仅是去ClassPath路径下查询,而是会扫描所有路径下的jar包,只不过这个文件只会在ClassPath下的jar包中.

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
// spring.factories文件的格式为:key=value1,value2,value3
// 从所有的jar包中找到META-INF/spring.factories文件
// 然后从文件中解析出key=factoryClass类名称的所有value值
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
    String factoryClassName = factoryClass.getName();
    // 取得资源文件的URL
    Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
    List<String> result = new ArrayList<String>();
    // 遍历所有的URL
    while (urls.hasMoreElements()) {
        URL url = urls.nextElement();
        // 根据资源文件URL解析properties文件,得到对应的一组@Configuration类
        Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
        String factoryClassNames = properties.getProperty(factoryClassName);
        // 组装数据,并返回
        result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
    }
    return result;
}

Bean循环依赖如何解决的

先调用构造函数进行实例化,然后填充属性,再接着进行其他附加操作和初始化,正是这样的生命周期,才有了Spring的解决循环依赖,这样的解决机制是根据Spring框架内定义的三级缓存来实现的,也就是说:三级缓存解决了Bean之间的循环依赖

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

找出了前面提到的三级缓存,也就是三个Map集合类:

singletonObjects:第一级缓存,用于保存实例化、注入、初始化完成的bean实例

earlySingletonObjects:第二级缓存,用于保存实例化完成的bean实例(未注入和初始化)

singletonFactories:第三级缓存,用于保存bean创建工厂,以便于后面扩展有机会创建代理对象。属于提前暴露

后面专门针对这块分析下源码,下面是调用初始化的详细步骤示例

在这里插入图片描述

  1. 创建对象A,实例化的时候把A对象工厂放入三级缓存
  2. A注入属性时,发现依赖B,转而去实例化B
  3. 同样创建对象B,注入属性时发现依赖A,一次从一级到三级缓存查询A,从三级缓存通过对象工厂拿到A,把A放入二级缓存,同时删除三级缓存中的A,此时,B已经实例化并且初始化完成,把B放入一级缓存
  4. 接着继续创建A,顺利从一级缓存拿到实例化且初始化完成的B对象,A对象创建也完成,删除二级缓存中的A,同时把A放入一级缓存
  5. 最后,一级缓存中保存着实例化、初始化都完成的A、B对象

解释 Spring 支持的几种 bean 的作用域。

Spring 框架支持以下五种 bean 的作用域:

  • singleton : bean 在每个 Spring ioc 容器中只有一个实例。
  • prototype:一个 bean 的定义可以有多个实例。
  • request:每次 http 请求都会创建一个 bean,该作用域仅在基于 web的 Spring ApplicationContext 情形下有效。
  • session:在一个 HTTP Session 中,一个 bean 定义对应一个实例。该作用域仅在基于 web 的 Spring ApplicationContext 情形下有效。
  • global-session:在一个全局的 HTTP Session 中,一个 bean 定义对应一个实例。该作用域仅在基于 web 的 Spring ApplicationContext 情形下有效。缺省的 Spring bean 的作用域是 Singleton.

BeanFactory 和 ApplicationContext 的区别

BeanFactoryApplicationContext 都是 Spring 框架提供的 IOC 容器,分别代表了基础的 IOC 容器和高级的 IOC 容器。ApplicationContextBeanFactory 的子接口,继承了 BeanFactory 的所有功能,并在此基础上提供了更多扩展性的服务。

二、BeanFactory

  • 基本概念BeanFactory 是 Spring 框架中最基础的 IOC 容器,它负责读取 bean 配置文档,管理 bean 的加载与实例化,并控制 bean 的生命周期及维护 bean 间的依赖关系。
  • 加载机制BeanFactory 采用延迟加载机制,即在真正使用某个 bean 时(通过 getBean() 方法调用)才会对其进行加载和实例化。
  • 创建方式BeanFactory 通常通过编程方式创建。

三、ApplicationContext

  • 高级特性ApplicationContextBeanFactory 的基础上增加了许多高级功能,例如国际化支持、资源文件访问、事件发布机制等。
  • 加载机制ApplicationContext 在容器启动时,会一次性创建所有非懒加载的 bean。
  • 创建方式:除了支持编程式创建之外,ApplicationContext 还支持声明式创建。
  • 扩展功能
    • 继承 MessageSource 接口,支持国际化。
    • 提供统一的资源文件访问方式。
    • 支持在监听器中注册 bean 的事件。
    • 允许同时加载多个配置文件。
    • 能够载入具有继承关系的多个上下文,使每个上下文专注于特定的层次(如 Web 层)。
      四、BeanPostProcessor 和 BeanFactoryPostProcessor 的使用
  • BeanFactory 需要手动注册 BeanPostProcessorBeanFactoryPostProcessor
  • ApplicationContext 则自动注册 BeanPostProcessorBeanFactoryPostProcessor

框架中都用到了哪些设计模式?

  1. 工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;

  2. 单例模式:Bean默认为单例模式。

  3. 代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;

  4. 模板方法:用来解决代码重复的问题。比如.JdbcTemplate

  5. 观察者模式:ApplicationListener。

  6. 适配器模式:Aop中,使用Advice(通知)来增强被代理类的功能

使用@Autowired 注解自动装配的过程是怎样的?

使用@Autowired 注解来自动装配指定的 bean。在使用@Autowired 注解之前需要在 Spring 配置文件进行配置。

在启动 spring IoC 时,容器自动装载了一个 AutowiredAnnotationBeanPostProcessor 后置处理器,

当容器扫描到@Autowied、@Resource 或@Inject 时,就会在 IoC 容器自动查找需要的 bean,并装配给该对象的属性。在使用@Autowired 时,首先在容器中查询对应类型的 bean:

• 如果查询结果刚好为一个,就将该 bean 装配给@Autowired 指定的数据;

• 如果查询的结果不止一个,那么@Autowired 会根据名称来查找;

• 如果上述查找的结果为空,那么会抛出异常。解决方法时,使用 required=false。

后面看看会针对一些比较常见重要的问题进行更新,今天就到这,总结总结,希望大家一起成长

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【HTTP】构造HTTP请求和状态码

状态码 用于响应中&#xff0c;表示响应的结果如何 正确&#xff1f;错误&#xff1f;什么原因&#xff1f; HTTP 中的状态码都是标准约定好的 200 OK 成功了&#xff0c;一切顺利 在抓包到的响应中 404 Not Found 访问的资源&#xff08;URL 中的路径&#xff09;没找…

Python语言基础教程(下)4.0

✨博客主页&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客内容》&#xff1a;.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 &#x1f4e2;博客专栏&#xff1a; https://blog.csdn.net/m0_63815035/cat…

十六 未来信息综合技术(考点篇)

1 信息物理系统技术 信息物理系统(CPS)是控制系统、嵌入式系统的扩展与延伸&#xff0c;其涉及的相关底层理论技术源于对嵌入式技术的应用与提升。 CPS 通过集成先进的感知、计算、通信、控制等信息技术和自动控制技术&#xff0c;构建了物理空间与信息空间中人、机、物、环境…

OpenCV特征检测(3)计算图像中每个像素处的特征值和特征向量函数cornerEigenValsAndVecs()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算图像块的特征值和特征向量用于角点检测。 对于每一个像素 p &#xff0c;函数 cornerEigenValsAndVecs 考虑一个 blockSize blockSize 的邻…

mysql为什么建议创建字段的时候not null

相信大家在建表或者给表新加字段的时候&#xff0c;一些老司机们都会建议我们&#xff0c;字段要定义为not null&#xff0c;原因呢是一是占用存储空间&#xff0c;另一个是避免出现一些意料之外的错误。当然针对这个问题&#xff0c;大家可能也会在网上去搜下&#xff0c;不过…

制作炫酷个人网页:用 HTML 和 CSS3 展现你的风格

你是否觉得自己的网站应该看起来更炫酷&#xff1f;今天我将教你如何使用 HTML 和 CSS3 制作一个拥有炫酷动画和现代设计风格的个人网页&#xff0c;让它在任何设备上看起来都无敌酷炫&#xff01; 哈哈哈哈哈哈哈哈,我感觉自己有点中二哈哈哈哈~ 目录 炫酷设计理念构建 HTML …

【电力系统】基于遗传算法的33节点电力系统无功优化及MATLAB实现

摘要 本文研究了基于遗传算法的33节点配电系统的无功优化问题。通过调整电容器的安装位置和容量&#xff0c;以最小化系统的无功损耗和电压偏差。研究使用遗传算法对无功优化问题进行求解&#xff0c;并在MATLAB环境中进行仿真实现。实验结果表明&#xff0c;该方法能够有效地…

零工市场小程序:推动零工市场建设

人力资源和社会保障部在2024年4月发布了标题为《地方推进零工市场建设经验做法》的文章。 零工市场小程序的功能 信息登记与发布 精准匹配、推送 在线沟通 权益保障 零工市场小程序作为一个找零工的渠道&#xff0c;在往后随着技术的发展和政策的支持下&#xff0c;功能必然…

★ C++进阶篇 ★ 二叉搜索树

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;我将继续和大家一起学习C进阶篇第三章----二叉搜索树 ~ ❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️ 澄岚主页&#xff1a;椎名澄嵐-CSDN博客 C基础篇专栏&#xff1a;★ C基础篇 ★_椎名澄嵐的博客-CSD…

【matlab】生成 GIF 的函数(已封装可直接调用)

文章目录 前言一、函数输入与输出二、函数代码三、例程&#xff08;可直接运行&#xff09;参考文献 前言 生成 gif 图片时遇到的问题&#xff0c;为了后续调用方便&#xff0c;封装为函数 一、函数输入与输出 输入&#xff1a; cell_figure: cell 数组&#xff0c;数组元素是…

git 更换远程地址的方法

需要将正在开发的代码远程地址改成新的地址&#xff0c;通过查询发现有三个方法可以实现&#xff0c;特此记录。具体方法如下&#xff1a; &#xff08;1&#xff09;通过命令直接修改远程仓库地址 git remote 查看所有远程仓库git remote xxx 查看指定远程仓库地址git remote…

ProtoBuf序列化框架介绍

文章目录 ProtoBuf介绍使用流程 QUICK START创建.proto文件注释语法编译部分代码展示使用接口运行结果 ProtoBuf介绍 ProtoBuf全称是Protocol Buffer&#xff0c;是一个数据结构的序列化和反序列化框架 他又很多好处&#xff0c;首先是他支持跨平台&#xff0c;支持Java、C、…

Mac 上,终端如何开启 proxy

文章目录 为什么要这么做前提步骤查看 port查看代理的port配置 bash测试 为什么要这么做 mac 上的终端比较孤僻吧&#xff0c;虽然开了&#xff0c;但是终端并不走&#x1fa9c;…产生的现象就是&#xff0c;浏览器可以访问&#x1f30d;&#xff0c;但是终端不可以访问&#…

创建Application(Qt)模板项目时的 Base class选择

在Qt中&#xff0c;当你使用Qt Creator新建一个Qt Widgets Application项目时&#xff0c;选择Base class是一个重要的步骤&#xff0c;因为它决定了你的主窗口或对话框将继承自哪个类&#xff0c;从而决定了你的应用程序将具有哪些基本的功能和外观。以下是一些常见的Base cla…

docker进入容器运行命令

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

3D生成技术再创新高:VAST发布Tripo 2.0,提升AI 3D生成新高度

随着《黑神话悟空》的爆火&#xff0c;3D游戏背后的AI 3D生成技术也逐渐受到更多的关注。虽然3D大模型的热度相较于语言模型和视频生成技术稍逊一筹&#xff0c;但全球的3D大模型玩家们却从未放慢脚步。无论是a16z支持的Yellow&#xff0c;还是李飞飞创立的World Labs&#xff…

双击就可以打开vue项目,而不用npm run dev

右键点击桌面或其他位置&#xff0c;选择“新建” -> “快捷方式”&#xff0c;在“对象的位置”处直接输入“npm run dev”&#xff0c;然后下一步 自定义一个快捷方式名称 完成后&#xff0c;桌面会创建一个快捷方式&#xff0c;右键快捷方式选择属性&#xff0c;可以看…

为什么 ECB 模式不安全

我们先来简单了解下 ECB 模式是如何工作的 ECB 模式不涉及链接模式&#xff0c;所以也就用不着初始化向量&#xff0c;那么相同的明文分组就会被加密成相同的密文分组&#xff0c;而且每个分组运算都是独立的&#xff0c;这也就意味着可以并行提高运算效率&#xff0c;但也正是…

prometheus通过nginx-vts-exporter监控nginx

Prometheus监控nginx有两种方式。 一种是通过nginx-exporter监控&#xff0c;需要开启nginx_stub_status,主要是nginx自身的status信息&#xff0c;metrics数据相对较少&#xff1b; 另一种是使用nginx-vts-exporter监控&#xff0c;但是需要在编译nginx的时候添加nginx-module…

Shader 中的光源

1、Shader 开发中常用的光源属性 Unity当中一共支持四种光源类型&#xff1a; 平行光&#xff08;Directional&#xff09;点光源&#xff08;Point&#xff09;聚光灯&#xff08;Spot&#xff09;面光源&#xff08;Area&#xff09;— 面光源仅在烘焙时有用 不管光源类型到…