Spring Bean

106 阅读5分钟

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 的作用域(如:singletonprototype 等)
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的配置元信息中,可以使用idname属性来指定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生命周期

image-20240611143813628

在Spring中,Bean的声明周期可以分为以下几个阶段:

  1. 实例化(Instantiation): 在容器启动时,Spring会根据Bean的定义信息(如类名、构造函数参数等)来实例化Bean对象。
  2. 属性设置(Population): 在Bean实例化之后,Spring会将Bean的属性(如基本类型属性、引用类型属性)设置到Bean实例中。
  3. 初始化(Initialization): 在属性设置完成后,Spring会调用Bean的初始化方法。可以通过配置init-method属性或实现InitializingBean接口来指定初始化方法。
  4. 使用(In Use): Bean实例化、属性设置和初始化完成后,Bean将处于可用状态,可以被其他Bean或应用程序代码使用。
  5. 销毁(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();
 }