Jul 05, 2022
Spring 学习-1
1. IoC 容器
- Inversion of Control (IoC)
1.1. Spring IoC Container & Bean
IoC 也成为依赖注入,是对象仅通过*构造函数参数、工厂方法的参数 或在对象实例被构造 或从工厂方法返回后在对象实例上设置的属性来定义它们的依赖项。*
- 容器在创建 Bean 时注入这些依赖性。这个过程是 Bean 本身的逆过程,因此得名控制反转
- 在 Spring 中,构成应用程序主干并由 Spring IoC 容器管理的对象称为 bean。
- bean 是由 Spring IoC 容器实例化、组装和管理的对象。 否则,bean 只是应用程序中众多对象之一。 Bean 以及它们之间的依赖关系反映在容器使用的配置元数据中。
1.2. 容器概述
org.springframework.context.ApplicationContext
接口代表 Spring IoC 容器,负责实例化、配置和组装 bean。 容器通过读取配置元数据来获取有关要实例化、配置和组装哪些对象的指令。 配置元数据以 XML、**Java 注解**或 Java 代码表示。 它可以让您表达组成应用程序的对象以及这些对象之间丰富的相互依赖关系。
- 一般来说,创建并初始化了
ApplicationContext
后,就有了一个完全配置且可执行的系统或应用程序
1.2.1. 配置元数据
方式主要有三
- 基于 XML(基本用不到,不详述)
- 基于注解(后文提到)
- 基于 Java(后文提到)
1.2.2. 实例化容器
- Spring 的实例化用的比较少了,略
1.2.3. 使用容器
- Spring 的实例化用的比较少了,略
1.3. Bean 概述
- 略
1.4. 依赖关系
1.4.1. 依赖注入
- 基于构造函数的依赖注入
- 基于构造函数的 DI 是通过容器调用具有多个参数的构造函数来完成的,每个参数代表一个依赖项。 调用带有特定参数的
static
工厂方法来构造 bean 几乎是等效的,本讨论将类似地处理构造函数和static
工厂方法的参数。 以下示例显示了一个只能使用构造函数注入进行依赖注入的类
- 基于构造函数的 DI 是通过容器调用具有多个参数的构造函数来完成的,每个参数代表一个依赖项。 调用带有特定参数的
public class SimpleMovieLister { |
SpringBoot 中多用注解结合构造函数进行 DI
- 构造函数参数解析
- 构造函数参数解析匹配通过使用参数的类型发生。 如果 bean 定义的构造函数参数中不存在潜在的歧义,那么在 bean 定义中定义构造函数参数的顺序就是在实例化 bean 时将这些参数提供给适当的构造函数的顺序。
- Spring 中构造函数消歧义的问题
- 略,SpringBoot 中很少碰到
- 依赖解析流程
- 容器执行 bean 依赖解析如下:
ApplicationContext
是用描述所有 bean 的配置元数据创建和初始化的。 配置元数据可以由 XML、Java 代码或注解指定。- 对于每个 bean,它的依赖关系以属性、构造函数参数或静态工厂方法的参数(如果您使用它而不是普通构造函数)的形式表示。 在实际创建 bean 时,将这些依赖关系提供给 bean。
- 每个属性或构造函数参数都是要设置的值的实际定义,或者是对容器中另一个 bean 的引用。
- 作为值的每个属性或构造函数参数都从其指定格式转换为该属性或构造函数参数的实际类型。 默认情况下,Spring 可以将字符串格式提供的值转换为所有内置类型,例如
int
、long
、String
、boolean
等等。
- 容器执行 bean 依赖解析如下:
1.5. 基于注解的容器配置
1.5.1. @Required
@Required
注解适用于 bean 属性 setter 方法,如下例所示:
public class SimpleMovieLister { |
此注解表明必须在配置时通过 bean 定义中的显式属性值或通过自动装配来填充受影响的 bean 属性。 如果尚未填充受影响的 bean 属性,则容器将引发异常。 避免以后出现 NullPointerException
实例等。
@Required
注解和RequiredAnnotationBeanPostProcessor
从 Spring Framework 5.1 开始正式弃用,赞成使用构造函数注入进行所需设置(或InitializingBean.afterPropertiesSet 的自定义实现 ()
或自定义@PostConstruct
方法以及 bean 属性 setter 方法)
1.5.2. @Autowired
您可以将 @Autowired
注解应用于构造函数
public class MovieRecommender { |
从 Spring Framework 4.3 开始,如果目标 bean 只定义了一个构造函数,则不再需要在这样的构造函数上添加
@Autowired
注解。 但是,如果有多个构造函数可用且没有主/默认构造函数,则必须至少用@Autowired
注解其中一个构造函数,以便指示容器使用哪一个。
您还可以将 @Autowired
注解应用于 传统 setter 方法,如以下示例所示:
public class SimpleMovieLister { |
您还可以将注解应用于具有任意名称和多个参数的方法,如以下示例所示:
public class MovieRecommender { |
您也可以将 @Autowired
应用于字段,甚至将其与构造函数混合,如下例所示:
public class MovieRecommender { |
您还可以通过将 @Autowired
注解添加到需要该类型数组的字段或方法来指示 Spring 从 ApplicationContext
提供特定类型的所有 bean,如 以下示例显示:
public class MovieRecommender { |
默认情况下,当给定注入点没有匹配的候选 bean 可用时,自动装配失败。 对于声明的数组、集合或映射,至少需要一个匹配元素。
默认行为是将带注解的方法和字段视为指示所需的依赖项。 您可以更改此行为,如下例所示,通过将不可满足的注入点标记为非必需(即,通过在 @ 自动连线
到false
):
public class SimpleMovieLister { |
1.5.3. @Primary
@Primary
表示当多个 bean 是自动装配到单值依赖项的候选者时,应优先考虑特定 bean。 如果候选中恰好存在一个主要 bean,则它成为自动装配的值。
|
1.5.4. 使用泛型作为自动装配限定符
- 可以用泛型和
@Autowired
搭配装配
1.5.5. @Resource
Spring 还通过在字段或 bean 属性 setter 方法上使用 JSR-250 @Resource
注解 (javax.annotation.Resource
) 来支持注入。
在没有指定显式名称的 @Resource
用法的唯一情况下,与 @Autowired
类似,@Resource
找到主要类型匹配而不是 一个特定的命名 bean 并解析众所周知的可解析依赖项:BeanFactory
、ApplicationContext
、ResourceLoader
、ApplicationEventPublisher
和 MessageSource
接口。
1.5.6. @Value
@Value
通常用于注入外化属性:
|
使用以下配置:
|
以及以下 application.properties
文件:
catalog.name=MovieCatalog |
在这种情况下,catalog
参数和字段将等于 MovieCatalog
值。
Spring 提供了一个默认的宽松嵌入值解析器。 它将尝试解析属性值,如果无法解析,则属性名称(例如 ${catalog.name}
)将作为值注入。 如果你想对不存在的值保持严格的控制,你应该声明一个 PropertySourcesPlaceholderConfigurer
bean,如下例所示:
|
Spring Boot 默认配置一个
PropertySourcesPlaceholderConfigurer
bean,它将从application.properties
和application.yml
文件中获取属性。
当 @Value
包含 SpEL
表达式 时,该值将在运行时动态计算,如下例所示:
- 注:SpEL 表达式是 Spring 表达式语言
|
1.5.7. @Component 和进一步的定型注解
@Repository
注解是任何实现存储库角色或构造型(也称为数据访问对象或 DAO)的类的标记。 此标记的用途之一是自动转换异常。
Spring 提供了更多构造型注解:@Component
、@Service
和 @Controller
。 @Component
是任何 Spring 管理的组件的通用构造型。
@Repository
、@Service
和 @Controller
是 @Component
的特化,用于更具体的用例(在分别为持久层、服务层和表示层)。因此,您可以使用 @Component
注解您的组件类,但是,通过使用 @Repository
、@Service
或 @ 注解它们Controller
相反,您的类更适合由工具处理或与切面相关联。例如,这些构造型注解是切入点的理想目标。 @Repository
、@Service
和 @Controller
还可以在 Spring Framework 的未来版本中携带额外的语义。因此,如果您在服务层使用 @Component
或 @Service
之间做出选择,@Service
显然是更好的选择。同样,如前所述,@Repository
已经被支持作为持久层中自动异常转换的标记。
1.6. 基于 Java 的容器配置
1.6.1. @Bean 和@Component
Spring 的新 Java 配置支持中的核心工件是 @Configuration
注解类和 @Bean
注解方法。
@Bean
注解用于指示一个方法实例化、配置和初始化一个由 Spring IoC 容器管理的新对象。 对于熟悉 Spring 的 ``XML 配置的人来说,
@Bean注解与元素扮演着相同的角色。 您可以将带有
@Bean注解的方法与任何 Spring
@Component一起使用。 然而,它们最常与
@Configuration` bean 一起使用。
用 @Configuration
注解一个类表明它的主要目的是作为 bean 定义的来源。 此外,@Configuration
类允许通过调用同一类中的其他 @Bean
方法来定义 bean 间的依赖关系。 最简单的 @Configuration
类如下:
|
使用 Component 注解
@Configuration
是一个类级别的注解,表明一个对象是 bean 定义的来源。 @Configuration
类通过带有 @Bean
注解的方法来声明 bean。 对 @Configuration
类上的 @Bean
方法的调用也可用于定义 bean 间的依赖关系。