SpringBoot开发秘籍【个人八股】

SpringBoot开发秘籍【个人八股】 介绍一下 SpringBootSpring Boot极大地简化了 Spring 应用的开发和部署过程。以前我们用 Spring 开发项目的时候需要配置一大堆 XML 文件包括 Bean 的定义、数据源配置、事务配置等等非常繁琐。而且还要手动管理各种 jar 包的依赖关系很容易出现版本冲突的问题。部署的时候还要单独搭建 Tomcat 服务器整个过程很复杂。什么是数据源数据源是JDBC规范定义的接口本质是一个数据库连接池它封装了数据库连接的创建、复用和释放逻辑应用程序通过它获取连接即可执行SQL无需关心连接的生命周期管理。“约定大于配置”是 Spring Boot 最核心的理念。它预设了很多默认配置比如默认使用内嵌的 Tomcat 服务器默认的日志框架是 Logback 等等。这样我们开发者就只需要关注业务逻辑自动装配也是 Spring Boot 的一大特色它会根据项目中引入的依赖自动配置合适的 Bean。比如说我们引入了 Spring Data JPASpring Boot 就会自动配置数据源比如说我们引入了 Spring SecuritySpring Boot 就会自动配置安全相关的 Bean。Spring Boot 还提供了很多开箱即用的功能比如 Actuator 监控、DevTools 开发工具、Spring Boot Starter 等等。Actuator 可以让我们轻松监控应用的健康状态、性能指标等DevTools 可以加快开发效率比如自动重启、热部署等Spring Boot Starter 则是一些预配置好的依赖集合让我们可以快速引入某些常用的功能。简单来讲就是springboot相较于传统的spring框架是起到了一个简化开发的作用如果是传统的spring开发我们需要写很多的xml配置文件需要手动管理jar包之间的相互依赖以及bean的配置数据源配置事务的配置还需要手动搭建tomcat整个开发的前置过程是非常繁琐的因此我们引入了springboot这个spring快速开发的脚手架是基于spring的基础上预设了很多的基础配置让开发者更多的去关注业务的开发自动装配是springboot的一大特色比如我们需要引入某一个功能的时候springboot就会自动配置合适的bean。同时springboot也提供了很多开箱即用的功能springboot starter预设好了很多配置好的依赖集合就不需要去处理依赖之间的冲突问题可以帮助我们快速的引入对应的功能Spring Boot 和 Spring MVC / Spring 有什么区别我目前了解到的点springboot是约定大于配置springboot已经帮助我们完成了项目运行时需要的大部分的配置工作最基础的最底层的配置都已经是springboot帮助我们配置完成了。Spring Boot不是新框架而是基于 Spring 的快速开发脚手架主要解决配置繁琐、依赖冲突、部署复杂的问题。springMVC的话是model-view-controller模型而在现在的前后端分离分离开发模式当中对于view部分的工作已经不再是后端人员需要负责的内容Spring Boot 通过spring-boot-starter-web自动集成并配置了整个 Spring MVC Web 开发环境。在前后端分离项目中后端通常不再返回页面而是返回 JSON所以View 层弱化了但 Spring MVC 的整体机制仍然存在。spring的话是整个spring的全家桶如果不用springboot来辅助我们去进行配置就需要开发人员来对spring全家桶当中的每个工具库进行一个单独的配置工作同时也不方便我们对依赖进行统一的管理而且需要考虑依赖之间的冲突问题优化一句话版Spring 是一个基础框架核心能力是 IoC、AOP、事务管理等Spring MVC 是 Spring 中专门用于 Web 开发的模块负责处理 HTTP 请求和响应核心是 DispatcherServletSpring Boot 不是替代 Spring 的新框架而是基于 Spring 的快速开发脚手架通过自动配置、starter 依赖、内置 Tomcat 和统一版本管理简化了 Spring 项目的开发和部署。Spring Boot 自动配置原理是什么我的理解springboot进行自动配置springboot内置了一个IOC容器可以将常用的bean都放到这个IOC容器里面去当我们需要用到对应的工具的时候就直接从IOC容器进行依赖注入即可改进Spring Boot的自动装配原理了解吗在 Spring Boot 中开启自动装配的注解是EnableAutoConfiguration。这个注解会告诉 Spring 去扫描所有可用的自动配置类。Spring Boot 为了进一步简化把这个注解包含到了SpringBootApplication注解中。也就是说当我们在主类上使用SpringBootApplication注解时实际上就已经开启了自动装配。当main 方法运行的时候Spring 会去类路径下找spring.factories这个文件读取里面配置的自动配置类列表。比如在我们的技术派项目中paicoding-core 和 paicoding-service 模块里都有 spring.factories分别注册了 ForumCoreAutoConfig 和 ServiceAutoConfig这两个配置类就会在项目启动的时候被自动加载。然后每个自动配置类内部通常会有一个Configuration注解同时结合各种Conditional注解来做条件控制。像技术派的 RabbitMqAutoConfig 类就用了ConditionalOnProperty注解来判断配置文件里有没有开启 rabbitmq.switchFlag来决定是否初始化 RabbitMQ 消费线程。另外一个常见的场景是自动注入 Bean比如技术派的 ServiceAutoConfig 中就用了ComponentScan来扫描 service 包MapperScan扫描 MyBatis 的 mapper 接口实现业务层和 DAO 层的自动装配。执行过程具体的执行过程可以总结为Spring Boot 项目在启动时加载所有的自动配置类然后逐个检查它们的生效条件当条件满足时就实例化并创建相应的 Bean。自动装配的执行时机Spring 容器启动的时候。具体来说是在 ConfigurationClassPostProcessor 这个 BeanPostProcessor 中处理的它会解析Configuration类包括通过Import导入的自动配置类。一句话总结Spring Boot 自动装配就是根据 classpath 依赖、配置文件和容器中已有 Bean按条件自动加载配置类并创建 Bean。Spring Boot 启动流程大概是什么对于这个部分我没有深入的去想过改进Spring Boot 启动流程可以按这条主线记main()方法执行 → 创建 SpringApplication → 准备环境 → 创建 Spring 容器 → 加载 Bean 定义 → 刷新容器 → 启动 Web 服务器 → 执行启动后回调①、创建 SpringApplication 实例并识别应用类型比如说是标准的 Servlet Web 还是响应式的 WebFlux然后准备监听器和初始化监听容器。②、创建并准备 ApplicationContext将主类作为配置源进行加载。③、刷新 Spring 上下文触发 Bean 的实例化比如说扫描并注册ComponentScan指定路径下的 Bean。④、触发自动配置在 Spring Boot 2.7 及之前是通过 spring.factories 加载的3.x 是通过读取AutoConfiguration.imports并结合ConditionalOn系列注解依据条件注册 Bean。⑤、如果引入了 Web 相关依赖会创建并启动 Tomcat 容器完成 HTTP 端口监听。Spring Boot 启动时会先执行SpringApplication.run()然后创建SpringApplication对象准备运行环境加载配置文件创建 Spring 容器。接着解析启动类上的SpringBootApplication完成组件扫描和自动装配。之后调用容器的refresh()方法完成 Bean 的创建、依赖注入和初始化。如果是 Web 项目还会启动内置 Tomcat。最后执行ApplicationRunner、CommandLineRunner等启动后回调。Spring Boot 3 和 Spring Boot 2 有什么变化Spring Boot 3 相比 Spring Boot 2最大的变化是最低要求 Java 17底层升级到了 Spring Framework 6同时从 Java EE 的javax.*包迁移到了 Jakarta EE 的jakarta.*包这是升级时最容易出问题的地方。另外Spring Boot 3 对自动配置机制、安全配置、AOT 编译、GraalVM 原生镜像和可观测性都做了增强。Spring Security 也升级到了 6常见的WebSecurityConfigurerAdapter配置方式被新的SecurityFilterChain方式替代。Spring Boot 3 是基于 Java 17、Spring 6 和 Jakarta EE 的新一代 Boot核心变化是版本升级、javax到jakarta迁移以及原生镜像和可观测性的增强。你项目里的接口是怎么分层的我的回答我的项目内部接口分层采用的是controller层-service层-mapper层-数据库首先controller负责接收前端传递过来的所有请求并将这些请求适当的做一些处理比如说前端传递过来的参数是非常多的这每一个参数都有可能对应不同的service层接口因此需要对传递过来的参数进行分析分别取调用不同的业务层service接口接着是service层接口的调用主要的业务逻辑都是在这一层进行实现的如果需要对应的数据就去调用对应的mapper层接口去获取数据mapper层接口主要是实现了对数据库的操作实现了data的CRUD操作我项目里的接口主要按照 Controller、Service、Mapper 三层来拆分。Controller 负责接收请求和返回结果Service 负责核心业务逻辑Mapper 负责数据库操作。同时会区分 DTO、VO、Entity避免前端参数、业务对象和数据库对象混在一起。这样做的好处是职责清晰、代码解耦也方便后期维护和扩展。Spring Boot 中如何统一异常处理我的理解这个点需要考虑结合技术派项目中的全局异常处理器来回答!这个部分对于全局异常处理的注解有点遗忘了需要补充一下对于异常处理这部分感觉还是有点薄弱需要考虑补充一下这个部分的知识点Spring Boot 中通常使用RestControllerAdvice和ExceptionHandler做统一异常处理。RestControllerAdvice用来定义全局异常处理类ExceptionHandler用来捕获指定类型的异常。如何做参数校验对于这个部分也是一块空白Spring Boot 参数校验一般使用spring-boot-starter-validation。在请求 DTO 字段上加NotNull、NotBlank、Size、Email等注解然后在 Controller 参数上加Valid或Validated触发校验。校验失败后通过全局异常处理器捕获MethodArgumentNotValidException等异常统一返回错误信息。参数校验就是DTO 上写校验规则Controller 用Valid/Validated触发校验异常由全局异常处理统一返回。如何做接口幂等我的理解同一个请求执行一次和执行多次最终结果是一致的不会因为重复请求导致重复下单、重复支付、重复扣库存。可以考虑的解决方案首先最先相当的是用redisSETNX的方式只有在这个key不存在的情况下key才能创建成功并执行后续的业务代码否则key创建失败保证幂等性可以考虑使用token或者数据库数据库比如订单表中order_no加唯一索引但是需要考虑到可能会给数据库带来比较大的压力如果是redis可以做的事情为什么需要推到数据库身上呢可以考虑用状态机和乐观锁这两个都有一个思想就是去检查当前的状态/版本号这是两者的一个相似之处接口幂等主要是为了防止重复提交、网络重试、MQ 重复消费等场景导致数据重复处理。常见做法有几种第一种是 token 机制请求前生成 token请求时校验并删除第二种是 Redis 的SETNX用请求唯一 ID 作为 key只有第一次请求能成功第三种是数据库唯一索引比如订单号唯一防止重复插入第四种是通过业务状态机判断比如支付回调重复到达时如果订单已经支付就直接返回成功不再重复处理。接口幂等就是给请求或业务数据加一个唯一标识再结合 Redis、数据库唯一索引或状态判断保证重复请求不会重复执行业务逻辑。如何做全局响应封装我的理解可以与前端开发人员进行沟通确定我后端数据返回前端的格式/方式用统一的方式对数据进行一个封装的操作便于前端进行解析和处理Spring Boot 中做全局响应封装一般会先定义统一返回对象比如ResultT里面包含code、message、data。然后可以在 Controller 中手动返回Result.success(data)也可以使用ResponseBodyAdvice对接口返回值进行统一包装。成功响应统一封装异常响应则配合全局异常处理器返回统一错误格式。一句话总结全局响应封装就是通过统一 Result 对象加上 ResponseBodyAdvice 和全局异常处理让所有接口返回固定格式的数据。IOC说一说什么是IoCIoC 的全称是 Inversion of Control也就是控制反转。这里的“控制”指的是对象创建和依赖关系管理的控制权。请你说一说什么是控制反转这里的“控制”指的是对象创建和依赖关系管理的控制权。以前我们写代码的时候如果 A 类需要用到 B 类我们就在 A 类里面直接 new 一个 B 对象出来这样 A 类就控制了 B 类对象的创建。// 传统方式对象主动创建依赖 public class UserService { private UserDao userDao; public UserService() { // 主动创建依赖对象 this.userDao new UserDaoImpl(); } }有了 IoC 之后这个控制权就“反转”了不再由 A 类来控制 B 对象的创建而是交给外部的容器来管理。/** * 使用 Spring IoC 容器来管理 UserDao 的创建和注入 */ Service public class UserServiceImpl implements UserService { Autowired private UserDao userDao; // 不需要主动创建 UserDao由 Spring 容器注入 public BaseUserInfoDTO getAndUpdateUserIpInfoBySessionId(String session, String clientIp) { // 直接使用注入的 userDao return userDao.getBySessionId(session); } }对于DI你了解多少IoC 的思想是把对象创建和依赖关系的控制权由业务代码转移给 Spring 容器。而 DI也就是依赖注入它是实现 IoC 这种思想的具体技术手段。在 Spring 里我们用Autowired注解就是在使用 DI 的字段注入方式。为什么要用到IOC容器在日常开发中如果我们需要实现某一个功能可能至少需要两个以上的对象来协助完成在没有 Spring 之前每个对象在需要它的合作对象时需要自己 new 一个比如说 A 要使用 BA 就对 B 产生了依赖也就是 A 和 B 之间存在了一种耦合关系。有了 Spring 之后创建 B 的工作交给了 Spring 来完成Spring 创建好了 B 对象后就放到容器中A 告诉 Spring 我需要 BSpring 就从容器中取出 B 交给 A 来使用。至于 B 是怎么来的A 就不再关心了。这就是 IoC 的好处它降低了对象之间的耦合度让每个对象只关注自己的业务实现不关心其他对象是怎么创建的。框架Spring Boot 项目从启动到处理请求一、整体框架一句话springboot通过starter来引入依赖通过自动配置的方式来实现bean的生命周期Bean的生命周期由IOC容器进行管理运行时请求进入springMVC在请求的过程中会一次经过过滤器和拦截器同时可以考虑使用AOP来对业务进行增强处理其中事务就是用AOP机制来实现的。可以这样回答Spring Boot 项目启动时首先通过 Starter 引入相关依赖比如 Web、MyBatis、Redis 等。然后自动配置机制会根据 classpath、配置文件和条件注解自动创建对应的 Bean。Bean 的创建和依赖注入由 IOC 容器完成同时 Bean 会经历实例化、属性注入、初始化、后置处理等生命周期。在 Bean 生命周期中Spring 还会通过 BeanPostProcessor 创建 AOP 代理对象事务、日志等功能就是基于 AOP 实现的。项目启动完成后一个请求会先经过 Filter再进入 Spring MVC 的 DispatcherServlet然后通过 HandlerMapping 找到 Controller通过 HandlerAdapter 调用目标方法。Controller 调用 Service 时如果 Service 上有Transactional实际执行的是代理对象代理对象会在方法执行前开启事务执行成功后提交异常时回滚。所以整体来看Starter 负责依赖整合自动配置负责创建默认配置IOC 负责管理 BeanBean 生命周期负责 Bean 的创建和初始化Spring MVC 负责请求处理Filter、Interceptor、AOP 负责增强逻辑而事务传播机制就是 AOP 在业务层的典型应用。二、启动阶段Starter → 自动配置 → IOC → Bean 生命周期Spring Boot Starter 机制Starter 的作用是帮我们把一类功能需要的依赖和默认配置整合好。Starter 主要解决的是依赖整合 版本管理 自动配置入口。自动配置自动配置的作用是根据当前项目引入的依赖、配置文件和已有 Bean自动帮我们创建需要的 Bean。核心思想是你引了什么依赖、配了什么参数Spring Boot 就帮你装配什么功能。IOCIOC 的作用是把对象的创建、依赖注入、生命周期管理交给 Spring 容器。所以 IOC 解决的是对象创建和对象依赖关系管理的问题。换句话讲就是不需要手动的去new一个类Bean 生命周期Bean 生命周期描述的是一个 Bean 从创建到销毁的完整过程。实例化 Bean ↓ 属性注入 ↓ Aware 回调 ↓ BeanPostProcessor 前置处理 ↓ 初始化方法 ↓ BeanPostProcessor 后置处理 ↓ 放入单例池 ↓ 销毁这里和 AOP 有关系AOP 代理对象通常就是在 BeanPostProcessor 后置处理阶段生成的。所以一个 Service Bean 最终放进容器里的可能不是原始对象而是代理对象。三、运行阶段Spring MVC 请求流程Spring MVC 是 Spring 提供的 Web 模块核心是 DispatcherServlet它负责把请求分发到对应的 Controller 方法并将结果转换成响应返回给前端。浏览器 / 前端请求 ↓ Filter 过滤器 ↓ DispatcherServlet ↓ HandlerMapping 找 Controller ↓ HandlerAdapter 调用 Controller ↓ Interceptor 拦截器 ↓ Controller ↓ Service ↓ Mapper / DAO ↓ 数据库 ↓ 返回 JSON四、增强阶段Filter / Interceptor / AOPFilter 过滤器Filter 属于 Servlet 规范不是 Spring MVC 专属。它的位置最靠前请求 → Filter → DispatcherServletInterceptor 拦截器Interceptor 是 Spring MVC 提供的。它的位置在 DispatcherServlet 之后、Controller 之前DispatcherServlet → Interceptor → ControllerAOPAOP 是面向切面编程和 Web 不强绑定。它增强的是方法调用Controller / Service / Mapper 方法执行前后五、事务传播机制AOP 的典型应用事务传播机制主要解决多个加了Transactional的方法互相调用时事务之间如何协作的问题。比如A 方法有事务 ↓ 调用 B 方法 ↓ B 方法到底加入 A 的事务还是开启新事务这就是传播机制。六、把所有知识点串起来1. 项目启动时SpringApplication.run() 开始启动 Spring Boot 项目。 2. Spring Boot 通过 Starter 引入相关依赖比如 starter-web 引入 Spring MVC、Tomcat、Jackson。 3. 自动配置机制根据 classpath 依赖、配置文件和条件注解自动加载配置类注册 BeanDefinition。 4. IOC 容器负责创建 Bean并完成依赖注入。 5. Bean 创建过程中会经历生命周期比如实例化、属性注入、初始化、BeanPostProcessor。 6. AOP 代理对象通常在 BeanPostProcessor 后置处理阶段生成所以事务、日志等功能可以对 Bean 方法进行增强。 7. 项目启动完成后HTTP 请求先进入 Filter再进入 Spring MVC 的 DispatcherServlet。 8. DispatcherServlet 通过 HandlerMapping 找到 Controller再通过 HandlerAdapter 调用目标方法。 9. 调用 Controller 前后可能会经过 Interceptor。 10. Controller 调用 Service 时如果 Service 方法有 Transactional实际调用的是 AOP 代理对象由代理对象控制事务提交或回滚。 11. Service 调用 Mapper 访问数据库最后结果通过 HttpMessageConverter 转成 JSON 返回前端。