前言
本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本. 因为 Spring 整个体系太过于庞大, 所以只会进行关键部分的源码解析.
本篇文章主要介绍 Spring IoC 容器中 bean 的初始化阶段.
正文
我们在 Spring IoC bean 的创建一文中分析创建 bean 实例的主要流程, 此时创建出来的 bean 还是个属性未赋值的实例, 在创建完之后会进入 populateBean() 方法, 即进入属性赋值阶段. 我们简单回顾一下, 上次分析过的 doCreateBean() 方法:
- protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
- // 实例化 bean
- BeanWrapper instanceWrapper = null;
- if (mbd.isSingleton()) {
- // 如果 bean 的作用域是 singleton, 则需要移除未完成的 FactoryBean 实例的缓存
- instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
- }
- if (instanceWrapper == null) {
- // 通过构造函数反射创建 bean 的实例, 但是属性并未赋值, 见下文详解
- instanceWrapper = createBeanInstance(beanName, mbd, args);
- }
- // 获取 bean 的实例
- final Object bean = instanceWrapper.getWrappedInstance();
- // 获取 bean 的类型
- Class<?> beanType = instanceWrapper.getWrappedClass();
- if (beanType != NullBean.class) {
- mbd.resolvedTargetType = beanType;
- }
- synchronized (mbd.postProcessingLock) {
- if (!mbd.postProcessed) {
- try {
- // BeanDefinition 合并后的回调, 见下文详解
- applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
- }
- // 省略异常处理...
- mbd.postProcessed = true;
- }
- }
- // bean 的作用域是单例 && 允许循环引用 && 当前 bean 正在创建中
- boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
- // 如果允许 bean 提前曝光
- if (earlySingletonExposure) {
- // 将 beanName 和 ObjectFactory 形成的 key-value 对放入 singletonFactories 缓存中
- addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
- }
- Object exposedObject = bean;
- try {
- // 给 bean 的属性赋值
- populateBean(beanName, mbd, instanceWrapper);
- // 初始化 bean
- exposedObject = initializeBean(beanName, exposedObject, mbd);
- }
- // 省略部分代码
- }
上篇文章分析了 populateBean() 方法, 这次我们总店分析 initializeBean() 方法.
bean 的初始化
- AbstractAutoCapableBeanFactory#initializeBean
- protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
- // BeanAware 的接口回调, 见下文详解
- invokeAwareMethods(beanName, bean);
- Object wrappedBean = bean;
- if (mbd == null || !mbd.isSynthetic()) {
- // BeanPostProcessor 的 postProcessBeforeInitialization() 回调, 也就是 bean 初始化前的回调
- // 在 ApplicationContextAwareProcessor 实现的 postProcessBeforeInitialization 方法中会执行
- // ApplicationContext Aware 的接口回调.
- // InitDestoryAnnotationBeanPostProcessor 的 postProcessBeforeInitialization() 中会执行
- // 标注了 @PostConstruct 注解的方法.
- wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
- }
- try {
- // 调用 bean 的自定义初始化方法, 如 afterPropertiesSet,xml 中的 init 属性指定的方法等
- invokeInitMethods(beanName, wrappedBean, mbd);
- } catch (Throwable ex) {
- throw new BeanCreationException(
- (mbd != null ? mbd.getResourceDescription() : null),
- beanName, "Invocation of init method failed", ex);
- }
- if (mbd == null || !mbd.isSynthetic()) {
- // BeanPostProcessor 的 postProcessAfterInitialization() 回调, 也就是 bean 初始化后的回调
- wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
- }
- return wrappedBean;
- }
Aware 接口回调
- AbstractAutowireCapableBeanFactory#invokeAwareMethods
- private void invokeAwareMethods(final String beanName, final Object bean) {
- if (bean instanceof Aware) {
- // BeanNameAware 接口方法回调
- if (bean instanceof BeanNameAware) {
- ((BeanNameAware) bean).setBeanName(beanName);
- }
- // BeanClassLoaderAware 接口方法回调
- if (bean instanceof BeanClassLoaderAware) {
- ClassLoader bcl = getBeanClassLoader();
- if (bcl != null) {
- ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
- }
- }
- // BeanFactoryAware 接口方法回调
- if (bean instanceof BeanFactoryAware) {
- ((BeanFactoryAware)bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
- }
- }
- }
通过实现这些 Aware 接口的 bean 的被初始化之前, 可以取得一些相对应的资源, 比如 beanName,beanFactory 等.
bean 的初始化前回调
- AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
- public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
- Object result = existingBean;
- // 遍历所有注册的 BeanPostProcessor 实现类, 调用 postProcessBeforeInitialization 方法
- for (BeanPostProcessor processor : getBeanPostProcessors()) {
- // 在 bean 初始化方法执行前, 调用 postProcessBeforeInitialization 方法
- Object current = processor.postProcessBeforeInitialization(result, beanName);
- if (current == null) {
- return result;
- }
- result = current;
- }
- return result;
- }
上面方法主要是调用了 BeanPostProcessor 的 postProcessBeforeInitialization() 方法, 下面我们看一下 BeanPostProcessor 接口的定义:
- public interface BeanPostProcessor {
- /**
- * bean 初始化前调用, 此时 bean 已经实例化并且属性已经赋值, Aware 接口已经回调; 返回非 {@code null} 会使用返回的 bean
- */
- @Nullable
- default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
- /**
- * bean 初始化后调用, 返回非 {@code null} 会使用返回的 bean
- */
- @Nullable
- default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
- }
调用初始化方法
- AbstractAutowireCapableBeanFactory#invokeInitMethods
- protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
- // bean 是否实现 InitializingBean 接口
- boolean isInitializingBean = (bean instanceof InitializingBean);
- if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
- // 调用 afterPropertiesSet 方法
- ((InitializingBean) bean).afterPropertiesSet();
- }
- // 调用自定义的 init 方法, 例如 xml 中 init-method 属性设置的方法
- if (mbd != null && bean.getClass() != NullBean.class) {
- String initMethodName = mbd.getInitMethodName();
- if (StringUtils.hasLength(initMethodName) &&
- !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
- !mbd.isExternallyManagedInitMethod(initMethodName)) {
- invokeCustomInitMethod(beanName, bean, mbd);
- }
- }
- }
我们知道设置 bean 的初始化方法其实有三种方式 @PostConstruct,InitializingBean, 自定义初始化方法, 一个 bean 同时实现这三种方式时, 调用顺序如下:
- @PostConstruct
- InitializingBean#afterPropertiesSet()
自定义初始化方法
从上面方法可以很容易的看出 InitializingBean 接口的 afterPropertiesSet() 方法先于自定义初始化方法调用, 那么 @PostConstruct 注解标注的方法在何时调用的呢? 玄机就在上面介绍的 BeanPostProcessor 接口, InitDestroyAnnotationBeanPostProcessor 实现了该接口并重写了 postProcessBeforeInitialization() 方法调用了标注 @PostConstruct 注解的方法. 我会在后续文章分析其实现.
bean 初始化后回调
- AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
- public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
- Object result = existingBean;
- // 遍历所有注册的 BeanPostProcessor 实现类, 调用 postProcessAfterInitialization 方法
- for (BeanPostProcessor processor : getBeanPostProcessors()) {
- // 在 bean 初始化方法执行后, 调用 postProcessBeforeInitialization 方法
- Object current = processor.postProcessAfterInitialization(result, beanName);
- if (current == null) {
- return result;
- }
- result = current;
- }
- return result;
- }
总结
本篇文章主要分析了 Spring IoC bean 的初始化阶段流程, Spring 在此阶段也提供了 2 个扩展点; 分别是 bean 的初始化前和初始化后, 也就是 BeanPostProcessor 接口, 该接口十分重要其它 processor 接口都是直接或间接在此接口上扩展出来的.
最后, 我模仿 Spring 写了一个精简版, 代码会持续更新. 地址: https://github.com/leisurexi/tiny-spring .
来源: https://www.cnblogs.com/leisurexi/p/13238055.html