什么是 Spring 和 SpringBoot

Spring 是什么

Spring Framework 是很多模块的集合,使用这些模块可以很方便地协助我们进行开发;核心功能是 IoC 和 AOP。
下图是 Spring 中各个模块之间的依赖关系。需要大概知道一些模块是干嘛的。

  1. Core Container:基础模块,包含spring-core、spring-beans等
  2. Data Access/Integration:数据访问模块,包含spring-jdbc、spring-orm等
  3. Spring Web:网络部分,包含spring-webmvc、spring-websocket等等

JavaGuide-Spring模块的依赖关系

Spring Boot

SpringBoot是用来快速开发Spring应用的一个脚手架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程;

SpringBoot提供了很多内置的Starter(⼀系列依赖关系的集合)结合自动配置,对主流框架如 Redis MySQL无需配置或开箱即用;

SpringBoot简化了开发,采用JavaConfig的方式可以使用零xml的方式进行开发,配置即自动装配;

SpringBoot内置Web容器无需依赖外部Web服务器,省略了Web.xml,直接运行jar文件就可以启动web应用;

SpringBoot帮我管理了常用的第三方的依赖版本,减少出现版本冲突的问题; SpringBoot自带了监控功能,可以监控应用程序的运行状况,或者内存,线程池,Http请求统计等,同时还提供了优雅关闭应用程序等功能。

什么是Spring IoC

IoC 的思想就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。这样就把应用从复杂的依赖关系中解放出来,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。

在 Spring 中, IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个 Map(key,value),Map 中存放的是各种对象。

@Bean 和 @Component 和 @Configuration

  1. Spring会自动检测被Component注解的类,并将其作为bean注册到IoC容器中。但是不能用于第三方库,因为不能修改他们的源码,这时候要用到bean
  2. bean是方法注解,一般会在配置类Configuration中编写方法,返回值将被注册为 Spring IoC 容器中的一个 bean;不推荐在Component类中对方法添加@Bean注解,这样会导致非预期的Bean实例化问题
1
2
3
4
5
6
7
8
9
10
11
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyService(); // 显式创建 MyService 实例
}
@Bean
public AnotherBean anotherBean(MyService myService) { // 自动注入其他 bean
return new AnotherBean(myService);
}
}

如果方法被 @Bean 注解,并且方法的参数是 Spring IoC 容器中已存在的 Bean 对象,那么 Spring 会自动将这些 Bean 注入到方法中。

@Autowired 和 @Resource

@Bean 和 @Component 是告诉Spring IoC,某个类需要IoC进行管理;而@Autowired 和 @Resource则是告诉 Spring 框架,我需要使用某个Bean,需要进行依赖注入(DI)

@Autowired 用于自动注入 Bean 依赖项,它默认按照类型进行注入。它可以标注在构造器、字段、Setter 方法或配置方法上,Spring 容器会自动查找匹配类型的 Bean 并将其注入。

当存在多个相同类型的 Bean 时,@Autowired 默认按类型注入可能产生歧义。此时,可以与 @Qualifier 结合使用,通过指定 Bean 的名称来精确选择需要注入的实例;或者使用 @Primary 方法将某个实现设为首选注入对象。

@Resource(name="beanName") 默认按名称 (by Name) 查找 Bean 进行注入,

依赖注入的常见方式

以下三种方式的初始化时间依次推迟:

  1. 构造函数注入:通过类的构造函数来注入依赖项(最佳实践);
  2. Field(字段) 注入:直接在类的字段上使用注解(如 @Autowired@Resource)来注入依赖项;
  3. Setter 注入:通过类的 Setter 方法来注入依赖项(官方更推荐使用构造函数注入);

Spring 循环依赖

循环依赖是指 Bean 对象循环引用,是两个或多个 Bean 之间相互持有对方的引用。Spring 框架通过使用三级缓存来解决这个问题,确保即使在循环依赖的情况下也能正确创建 Bean。

Bean 的生命周期

image-20250705111012950

Bean的作用域和线程安全

Spring 中 Bean 的作用域通常有下面几种:

  • singleton : IoC 容器中只有唯一的 bean 实例。Spring 中的 bean 默认都是单例的,是对单例设计模式的应用。
  • prototype : 每次获取都会创建一个新的 bean 实例。也就是说,连续 getBean() 两次,得到的是不同的 Bean 实例。
  • request (仅 Web 应用可用): 每一次 HTTP 请求都会产生一个新的 bean(请求 bean),该 bean 仅在当前 HTTP request 内有效。
  • session (仅 Web 应用可用) : 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean(会话 bean),该 bean 仅在当前 HTTP session 内有效。
  • application/global-session (仅 Web 应用可用):每个 Web 应用在启动时创建一个 Bean(应用 Bean),该 bean 仅在当前应用启动时间内有效。
  • websocket (仅 Web 应用可用):每一次 WebSocket 会话产生一个新的 bean。

详细解释见:https://g.co/gemini/share/e923f73db565

AOP 相关

面向切面编程,是OOP的一种延续,OOP 不能很好地处理一些分散在多个类或对象中的公共行为(如日志记录、事务管理、权限控制、接口限流、接口幂等等),而 AOP 可以将横切关注点(如日志记录、事务管理、权限控制、接口限流、接口幂等等)从 核心业务逻辑 中分离出来,实现关注点的分离。

主要通过注解的方式实现,且以方法为单位,可以在方法运行前和结束后添加额外逻辑,为代理模式,会在bean生命周期中生成一个代理对象。主要有如下通知类型:

  1. 前置通知(Before):在目标方法执行之前执行。
  2. 后置通知(After):在目标方法执行之后执行,无论方法是否成功完成。
  3. 返回通知(AfterReturning):在目标方法成功执行并返回结果后执行。
  4. 异常通知(AfterThrowing):在目标方法抛出异常后执行。
  5. 环绕通知(Around):在目标方法执行前后都执行,甚至可以控制目标方法是否执行。

类限定:Pointcut表达式

  1. within()和target()
  2. @within()和@target()
  3. execute()

@SpringBootApplication 注解

用于标注主启动类,如下:

1
2
3
4
5
6
@SpringBootApplication
public class SpringSecurityJwtGuideApplication {
public static void main(java.lang.String[] args) {
SpringApplication.run(SpringSecurityJwtGuideApplication.class, args);
}
}

可以看出⼤概可以把 @SpringBootApplication 看作是@Configuration@EnableAutoConfiguration@ComponentScan注解的集合。根据 SpringBoot 官⽹,这三个注解的作⽤分别是:

  1. @EnableAutoConfiguration:启⽤ SpringBoot 的⾃动配置机制
  2. @ComponentScan:扫描被@Component (@Service , @Controller)注解的 bean,注解默认会扫描该类所在的包下所有的类(启动类在src最外层)
  3. @SpringBootConfiguration:也可能是@Configuration,表示启动类也是一个配置类,允许在上下⽂中注册额外的 bean 或导⼊其他配置类,支持JavaConfig的方式进行配置(?)

SpringBoot 自动装配的原理

理解得还不够透彻

  1. @EnableAutoConfiguration是启动⾃动配置的关键
  2. 里面@ImportAutoConfigurationImportSelector,用于选择出所有需要自动配置的类,同时也会让SpringBoot的自动配置类的注入顺序在最后
  3. 这里面会去读取一个文件spring.factories,并根据@Condition的相关注解进行筛选,最后完成注入

Http 请求的相关注解

  1. @PathVariable
  2. @RequestParam

若请求 URL 为 /klasses/123/teachers?type=web,则 klassId = 123 为 PathVariable,type = web 为 RequestParam。

  1. @RequestBody