SpringBoot学习总结
SpringBoot一些知识重点的整理,可在面试前复习回忆。
一、基础知识点
1. 什么是 Spring 框架?
简答: 一个轻量级 Java 框架,支持依赖注入、AOP 等,用于构建企业级应用。
Spring 是一个非常成熟的 Java 企业级开发框架,它的核心是通过 IoC(控制反转) 和 AOP(面向切面编程) 简化开发、提升可维护性。简单来说,它帮我们管理对象之间的依赖关系,把对象的创建和依赖注入交给框架完成,从而做到模块之间解耦。除了核心容器,Spring 还包括 Web、数据访问、安全、消息、测试等多个模块,几乎可以覆盖整个后端开发需求。
2. 什么是 Spring Boot?它和 Spring 有什么区别?
简答: Spring Boot 通过自动配置和内嵌服务器简化 Spring 应用的搭建。
Spring Boot 是在 Spring 基础上的快速开发框架,目标是让 Spring 项目开箱即用。
和Spring的区别主要体现在两点:
- Spring 是一个基础框架,但项目搭建和配置需要大量手动操作;
- Spring Boot 是一个增强工具,提供了自动配置、Starter 依赖、内嵌 Tomcat、Actuator 监控等,极大简化了开发流程。
3. 使用 Spring Boot 有什么优势?
简答: 快速开发、减少样板代码、生产就绪、易于集成。
Spring Boot 的优势主要有如下几点:
- 快速开发:starter + 自动配置,几行代码就能跑;
- 减少重复工作:不需要写大量 XML 或配置类;
- 内嵌服务器:比如 Tomcat、Jetty,打包后直接运行;
- 配置集中统一:使用 application.yml 或 application.properties 管理配置;
4. 什么是 Bean?怎么定义一个 Bean?
简答: Bean 是由 Spring IoC 管理的对象,可通过注解或配置类定义。
Bean 就是被 Spring 容器管理的对象,Spring 会自动把这些对象注册到容器中,并在需要的时候注入使用。
/* 两种定义方式 */// 1.注解方式:用 @Component、@Service、@Repository 等注解标记类;
// 2. Java配置方式:在 @Configuration 类中用 @Bean 方法返回对象:@Bean
public UserService userService() {return new UserServiceImpl();
}
5. Spring Bean 的生命周期是怎样的?
简答: 创建 → 属性注入 → 初始化 → 使用 → 销毁。
spring的bean的生命周期主要是创建bean的过程,一个bean的生命周期主要是5个步骤:实例化,属性注入,初始化,使用,销毁。
但是对于一些复杂的bean的创建,spring会在bean的生命周期中开放很多的接口,可以让你加载bean的时候对bean做一些改变,完整的过程如下:
#1. 创建
实现了BeanFactoryPostProcessor接口的bean,在加载其他的bean的时候,也会调用这个bean的postProcessBeanFactory方法,可以在这个步骤去对bean中的属性去赋值。
实现了InstantiationAwareBeanPostProcessor接口的bean,会在实例化bean之前调用postProcessBeforeInstantiation方法,然后在对bean进行实例化。#2. 属性注入
对bean进行属性注入#3.初始化
对bean进行初始化,在初始化中,包含了以下几个步骤:
1. 实现了BeanFactoryAware接口,会先调用setBeanFactory方法
2. 实现了BeanNameAware接口,会先调用setBeanName方法
3. 实现了BeanPostProcessor接口,会先调用postProcessBeforeInitialization方法
4. 实现了InitializingBean接口,会调用afterPropertiesSet方法
5. 然后在进行aop后置处理,通过实现BeanPostProcessor接口,在postProcessAfterInitialization方法中进行动态代理#4. 使用
#5. 销毁
6. 什么是 Spring 中的依赖注入(DI)?
简答: 一种设计模式,依赖关系由框架注入,而不是手动创建。
依赖注入(DI)就是把对象之间的依赖交给 Spring 框架来维护。比如你写了一个 Service,它依赖一个 DAO 层的 Bean,你不需要手动 new,而是让 Spring 自动注入:
@Autowired
private UserRepository userRepository;
这样做可以使得类与类之间通过接口+注入协作解耦合并且易于扩展(因为换实现类只需要改注入方式,不影响业务逻辑)。
7. @Component、@Service、@Repository 有什么区别?
简答: 都是组件注解,但语义不同,并在不同层有专属功能。
这三个注解本质上都是把类注册成 Spring 容器的组件 Bean,区别在于它们所代表的“层次语义”和某些“附加功能”。实际开发中,通过语义选择不同注解,能提高代码可读性和可维护性。
- @Component:通用组件,没有特定语义;
- @Service:业务逻辑层用,表达这是一个服务类;
- @Repository:持久层用,Spring 会对它的异常进行转换,比如把 SQLException 转成统一的
DataAccessException。
8. 什么是 ApplicationContext?
简答: 获取 Bean、配置等的核心接口。
ApplicationContext 是 Spring 的核心容器接口,它管理着所有 Bean 的创建、注入和生命周期。
常见的使用方式就是通过它来获取上下文中的某个 Bean 实例.Spring Boot 启动时也会创建一个 ApplicationContext,并将其作为容器入口。
applicationContext.getBean(UserService.class);
9. @SpringBootApplication 有什么作用?
简答: 是 @Configuration、@EnableAutoConfiguration、@ComponentScan 的组合。
@SpringBootApplication
是一个组合注解,等价于以下几个注解的组合。你只需要在入口类上加这一个注解,就能启用整个 Spring Boot 的自动配置机制,几乎是 Spring Boot 项目的标准写法。
@Configuration //表示该类是配置类;
@EnableAutoConfiguration //启用自动配置;
@ComponentScan // 自动扫描当前包及子包的组件。
10. 什么是 @EnableAutoConfiguration?
简答:告诉 Spring Boot 根据类路径中的内容去“猜测”并配置所需的 Bean。
@EnableAutoConfiguration 的作用就是开启自动配置功能。通俗讲,就是它会让 Spring Boot 根据你项目中引入的依赖,“猜”你想用什么,然后自动帮你配置好对应的 Bean,从而减少手动配置的工作量。比如:
你引入了 spring-boot-starter-web,Spring Boot 会自动配置 Tomcat、DispatcherServlet、Jackson 等,不需要写一堆 XML 或 @Bean 手动注册。
11. Spring Boot 是如何判断需要自动配置哪些内容的?
简答:通过 spring.factories 文件和一系列条件注解来判断,比如 @ConditionalOnClass。
Spring Boot 自动配置的背后是一个按需加载的机制,大致的判断步骤如下:
-
读取 spring.factories 文件:Spring Boot 在启动时会从所有依赖包里的
META-INF/spring.factories
文件中加载自动配置类列表。比如 WebAutoConfiguration、RedisAutoConfiguration 等。 -
条件注解判断(Conditional 系列):每个自动配置类上都会加上条件注解,例如:
@ConditionalOnClass
(类路径中存在某个类才生效) -
决定是否注入 Bean:如果条件满足,就把相应的 Bean 注册到容器中。
12. application.properties / application.yml 有什么作用?
简答: 用于存放配置,比如端口、数据库、日志等。
这两个文件是 Spring Boot 推荐的配置方式,两者本质一样,.yml 更适合结构化配置,.properties 更适合平铺式。
# 服务端口号
server.port=8081# 数据库配置
spring.datasource.url=...# 日志等级
logging.level.com.xxx=DEBUG# 第三方配置信息
Kafka
Redis
13. Singleton 和 Prototype 作用域有什么区别?
简答: Singleton 是默认的,每个容器一个实例;Prototype 每次获取一个新实例。
Spring 中 Bean 默认是单例的(Singleton),容器只会创建一个 Bean 实例,全局共用。而 Prototype 则是每次注入或获取都新建一个实例。在并发场景或者有状态组件中(比如线程绑定、缓存上下文),Prototype 更灵活;但需要开发者手动管理生命周期。
14. @Value 有什么用?
简答: 用于从配置文件注入值,支持 SpEL 表达式。
@Value
主要用于给属性注入值,来源通常是配置文件,也可以是表达式。如果是比较复杂的结构化配置,推荐用 @ConfigurationProperties
来映射配置文件,更安全。
@Value("${server.port}")
private int port;@Value("#{2 * 60}")
private int timeout;
15. 什么是 Spring AOP?
简答: 面向切面编程,抽离日志、事务、安全等横切关注点。
AOP 是面向切面编程的意思,它主要解决横切关注点的问题,比如日志、权限、事务控制等,Spring AOP 是基于代理机制实现的。
16. Spring 的核心模块有哪些?
简答: Core、Context、AOP、JDBC、ORM、Web、Security 等。
Spring 框架非常庞大,主要模块如下表,这些模块可以按需引入。
模块 | 作用 |
---|---|
Core / Beans / Context | IoC 容器相关 |
AOP | 切面编程支持 |
JDBC / ORM | 数据库访问 |
Web / WebMVC | Web 项目支持 |
Security | 认证授权 |
Test | 单元测试支持 |
17. 什么是循环依赖?Spring 如何解决?
简答: 两个或多个 Bean 相互依赖,可通过 setter 或延迟注入解决。
循环依赖就是 Bean A 依赖 Bean B,B 又依赖 A。Spring 解决方式:
- 三级缓存机制:提前暴露 Bean 的引用;
- 延迟初始化:使用 @Lazy;
- 调整注入方式:改用 setter 注入或 ObjectFactory 延迟获取。
二、重要注解
注解名 | 中文作用说明 |
---|---|
@ComponentScan | 指定 Spring 应该扫描哪些包,自动注册被注解的组件(如 @Component 等)。 |
@Component | 通用的组件注解,标识该类由 Spring 容器托管,自动作为一个 Bean 注册。 |
@RestController | 是 @Controller + @ResponseBody 的组合,用于开发 RESTful 接口,返回 JSON 或 XML。 |
@RequestMapping | 映射 HTTP 请求路径到处理方法上,可以设置方法、路径、参数等条件。 |
@Autowired | 按类型自动注入依赖 Bean,通常用于构造函数、字段或方法注入。 |
@ConditionalOnProperty | 仅在指定配置属性存在或符合预期值时才注册对应的 Bean,常用于控制功能开关。 |
@Profile | 仅在指定的激活环境(如 dev、prod)下才加载 Bean,常用于区分开发/生产环境配置。 |
@PropertySource | 加载外部配置文件(如 .properties)到 Spring 的 Environment 环境中。 |
@ConfigurationProperties | 将配置文件中的属性(如 application.yml)绑定到 Java Bean 上,便于参数集中管理。 |
@EnableConfigurationProperties | 开启 @ConfigurationProperties 支持,使其可以生效,常用于配置类上。 |
@EnableScheduling | 开启对定时任务(@Scheduled )的支持。 |
@Scheduled | 将方法标记为定时执行,可以基于 fixedDelay、fixedRate 或 cron 表达式。 |
@EnableAsync | 开启对异步方法(@Async )的支持。 |
@Async | 异步执行方法,在独立线程中运行,提高并发能力(如发送短信、邮件、日志等)。 |
三、事务管理
1. 什么是 @Transactional注解?
简答:用来声明式管理事务边界。
@Transactional
是 Spring 提供的声明式事务管理方式。它的作用把事务的开启、提交、回滚这些事情交给 Spring 管理。比如你写了一个涉及多个数据库操作的方法,只需要加上 @Transactional
,Spring 就会帮你管理好事务的边界。
2. @Transactional 应该加在哪一层?
简答:加在包含数据操作的 Service 层方法上。
一般建议把 @Transactional
放在 Service 层的方法上,而不是 DAO 层或 Controller 层。原因如下:
- Service 层是业务逻辑的核心,事务粒度和业务行为是一一对应的。
- DAO 层只是底层数据操作,不负责事务边界控制。
- Controller 层负责请求响应,不应该掺杂事务控制逻辑。
3. @Transactional(readOnly = true)和不加有什么区别?
简答:readOnly 优化只读场景的性能。
@Transactional(readOnly = true)
表示这个方法只读,不会进行数据修改。区别在于性能层面和底层数据库优化:不加则Spring 默认方法可能有修改操作,会开启事务;加上 readOnly = true
后Hibernate
会跳过“脏检查”。适合用于查询场景,比如分页查询。
4. @Transactional 能加在 private 方法上吗?
简答:不能,Spring 的 AOP 基于代理,只支持 public 方法。
不能。Spring 的默认事务管理基于 代理机制(Proxy-based AOP),只能拦截 public 方法。也就是说加在 private
或 protected
方法上,事务不会生效。注意,同一个类内部方法调用(即自调用)也无法触发事务代理。
5. 什么是 Spring 中事务的传播(Propagation)?
简答:提示:控制方法之间事务的传播行为。
事务的传播性(Propagation)决定了:当前方法被事务调用时,该怎么处理事务边界。Spring 支持的常用传播机制有 7 种,其中最常见的是以下三种。
传播属性 | 行为说明 |
---|---|
REQUIRED | 默认。如果有事务就加入,没有就新建一个 |
REQUIRES_NEW | 总是新建事务,原来的事务会挂起 |
NESTED | 在原事务中嵌套,可以单独回滚(基于 Savepoint) |
6. 多个 Service 嵌套调用时,事务怎么控制?
简答:使用
@Transactional
的传播属性(Propagation)控制事务行为。
在实际开发中,一个 Service 方法经常会调用另一个带事务的方法,这种嵌套事务就需要通过 Propagation
属性来控制。
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void sendCoupon() {// 启动一个新的事务,不受上层事务影响
}
7. 什么是事务的隔离级别(Isolation)?
简答:定义并发访问数据库时如何保证事务隔离性,防止脏读、不可重复读、幻读等。
事务的隔离级别是指:多个事务并发执行时,数据库如何隔离它们的数据视图,以保证数据一致性。 Spring 提供了与 JDBC 一致的五种隔离级别,可以通过@Transactional(isolation = Isolation.REPEATABLE_READ)
进行设置。
隔离级别 | 可防止的问题 |
---|---|
DEFAULT | 使用数据库默认设置 |
READ_UNCOMMITTED | 允许脏读 |
READ_COMMITTED | 防止脏读(Oracle 默认) |
REPEATABLE_READ | 防止脏读和不可重复读(MySQL 默认) |
SERIALIZABLE | 防止幻读,开销最大 |