Spring(04)Spring Bean 基础
Spring(04)Spring Bean 基础
Spring 核心编程思想目录:https://www.cnblogs.com/binarylei/p/12290153.html
1. 定义 Spring Bean
BeanDefinition 是 Spring Framework 中定义 Bean 的配置元信息接口,包含:
- Bean 的类名
- Bean 行为配置元素,如作用域、自动绑定的模式,生命周期回调等
- 其他 Bean 引用,又可称作合作者(collaborators)或者依赖(dependencies)
- 配置设置,比如 Bean 属性(Properties)
2. BeanDefinition 元信息
属性(Property) | 说明 |
---|---|
Class | Bean 全类名,必须是具体类,不能用抽象类或接口 |
Name | Bean 的名称或者ID |
Scope | Bean 的作用域(如:singleton、prototype 等) |
Constructor | arguments Bean 构造器参数(用于依赖注入) |
Properties | Bean 属性设置(用于依赖注入) |
Autowiring mode | Bean 自动绑定模式(如:通过名称byName) |
Lazy initialization mode | Bean 延迟初始化模式(延迟和非延迟) |
Initialization method | Bean 初始化回调方法名称 |
Destruction method | Bean 销毁回调方法名称 |
BeanDefinition 构建
- BeanDefinitionBuilder
- AbstractBeanDefinition 以及派生类
3. 命名 Spring Bean
3.1 Bean 的名称
每个 Bean 拥有一个或多个标识符(identifiers),这些标识符在 Bean 所在的容器必须是唯一的。通常,一个Bean 仅有一个标识符,如果需要额外的,可考虑使用别名(Alias)来扩充。
在基于 XML 的配置元信息中,开发人员可用 id 或者 name 属性来规定 Bean 的标识符。通常 Bean 的标识符由字母组成,允许出现特殊字符。如果要想引入 Bean 的别名的话,可在 name 属性使用半角逗号(“,”)或分号(“;”) 来间隔。
Bean 的 id 或name 属性并非必须制定,如果留空的话,容器会为 Bean 自动生成一个唯一的名称。Bean 的命名尽管没有限制,不过官方建议采用驼峰的方式,更符合 Java 的命名约定。
3.2 Bean 名称生成器(BeanNameGenerator)
由 Spring Framework 2.0.3 引入,框架內建两种实现:
- DefaultBeanNameGenerator:默认通用BeanNameGenerator 实现
- AnnotationBeanNameGenerator:基于注解扫描的BeanNameGenerator 实现,起始于 Spring Framework 2.5,关联的官方文档:
4. Spring Bean 的别名
Bean 别名(Alias)的价值
- 复用现有的 BeanDefinition
- 更具有场景化的命名方法,比如:
<alias name="myApp-dataSource" alias="subsystemA-dataSource"/>
<alias name="myApp-dataSource" alias="subsystemB-dataSource"/>
5. 注册Spring Bean
5.1 BeanDefinition 注册
-
XML 配置元信息
<bean name=”...” />
-
Java 注解配置元信息
- @Bean
- @Component
- @Import
-
Java API 配置元信息
-
命名方式:
BeanDefinitionRegistry#registerBeanDefinition(String, BeanDefinition)
-
非命名方式:
BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition, BeanDefinitionRegistry)
-
配置类方式:
AnnotatedBeanDefinitionReader#register(Class...)
-
5.2 外部单例对象注册
-
Java API 配置元信息
SingletonBeanRegistry#registerSingleton
6. 实例化 Spring Bean
Bean 实例化(Instantiation)
- 常规方式
- 通过构造器(配置元信息:XML、Java 注解和 Java API )
- 通过静态工厂方法(配置元信息:XML 和 Java API )
- 通过 Bean 工厂方法(配置元信息:XML 和 Java API )
- 通过 FactoryBean(配置元信息:XML、Java 注解和 Java API )
- 特殊方式
- 通过 ServiceLoaderFactoryBean(配置元信息:XML、Java 注解和Java API )
- 通过 AutowireCapableBeanFactory#createBean(java.lang.Class, int, boolean)
- 通过 BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
7. 初始化 Spring Bean
Bean 初始化(Initialization)
- @PostConstruct 标注方法
- 实现InitializingBean 接口的afterPropertiesSet() 方法
- 自定义初始化方法
- XML 配置:<bean init-method=”init” ... />
- Java 注解:@Bean(initMethod=”init”)
- Java API:AbstractBeanDefinition#setInitMethodName(String)
思考:假设以上三种方式均在同一 Bean 中定义,那么这些方法的执行顺序是怎样?
8. 延迟初始化 Spring Bean
Bean 延迟初始化(Lazy Initialization)
- XML 配置:<bean lazy-init=”true” ... />
- Java 注解:@Lazy(true)
思考:当某个 Bean 定义为延迟初始化,那么,Spring 容器返回的对象与非延迟的对象存在怎样的差异?
9. 销毁 Spring Bean
Bean 销毁(Destroy)
- @PreDestroy 标注方法
- 实现 DisposableBean 接口的 destroy() 方法
- 自定义销毁方法
- XML 配置:<bean destroy=”destroy” ... />
- Java 注解:@Bean(destroy=”destroy”)
- Java API:AbstractBeanDefinition#setDestroyMethodName(String)
思考:假设以上三种方式均在同一Bean 中定义,那么这些方法的执行顺序是怎样?
10. 垃圾回收 Spring Bean
Bean 垃圾回收(GC)
- 关闭 Spring 容器(应用上下文)
- 执行 GC
- Spring Bean 覆盖的 finalize() 方法被回调
11. 面试题精选
问题1:如何注册一个 Spring Bean?
答:通过 BeanDefinition 和外部单体对象来注册。
问题2:什么是 Spring BeanDefinition?
答:回顾 "定义 Spring Bean" 和 "BeanDefinition 元信息”。
问题3:Spring 容器是怎样管理注册 Bean?
答:答案将在后续专题章节详细讨论,如:IoC 配置元信息读取和解析、依赖查找和注入以及 Bean 生命周期等。
每天用心记录一点点。内容也许不重要,但习惯很重要!