# spring 面试题

##### 1.实例化bean的方式  


1，使用类构造器实例化（无参构造函数） ：直接通过Spring工厂返回类的实例对象

2，使用静态工厂方法实例化（简单工厂模式） ：Spring工厂调用自定义工厂的静态方法返回类的实例对象。

3，使用实例工厂方法实例化（工厂方法模式） ：Spring工厂调用工厂的普通方法（非静态方法）返回类的实例对象。

##### 2.定义Bean有几种方式  


1.Component

2.Controller Service Mapper RestController

3.Bean

4.Configuration

5.Imoprt

6.BeanDefinition

7.&lt;bean/&gt;配合ImportResource

8.ControllerAdvice 控制器的切面 可以对响应的数据进行增强

[![image.png](http://wiki.shopqorg.com/uploads/images/gallery/2024-05/scaled-1680-/S81image.png)](http://wiki.shopqorg.com/uploads/images/gallery/2024-05/S81image.png)

##### 5.3@Resource和@Autowired的区别  


@Resource注解会先根据名字去找Bean，没找到就会去根据属性去找，诺是找到多个就会报错，同时@Resource还能指定名字，一旦没找到直接报错，不会根据类型再去找

@Autowired注解会根据属性去找Bean，如果找到多个，会根据名字去确定Bean，还是没找到就会报错

@Autowired是Spring层面提供的，与Spring强绑定

@Resource是jdk提供的，没有和Spring强绑定

4.Mybatis-plus对比Mybatis的优势是什么?

1.封装了常用的操作，减少了代码量

2.提供了一些常用的CRUD的操作

3.提供了分页查询，逻辑删除，多表查询，乐观锁，大大提高了开发效率

4.插件支持，方便二级缓存，性能分析，分页插件等等的集成

5.也可以通过配置文件或注解进行配置

5.单例Bean是单例模式吗？  
通常来说，单例是值在一个jvm中，一个类只能创建出一个对象，有很多方式来实现单例Bean，那如果在两个jvm中保持单例就要用到分布式锁，

而在spring中的单例也是单例模式，只不过范围比较小，它的范围是在一个BeanName中，一个BeanName对应的一个Bean对象，不同的BeanName对应着不同的Bean的对象，同一个类也可以有不同的BeanName

6.AspectJ和SpringAop的区别  
SpringAop是利用动态代理来实现的，如果一个Bean实现了接口，就会采用jdk动态代理来生成该接口的动态代理，如果Bean没有实现接口，那么就会采用CGLIB动态代理来实现，可以用SpringAop来实现登录验证，日志记录，权限控制

他们两者之间没有啥特别的关系，AOP表示面向切面编程，是一种思想，什么人都可以实现，AspectJ就是其中之一，它会在编译期就对类进行增强，要用Aspectj就要用Aspectj开发的编译器来执行项目，SpringAop是基于动态代理来实现的Aop，同时支持@before，@after，@Around等注解，虽然注解相同，但是底层的实现完全不同

7.如何理解Spring事务的传播机制？底层如何实现的

一个线程在运行过程中，可能连续调用好几个方法，调用某一个方法是可能就开启了一个spring事务，那么在调用接下来的方法时，到底是共用一个事务，还是开启一个新的事务，这就是事务的传播机制；

事务的传播机制种类

REQUIRED：如果当前存在事务，则加入该事务，如果当前没有事务，则创建一个新的事务。这是默认的传播行为。

REQUIRES\_NEW：创建一个新的事务，如果当前存在事务，则挂起当前事务。

SUPPORTS：如果当前存在事务，则加入该事务，如果当前没有事务，则以非事务方式执行。

NOT\_SUPPORTED：以非事务方式执行操作，如果当前存在事务，则挂起当前事务。

MANDATORY：如果当前存在事务，则加入该事务，如果当前没有事务，则抛出异常。

NEVER：以非事务方式执行操作，如果当前存在事务，则抛出异常。

NESTED：如果当前存在事务，则在当前事务的嵌套事务中执行，如果当前没有事务，则创建一个新的事务。

  
9.BeanFactory和ApplicationContext的区别

 BeanFactory是spring中的核心组件，也是顶级接口，表示Bean的工厂，可以生成Bean，维护Bean，而ApplicationContext继承该接口，拥有这接口的所有方法，并且同时继承了其他的接口，例如国际化，和获取环境变量，事件发布的能力 这些都是BeanFactory接口所没有的

10.什么是自动配置和自动装配

我的理解是自动装配就是@Autowrite注解，也就是依赖注入

自动配置就是在用springboot时springboot帮我们配置的一些比如

1.Mybatis 的SqlSessionFactory

2.AOP的EnableAspectJAutoProxy注解 等等

而在使用spring的时候，这些配置需要自己去配置

11.Spring容器的启动流程  
1.在启动或创建Spring容器时：

2.首先会扫描得到所有的BeanDefinition对象，然后存入一个Map中

3.然后筛选出非懒加载的单例BeanDefinition进行创建Bean,而多例Bean不需要启动容器时去创建，而是每次获取Bean的时候就会用BeanDefiniton创建

4.利用BeanDefinition创建Bean就是创建Bean的生命周期，

5.单例Bean创建完成后，spring会发布一个容器启动事件 你可以监听容器启动事件，在事件监听器中执行一些初始化操作、加载缓存数据、启动定时任务等

6.spring容器启动结束

12.SpringBoot的启动流程，又做了哪些事？  
1.加载配置文件，加载application.properties、application.yml等的配置文件，文件中配置了一些重要信息

2.创建Spring容器（ApplicationContext），基于配置文件加载一个Spring的应用上下文，管理和维护Bean的生命周期

3.执行自动配置，springboot提供了自动配置，找到spring.factories文件中定义的配置类信息，比如是否懒加载，等

4.启动嵌入的容器，Tomcat,jetty容器等，来监听端口

5.处理请求，springboot会接收http请求，并找到相应的Contrller,进行处理及响应

6.关闭程序，接收到关闭信号后，springboot会先关闭嵌入的容器，停止接收新的请求，摧毁容器，释放资源

13.如何理解SpringBoot的自动配置  
自动配置是springboot中最重要的一个特性，大大减轻了开发人员的工作量

我的理解有：

首先，他是约定大于配置，SB会使用一系列约定来判断应用程序的配置需求，从而减少显示配置的需求，在绝大数情况下不需要自己手动，SB会帮你配置好

然后，自动扫描和类路径，SB在启动时会扫描classpath路径下的配置信息

自动装配Bean：Spring Boot的自动配置会根据项目的依赖关系和配置信息，自动装配相应的Bean

还有，条件配置和自定义配置，SB里面的配置会根据一个条件注解来判断是否需要加载Bean，如果你自己自定义配置了，也能覆盖SB的配置

jdk的SPI和springboot的自动装配 知乎 CSDN

14.如何理解SpringBoot的Starter机制  
1.简化依赖管理：starter可以手动避免大量的依赖，只需要引入相关的Starter依赖，就可以获取所需的全部依赖，并且版本都兼容

2.自动配置：SpringBootStarter包含了与功能相关的自动配置类，减轻了开发人员的工作量

3.模块化和可重用性：将一组相关的依赖打包为一个Starter，这样就能反复重用

编写一个自己的starter

5.15如何理解spring.factories文件的作用？  
这个文件其实spring框架中的一个机制，用于实现类路径下自动发现和加载扩展的功能，它允许第三方库或模块在应用程序中注册自己的实现，从而扩展或定义spring框架的行为

16为什么springaop默认cglib动态代理  
功能扩展性：CGLIB 可以对类的任意方法进行代理，而不仅限于接口中定义的方法。这使得它在某些情况下更加灵活和强大，特别是对于没有实现接口的类进行代理。

无需接口：CGLIB 代理不依赖于接口，这对于一些只有具体实现类而没有接口的情况非常方便。Spring Boot 鼓励使用基于注解的开发，常见的 Bean 往往是普通的类，而不是接口的实现类。

简化配置：通过使用 CGLIB 代理，Spring Boot 可以自动完成代理的生成和注入，无需额外的配置。这样可以减少开发人员的工作量，简化配置过程

17.@Bean的工作原理  
spring容器启动时会扫描到该注解的类 如何解析该类，发现类中有@Bean注解，就会把名字作为bean的名字，把返回类型作为bean的类型，解析@Bean中的各个属性，解析该方法有没有其他注解 最后放入BeanDefinition对象中，解析BeanDefinition中的非懒加载的Bean，然后创建Bean

18.SpringBoot中用到的设计模式  
单例模式：spring中的大多数Bean都是单例Bean

简单工厂：BeanFactory ，Bean的工厂getBean创建Bean

工厂方法：factoryBean，实现这个接口重写getObject进行增强

代理模式：SpringAop，使用了动态代理 ，jdk动态代理和cglib字节码生产技术

模板方法模式：redisTemplate jdbcTemplate，里面提供了一些列模板方法

观察者模式：当一个对象的状态发生改变的时候，所有依赖于它的对象都会得到通知，比如ApplicationListener

策略模式：Bean的实例化包含原生对像的实例化和代理对象的实例化，不同的实例化内部逻辑不一样

装饰器模式：一些以Wrapper命名的类都是装饰器模式 。BeanWrapper去访问Bean的属性和方法的一个类

适配器模式：MVC模块的HandleAdapter就用到适配器模式

19.过滤器和拦截器的区别  
①：拦截器是基于java的反射机制的，而过滤器是基于函数的回调。 ②：拦截器不依赖于servlet容器，而过滤器依赖于servlet容器。 ③：拦截器只对action请求起作用，而过滤器则可以对几乎所有的请求起作用。 ④：拦截器可以访问action上下文、值、栈里面的对象，而过滤器不可以。 ⑤：在action的生命周期中，拦截器可以多次被调用，而过滤器只能在容器初始化时被调用一次。 ⑥：拦截器可以获取IOC容器中的各个bean，而过滤器不行，这点很重要，在拦截器里注入一个service，可以调用业务逻辑。

20.Static为什么不能依赖注入  
依赖注入是对对象而言的，而静态成员static不依赖于特定的对象，它与类的本身关联，所以spring不支持

21.Cookie和Session的区别  
他是客户端浏览器来保持服务端数据的一种机制，我们访问浏览器时，服务器会把某一些状态的数据以key-value的形式存储在Cookie中，客户端在下一次访问服务器的时候就能携带这些数据到服务端，服务端根据里面的数据识别使用者

session是一个会话，默认情况下服务端会根据每一个浏览器的请求servlet容器都分配一个session对象，本质上可以认为是一个currenthashmap，用来存储当前会话的数据，http本身是一个无状态的协议，服务端不知道客户端发来的多次请求是不是属于同一个用户，所以session是用来弥补http无状态的一个不足，服务端可以利用session存储用户端在同一个会话里面的产生的多次请求的一个记录，

这两者就能实现一个有状态的http协议

22.Component和Bean的区别  
用途不同：@Component普通标识类，@Bean标识配置类中Bean对象

使用方式不同：@Component是类级别的注解，Spring可以扫描被标注的类，并把它们注入到容器中。@Bean使用在方法上，表示此方法返回一个Bean对象注入到spring容器中

控制权不同，@Component备注的类是由Spring框架统一管理和创建，@Baen允许开发人员手动控制Bean的创建和配置

23.用户在浏览器输入url后会有什么操作  
DNS解析，浏览器会对输入的URL进行域名解析，查找到对应的IP地址，如果该域名被缓存过就直接去缓存获取，如果没被缓存就向本地DNS服务器发出请求，本地DNS没有缓存就会向根域名服务器发出请求来获取IP地址

进行TCP可靠性连接，浏览器向服务器进行三次握手操作，syn，syn-ack，ack三个阶段

发送http请求，向服务端发送http请求，请求返回响应数据

服务器响应请求，包括状态码，响应头，响应体

浏览器解析渲染

断开TCP连接，四次挥手fin，ack，fin，ack四个阶段

24.遇到死锁如何解决  
互斥条件

请求保持条件：在第一次执行的时候一次性申请所有的共享资源

不可抢占条件：在申请其他资源的时候，如果申请不到就主动放弃自己占有的资源

循环等待条件：按照顺序来申请锁资源

互斥条件是锁本身的特点所以不能被破坏，但凡涉及到互斥锁的地方都会有死锁的可能，行锁，表锁，分布式锁

25.SpringIoc工作流程  
IOC容器的初始化阶段，根据xml和注解等bean的声明方式，解析加载后生成BeanDefinition，然后把BeanDefinition注册到IOC容器中去，BeanDefinition实体包含Bean的一些定义，把他保持到map集合里面，是ioc容器控制反转的一个核心

完成初始化和依赖注入，通过反射对非懒加载的单例Bean进行初始化，完成Bean的依赖注入

Bean的使用，通过注解进行依赖注入使用