Spring Bean

3 篇文章 0 订阅

Spring Bean

在 Spring 中,构成应用程序主体由 Spring IoC 容器管理的对象称为 Bean。Bean 是由 Spring IoC 容器实例化、装配和管理的对象。 Bean 以及它们之间的依赖关系反映在容器使用的配置元数据中。

Spring Bean 定义

BeanDefinition

Spring IoC 容器本身,并不能识别配置的元数据。为此,要将这些配置信息转为 Spring 能识别的格式——BeanDefinition 对象。

BeanDefinition 是 Spring 中定义 Bean 的配置元信息接口,它包含:

  • Bean 类名
  • Bean 行为配置元素,如:作用域、自动绑定的模式、生命周期回调等
  • 其他 Bean 引用,也可称为合作者(Collaborators)或依赖(Dependencies)
  • 配置设置,如 Bean 属性(Properties)
BeanDefinition 元信息

BeanDefinition 元信息如下:

属性(Property)说明
Class全类名,必须是具体类,不能用抽象类或接口
NameBean 的名称或者 ID
ScopeBean 的作用域(如:singletonprototype 等)
Constructor argumentsBean 构造器参数(用于依赖注入)
PropertiesBean 属性设置(用于依赖注入)
Autowiring modeBean 自动绑定模式(如:通过名称 byName)
Lazy initialization modeBean 延迟初始化模式(延迟和非延迟)
Initialization methodBean 初始化回调方法名称
Destruction methodBean 销毁回调方法名称
BeanDefinition 构建

BeanDefinition 构建方式:

  • 通过 BeanDefinitionBuilder

  • 通过 AbstractBeanDefinition 以及派生类

Spring Bean 命名

Spring Bean 命名规则

每个 Bean 拥有一个或多个标识符(identifiers),这些标识符在 Bean 所在的容器必须是唯一的。通常,一个 Bean 仅有一个标识符,如果需要额外的,可考虑使用别名(Alias)来扩充。

在基于 XML 的配置元信息中,开发人员可以使用 id 属性、name 属性或来指定 Bean 标识符。通常,Bean 的标识符由字母组成,允许出现特殊字符。如果要想引入 Bean 的别名的话,可在 name 属性使用半角逗号(“,”)或分号(“;”) 来间隔。

Spring 中,为 Bean 指定 idname 属性不是必须的。如果不指定,Spring 会自动为 Bean 分配一个唯一的名称。尽管 Bean 的命名没有限制,不过官方建议采用驼峰命名法来命名 Bean

Spring Bean 命名生成器

Spring 提供了两种 Spring Bean 命名生成器:

  • DefaultBeanNameGenerator:默认通用 BeanNameGenerator 实现。
  • AnnotationBeanNameGenerator:基于注解扫描的 BeanNameGenerator 实现。
public interface BeanNameGenerator {
   String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry);
}
Spring Bean 别名

Spring 支持通过 <alias> 属性为 Bean 设置别名。

Bean 别名(Alias)的作用:

  • 复用现有的 BeanDefinition
  • 更具有场景化的命名方法,比如:
    • <alias name="myApp-dataSource" alias="subsystemA-dataSource"/>
    • <alias name="myApp-dataSource" alias="subsystemB-dataSource"/>
<bean id="user" class="io.github.dunwu.spring.core.bean.entity.person.User">
  <!-- 属性略 -->
</bean>
<alias name="user" alias="aliasUser" />

Spring Bean 生命周期

  1. Spring 对 Bean 进行实例化(相当于 new XXX())

  2. Spring 将值和引用注入到 Bean 对应的属性中

  3. 如果 Bean 实现了 BeanNameAware 接口,Spring 将 Bean 的 ID 传递给 setBeanName 方法

   作用是通过 Bean 的引用来获得 Bean ID,一般业务中是很少有用到 BeanID
  1. 如果 Bean 实现了 BeanFactoryAware 接口,Spring 将调用 setBeanDactory 方法,并把 BeanFactory 容器实例作为参数传入。
   作用是获取 Spring 容器,如 Bean 通过 Spring 容器发布事件等
  1. 如果 Bean 实现了 ApplicationContextAware 接口,Spring 容器将调用 setApplicationContext 方法,把应用上下文作为参数传入
   作用与 `BeanFactory` 类似都是为了获取 Spring 容器,不同的是 Spring 容器在调用 `setApplicationContext` 方法时
   会把它自己作为 `setApplicationContext` 的参数传入,而 Spring 容器在调用 `setBeanFactory` 
   前需要使用者自己指定(注入)`setBeanFactory` 里的参数 `BeanFactory`
  1. 如果 Bean 实现了 BeanPostProcess 接口,Spring 将调用 postProcessBeforeInitialization 方法
   作用是在 Bean 实例创建成功后对其进行增强处理,如对 Bean 进行修改,增加某个功能
  1. 如果 Bean 实现了 InitializingBean 接口,Spring 将调用 afterPropertiesSet 方法,作用与在配置文件中对 Bean 使用 init-method 声明初始化的作用一样,都是在 Bean 的全部属性设置成功后执行的初始化方法。
  2. 如果 Bean 实现了 BeanPostProcess 接口,Spring 将调用 postProcessAfterInitialization 方法
   postProcessBeforeInitialization 是在 Bean 初始化前执行的,而
   postProcessAfterInitialization 是在 Bean 初始化后执行的
  1. 经过以上的工作后,Bean 将一直驻留在应用上下文中给应用使用,直到应用上下文被销毁
  2. 如果 Bean 实现了 DispostbleBean 接口,Spring 将调用它的 destory 方法,作用与在配置文件中对 Bean 使用 destory-method 属性的作用一样,都是在 Bean 实例销毁前执行的方法。

Spring Bean 注册

注册 Spring Bean 实际上是将 BeanDefinition 注册到 IoC 容器中。

XML 配置元信息

Spring 的传统配置方式。在 <bean> 标签中配置元数据内容。

缺点是当 JavaBean 过多时,产生的配置文件足以让你眼花缭乱。

注解配置元信息

使用 @Bean@Component@Import 注解注册 Spring Bean。

Java API 配置元信息

  • 命名方式:BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
  • 非命名方式:BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition,BeanDefinitionRegistry)
  • 配置类方式:AnnotatedBeanDefinitionReader#register(Class...)

Spring Bean 实例化

Spring Bean 实例化方式:

  • 常规方式
    • 通过构造器(配置元信息:XML、Java 注解和 Java API)
    • 通过静态方法(配置元信息:XML、Java 注解和 Java API)
    • 通过 Bean 工厂方法(配置元信息:XML、Java 注解和 Java API)
    • 通过 FactoryBean(配置元信息:XML、Java 注解和 Java API)
  • 特殊方式
    • 通过 ServiceLoaderFactoryBean(配置元信息:XML、Java 注解和 Java API )
    • 通过 AutowireCapableBeanFactory#createBean(java.lang.Class, int, boolean)
    • 通过 BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)

Spring Bean 初始化和销毁

Spring Bean 初始化和销毁的方式有以下几种:

  1. 使用 @PostConstruct@PreDestroy 注解分别指定相应的初始化方法和销毁方法。

  2. 实现 InitializingBean 接口的 afterPropertiesSet() 方法来编写初始化方法;实现 DisposableBean 接口的 destroy() 方法来编写销毁方法。

    • InitializingBean 接口包含一个 afterPropertiesSet 方法,可以通过实现该接口,然后在这个方法中编写初始化逻辑。
    • DisposableBean接口包含一个 destory 方法,可以通过实现该接口,然后在这个方法中编写销毁逻辑。
  3. 自定义初始化方法

    • XML 配置:<bean init-method="init" destroy="destroy" ... />
    • Java 注解:@Bean(initMethod = "init", destroyMethod = "destroy")
    • Java API:AbstractBeanDefinition#setInitMethodName(String)AbstractBeanDefinition#setDestroyMethodName(String) 分别定义初始化和销毁方法

注意:如果同时存在,执行顺序会按照序列执行。

Bean 的延迟初始化

  • xml 方式:<bean lazy-init="true" ... />
  • 注解方式:@Lazy

Spring 提供了一个 BeanPostProcessor 接口,提供了两个方法 postProcessBeforeInitializationpostProcessAfterInitialization。其中postProcessBeforeInitialization 在组件的初始化方法调用之前执行,postProcessAfterInitialization 在组件的初始化方法调用之后执行。它们都包含两个入参:

  • bean:当前组件对象;
  • beanName:当前组件在容器中的名称。

Spring Bean 垃圾回收

Spring Bean 垃圾回收步骤:

  1. 关闭 Spring 容器(应用上下文)
  2. 执行 GC
  3. Spring Bean 覆盖的 finalize() 方法被回调

Spring Bean 作用范围

ScopeDescription
singleton(Default) Scopes a single bean definition to a single object instance for each Spring IoC container.
prototypeScopes a single bean definition to any number of object instances.
requestScopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
sessionScopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
applicationScopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
websocketScopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.

参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码的搬运工-小刘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值