Spring
1.IOC
控制反转,传统开发中,通过new来创建对象,而IOC是将对象的创建,初始化,销毁交给了Spring容器。
IOC容器利用反射机制动态地加载类,创建对象实例以及调用对象方法。采用工厂模式来管理对象的生命周期,核心概念是依赖注入,由容器来管理类之间的依赖关系,包括构造函数注入,方法注入,字段注入。
2.AOP
面向切面编程,将与业务无关,却为业务模块所共同调用的逻辑封装起来(例如日志),以减少系统的重复代码,降低模块间的耦合度。
Spring AOP 是基于动态代理实现的,如果要代理的对象,实现了某个接口,那么 使用 JDK Proxy,去创建代理对象,而对于没有实现接口的对象,会使用 Cglib 生成一个被代理对象的子类来作为代理。在BeanPostProcessor中,把代理对象返回。
事务也是基于AOP实现的,在方法执行之前开启事务,执行之后提交事务
AOP里的概念:

3.循环依赖如何解决
三级缓存用来解决循环依赖问题:A类中有B属性,B类中有A属性
一级缓存:单例对象池,存储成品Bean,即实例化和初始化都完成的Bean
二级缓存:早期单例对象池,缓存半成品对象,且当前对象已经被其他对象引用了
三级缓存:单例工厂,通过工厂创建Bean
UserService和UserDao循环依赖的过程结合上述三级缓存描述一下
- UserService 实例化对象,但尚未初始化,将UserService存储到三级缓存;
- UserService 属性注入,需要UserDao,从缓存中获取,没有UserDao;
- UserDao实例化对象,但尚未初始化,将UserDao存储到到三级缓存;
- UserDao属性注入,需要UserService,从三级缓存获取UserService,UserService从三级缓存移入二级缓存;
- UserDao执行其他生命周期过程,最终成为一个完成Bean,存储到一级缓存,删除二三级缓存;
- UserService 注入UserDao;
- UserService执行其他生命周期过程,最终成为一个完成Bean,存储到一级缓存,删除二三级缓存。
三级缓存它不是直接缓存对象,而是缓存一个能生产对象的工厂。当发生循环依赖时,调用这个工厂的 getObject() 方法,这时 Spring 会判断:如果这个 Bean 最终需要代理,就提前生成代理对象并放入二级缓存;如果不需要代理,就返回原始对象。这样一来,B 注入的 A 就是最终形态(可能是代理对象),后续 A 初始化完成后也不会再创建新代理,保证了对象全局唯一。
4.Bean的生命周期

实例化阶段:会将xml配置的的信息封装成一个BeanDefinition 对象,所有的BeanDefinition存储到一个名为beanDefinitionMap 的Map集合中去,Spring框架在对该Map进行遍历,使用反射创建 Bean实例对象。在BeanDefinitionMap填充完毕 ,Bean实例化之前执行Bean工厂后处理器,用于对BeanDefinition注册和修改。
初始化阶段:填充Bean实例属性,Aware接口属性注入,Bean后处理器,InitializingBean接口的初始化方法回调,自定义初始化方法init回调
完成阶段:经过初始化阶段,Bean就成为了一个完整的Spring Bean,被存储到单例池singletonObjects中去了,即完成了Spring Bean的整个生命周期。
5.Spring的常用注解
@Atuowired:自动装配
@Component:标记一个类作为Spring的Bean @Service @Controller @Repository
@Configuration:配置类 @Bean:标记方法作为Bean工厂方法
6.Spring事务什么情况下会失效?
- 被代理方法不是public
- 方法被final修饰(或者是static)
- this调用 -- 手动生成一个代理对象去调用
- 对象未被Spring管理
- 不同数据源/数据库连接
- 自己捕获异常
- 抛出非运行时异常(只捕获运行时异常:
RuntimeException(运行时异常)和Error(错误))
7.Bean的作用域有哪些?
singleton:单例,默认值,Spring容器创建的时候,就会进行Bean的实例化,并存储到容器内部的单例池中,每次getBean时都是从单例池中获取相同的Bean实例;
prototype:原型,Spring容器初始化时不会创建Bean实例,当调用getBean时才会实例化Bean,每次getBean都会创建一个新的Bean实例。生成的Bean不会存在单例池中。容器不管理销毁
SpringMVC
1.介绍一下SpringMVC
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面。
流程步骤:
- 用户通过View 页面向服务端提出请求;
- 服务端 Controller 控制器接收到请求后对请求进行解析,找到相应的Model,对用户请求进行处理Model 处理;
- 将处理结果再交给 Controller;
- 根据处理结果找到要作为向客户端发回的响应View 页面,页面经渲染后发送给客户端
2.SpringMVC的处理流程

Spring MVC的工作流程如下:
-
用户发送请求至前端控制器DispatcherServlet
-
DispatcherServlet收到请求调用处理器映射器HandlerMapping。
-
处理器映射器根据请求url找到具体的处理器(Handler/Controller),生成处理器执行链HandlerExecutionChain(包括处理器对象和处理器拦截器)(多个拦截器方法的执行顺序)一并返回给DispatcherServlet。
-
DispatcherServlet根据处理器Handler获取处理器适配器HandlerAdapter执行HandlerAdapter处理一系列的操作,如:参数封装,数据格式转换,数据验证等操作
-
执行处理器Handler(Controller,也叫页面控制器)。
-
Handler执行完成返回ModelAndView
-
HandlerAdapter将Handler执行结果ModelAndView返回到DispatcherServlet
-
DispatcherServlet将ModelAndView传给ViewReslover视图解析器
-
ViewReslover解析后返回具体View
-
DispatcherServlet对View进行渲染视图(即将模型数据model填充至视图中)。
-
DispatcherServlet响应用户
3.过滤器和拦截器有什么区别?

- 所属规范:过滤器是 Java Servlet 规范的一部分,而拦截器是 Spring 框架提供的机制。
- 执行顺序:过滤器在请求进入 Servlet 容器后,在到达目标 Servlet 或控制器之前执行;拦截器在请求到达控制器之后,在控制器方法执行前后执行。
- 使用范围:过滤器可以对所有类型的请求进行过滤,包括静态资源请求;拦截器只能对 Spring MVC 控制器的请求进行拦截。
SpringBoot
1.自动装配原理
当Spring容器启动后,一些配置类、bean对象就自动存入到了IOC容器中,不需要我们手动去声明。
-
Spring Boot启动时加载@SpringBootApplication注解
-
该注解引入@EnableAutoConfiguration,进而触发自动配置机制
-
引入@Import(AutoConfigurationImportSelector.class),AutoConfigurationImportSelector类中读取META-INF/spring.factories中的自动配置类
-
过滤并排序这些自动配置类
-
根据条件注解判断哪些配置类应该生效
-
生效的配置类向容器中添加所需的Bean
2.起步依赖
igurationImportSelector类中读取META-INF/spring.factories中的自动配置类
-
过滤并排序这些自动配置类
-
根据条件注解判断哪些配置类应该生效
-
生效的配置类向容器中添加所需的Bean
2.起步依赖
原理是基于Maven的依赖传递。提供了快速的项目启动器,通过引入不同的 Starter,可以快速集成常用的框架和库(如数据库、消息队列、Web 开发等),极大地提高了开发效率。