0.什么是Spring Bean
在Spring中,构成应用程序主体由Spring IoC容器管理的对象称为Bean
Bean是由Spring IoC容器实例化、装配和管理的对象
1.BeanDefinition
Spring IoC容器本身,并不能识别配置的元数据,要将这些配置信息转为Spring能识别的格式——BeanDefinition对象
BeanDefintion是Spring中定义Bean的配置元信息接口,它包含:
- Bean类名
- Bean行为元素,如:作用域,自动绑定的模式,生命周期回调等
- 其他Bean引用,也可称为合作者或依赖
- 配置设置,如Bean属性
1.1 BeanDefinition元信息
BeanDefinition 元信息如下:
| 属性(Property) | 说明 |
|---|---|
| Class(opens new window) | 全类名,必须是具体类,不能用抽象类或接口 |
| Name(opens new window) | Bean 的名称或者 ID |
| Scope(opens new window) | Bean 的作用域(如:singleton、prototype 等) |
| Constructor arguments(opens new window) | Bean 构造器参数(用于依赖注入) |
| Properties(opens new window) | Bean 属性设置(用于依赖注入) |
| Autowiring mode(opens new window) | Bean 自动绑定模式(如:通过名称 byName) |
| Lazy initialization mode(opens new window) | Bean 延迟初始化模式(延迟和非延迟) |
| Initialization method(opens new window) | Bean 初始化回调方法名称 |
| Destruction method(opens new window) | Bean 销毁回调方法名称 |
1.2 BeanDefinition构建
构建方式:
- BeanDefintionBuilder
- AbstractBeanDefintion以及派生类
2.Spring Bean命名
2.1 Spring Bean命名规则
每个Bean都需要一个唯一的标识符;如果需要额外的,可考虑使用别名(Alias)
基于XML的配置元信息中,可以使用id或name属性来指定Bean标识符
如果不指定,Spring会自动为Bean分配一个唯一的名称
2.2 SpringBean 命名生成器
Spring提供了两种Spring Bean命名生成器:
- DefaultBeanNameGenerator:默认使用通过 BeanNameGenerator 实现。
- AnnotationBeanNameGenerator:基于注解扫描实现的 BeanNameGernerator 实现。
2.3 Spring Bean别名
Spring支持通过 属性为Bean设置别名
作用:复用
<bean id="myBean" class="com.example.MyBean" />
<alias name="myBean" alias="aliasBean1" />
<alias name="myBean" alias="aliasBean2" />
3. Spring Bean生命周期
在Spring中,Bean的声明周期可以分为以下几个阶段:
- 实例化(Instantiation): 在容器启动时,Spring会根据Bean的定义信息(如类名、构造函数参数等)来实例化Bean对象。
- 属性设置(Population): 在Bean实例化之后,Spring会将Bean的属性(如基本类型属性、引用类型属性)设置到Bean实例中。
- 初始化(Initialization): 在属性设置完成后,Spring会调用Bean的初始化方法。可以通过配置init-method属性或实现InitializingBean接口来指定初始化方法。
- 使用(In Use): Bean实例化、属性设置和初始化完成后,Bean将处于可用状态,可以被其他Bean或应用程序代码使用。
- 销毁(Destruction): 当Spring容器关闭时,会调用Bean的销毁方法来清理资源。可以通过配置destroy-method属性或实现DisposableBean接口来指定销毁方法。
4. 将一个类声明为Bean的注解
- @Component:通过的注解,可标注任意类为Spring组件
- @Repository:Dao层,数据库相关操作
- @Service:业务层,业务逻辑处理
- @Controller:Spring MVC控制层,接受请求调用Service层返回数据
5. @Component和@Bean的区别
用法:
- @Component用于类
- @Bean注解作用于方法
生成方法:
- @Component:Spring在扫描类路径时会自动检测带有@Component注解的类,并将其注册为Bean
- @Bean:被标记的方法会在Spring容器启动时被调用,并且返回对象会被注册成一个Bean
灵活性:
- @Bean注解比@Component注解的自定义性更强,比如当我们引用第三方库中的类需要装配到Spring容器时,则只能通过@Bean来实现
6.@Autowired和@Resource的区别
来源:
- @Autowired:Spring提供的注解
- @Resource:JDK提供的注解
注入方式:
- @Autowired:byType(根绝类型匹配)
- @Resource:byName(根据名称进行匹配)
但是当一个接口存在多个实现类的情况下,@Autowired和@Resource都需要通过名称才能正确匹配· 到对应的Bean
Autowired 可以通过 @Qualifier 注解来显式指定名称
// 报错,byName 和 byType 都无法匹配到 bean
@Autowired
private SmsService smsService;
// 正确注入 SmsServiceImpl1 对象对应的 bean
@Autowired
private SmsService smsServiceImpl1;
// 正确注入 SmsServiceImpl1 对象对应的 bean
// smsServiceImpl1 就是我们上面所说的名称
@Autowired
@Qualifier(value = "smsServiceImpl1")
private SmsService smsService;
@Resource可以通过 name 属性来显式指定名称。
// 报错,byName 和 byType 都无法匹配到 bean
@Resource
private SmsService smsService;
// 正确注入 SmsServiceImpl1 对象对应的 bean
@Resource
private SmsService smsServiceImpl1;
// 正确注入 SmsServiceImpl1 对象对应的 bean(比较推荐这种方式)
@Resource(name = "smsServiceImpl1")
private SmsService smsService;
可使用范围:
- @Autowired:支持在构造函数、方法、字段和参数上使用
- @Resource:主要用于字段和方法上的注入,不支持在构造函数或参数上使用
7.Bean的作用域
Spring中的Bean的作用域通常有下面几种:
- singleton:IoC容器中只有唯一的bean实例
- prototype:每次获取都会创建一个新的bean实例
- request(仅Web应用可用):每一次HTTP请求都会产生一个新的Bean,仅在当前HTTP requets内有效
- session(仅Web引用可用):每一次来自新Session的HTTP请求都会产生一个新的Bean(会话bean),该bean仅在当前HTTP session有效
- application/global-session(仅Web应用可用):每个Web应用启动时创建一个Bean(应用Bean),该Bean仅在当前应用启动时间内有效
- websocket(仅Web应用可用):每一个WebSocket会话产生一个新的bean
如何配置bean的作用域呢?
xml方式:
<bean id="..." class="..." scope="singleton"></bean>
注解方式:
@Bean
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Person personPrototype() {
return new Person();
}