Spring学习之@Bean
文章目录
注解说明
@Bean 是Spring的一个核心注解,通常与 @Configuration 注解一起使用,用于标记一个方法,方法返回的实体做为Spring管理的一个Bean,通过此注解可以使用JAVA的特性配置对象。默认情况下Bean名字为方法名,也支持通过属性进行配置
属性说明


name
自定义Bean的名称,支持配置多个名称,不配置默认为方法名称
initMethod
配置实例初始化方法,在Bean实例化被调用,默认为空
destroyMethod
配置实例销毁方法,默认值为 (inferred)
即会根据返回的Bean尝试查找识别对象的销毁方法 close 或者 shutdown(限制只查找public无参方法),如返回一个 BasicDataSource
实例,会默认查找 close()
方法进行注册,如果不想Spring进行此操作,需要将此值设置为: destroyMethod=""
(此配置对 DisposableBean 回调不生效)
核心逻辑在 DisposableBeanAdapter#inferDestroyMethodsIfNecessary() 方法中
与其它注解的关联
@Bean 与XML配置方式中的 <bean> 标签不同,它使用与其它注解组合的方式来实现类型 Scope 或者懒加载的功能,具体可组合注解如下:
- @Profile
- @Scope
- @Lazy
- @DepednsOn
- @Primary
- @Order
源码阅读
Bean注解配置实例化
由于@Bean通常与@Configuration 一起使用,核心逻辑在 refresh 阶段,定位代码发现在 ConfigurationClassParser#doProcessConfigurationClass() 方法进行对 @Bean 标识方法的解析

首先 通过调用 retrieveBeanMethodMetadata() 获取Bean定义方法元数据信息,在这里如果定义的Bean方法超过1个则会通过ASM工具来获取方法定义的顺序,这个处理是因为JAVA反射处理的顺序是不确定的

扫描完Bean配置信息,需要通过 processConfigBeanDefinitions() 调用 ConfigurationClassBeanDefinitionReader#loadBeanDefinitions() 对Bean进行注册,到这就是Spring的核心,可以确保 @Bean 方法返回的Bean被容器解析并注册。对于每个 beanMethod ,会调用 loadBeanDefinitionsForBeanMethod() 对每个Bean配置进行加载,在这个方法里面会看到所有对 @Bean 属性的处理逻辑。这里面对于静态方法,会直接使用方法所有类作为bean的类,否则使用类名作为工厂bean的名,还设置了工厂方法名为当前@Bean方法的名字

这些属性都处理完后,最后会调用 registry#registerBeanDefinition() 将Bean注册到容器中
核心类调用

Bean初始化
前面说了 Bean配置的initMethod会在Bean实例化后被执行,在代码里面对着的是 refresh 阶段的 finishBeanFactoryInitialization() 调用,重点看一下这个方法的逻辑,此方法调用 DefaultListableBeanFactory#preInstantiateSingletons() 对剩下的单例进行初始化,此方法会调用 preInstantiateSingleton() 对单个 bean 进行实例化,在此方法判断bean不是懒加载就调用 instantiateSingleton() 方法进行实例化,然后就看到了熟悉的 getBean() 方法,这个方法会负责 bean 的实例化、初始化以及其依赖的注入。
在 getBean() 方法又调用了 doGetBean() 方法实际来执行创建,在此方法中,容器会从缓存中查询bean是否已经创建,不有创建就会调用 createBean() 方法来创建bean,此方法又会调用 doCreateBean() 来真正执行创建bean的操作。在 doCreateBean() 方法中,会调用 initializeBean() 方法来进行初始化操作,这里面主要关注对 invokeInitMethods() 调用,看名字知道是调用初始化的方法,此方法会判断 initMehtod 是否配置,如果配置了,则会调用 invokeCustomInitMethod() 方法通过反射来对bean初始化方法进行调用

核心类调用

Bean销毁
Bean销毁发生成 context 的close() 方法调用时

close 会调用 doClose() 方法来真正执行关闭操作,此方法会调用 destroyBeans() 对容器所有缓存的单例进行销毁操作,进行调用 DefaultSingletonBeanRegistry#destroySingletons() 方法,此方法会遍历所有要销毁的 disposableBeanNames, 倒序调用 destroySingleton() 方法,然后调用 bean#destory() 来真正的销毁bean,这里面会进入到 DisposableBeanAdapter#destory() 方法,在此方法会判断 是否存在 destoryMethod ,有则通过 invokeCustomDestroyMethod 调用bean的 destoryMethod()

DisposableBeanAdapter主要对给定bean执行一系列解构步骤,主要包含:
- 解构AwareBeanPostProcessors
- 实现了 DisposableBean 接口的bean
- bean定义指定了destory方法
核心类调用

返回 BeanFactoryPrstProcessor 类型
因为 BeanFactoryPostProcessor
类型的Bean需要在Spring很早的阶段就进行实例化来处理其它注解,需要将返回 BeanFactoryPostProcessor
类型的方法标记为 static ,通过直接调用静态方法来避免冲突(不用等到 @Configuration 类实例化)。对于静态方法是不会被AOP增强
BeanFactoryPostProcessor 用于处理其它类型的注解如:
- @Autowired
- @Value
- @PostConstruct