Spring Bean创建流程分析讲解

作者:程序员小潘 时间:2022-04-20 22:53:07 

1. 前言

Spring提供了xml、注解、JavaConfig多种方式来配置bean,不论何种方式,Spring最终都会将bean封装成BeanDefinition对象,Spring创建bean的依据也是通过BeanDefinition来完成的。

当我们调用getBean()方法获取bean实例时,不管是单例bean还是原型bean,首次调用时容器内都不存在可用的bean实例,这时就不得不去创建bean了,我们分析下Spring创建bean的过程。

2. Bean创建概览

Spring Bean创建流程分析讲解

Spring Bean的创建过程是非常复杂的,但是整体流程又是清晰的。创建bean的入口函数在AbstractAutowireCapableBeanFactory#createBean(),Spring首先会触发一个扩展点InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(),如果扩展点返回了可用的bean,这里会进行短路操作,Spring将不再去实例化目标bean,这样做的好处是,扩展点可以在这里返回一个代理对象去避免目标bean被实例化。

如果扩展点没有返回可用的bean对象,Spring会自己去实例化bean,实例化bean的方式有三种,取决于BeanDefinition的配置。Bean实例化完了之后,Spring会通过扩展点的方式来收集Bean的注解属性和方法,比如:@Autowired、@Value、init-method等等,信息收集完毕会通过populateBean()方法对bean进行属性填充,其实就是注入依赖。属性填充完毕,紧接着会对bean进行初始化,触发bean实现的各种Aware接口,生命周期方法,以及BeanPostProcessor扩展点。

以上执行完毕后,此时的bean就已经是一个可用的bean了,可以直接返回了。但是,bean可能还会有destroy-method方法,需要在bean销毁时被调用,所以最后还需要把这一类bean暂存到Map容器中,以便销毁时触发。

3. InstantiationAwareBeanPostProcessor

根据beanName创建bean,首先需要知道bean对应的class。解析class有2种方式,如果mbd存在BeanClass就直接用,否则根据BeanClassName加载class。

/**
* 解析BeanClass
* 1.存在BeanClass
* 2.根据BeanClassName加载Class
*/
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);

紧接着准备MethodOverrides,因为Spring支持lookup-methodreplace-method功能,针对这两类方法Spring统一保存在MethodOverrides里面,如果bean存在MethodOverrides,则需要创建代理对象来增强。

这里的准备阶段,其实是解析MethodOverride是否存在重载方法,如果不存在重载方法,会将overloaded设为false,增强调用时就不用再根据参数类型去判断该调用哪个重载方法了。

/**
* 准备重写方法,解析是否有重载方法
* 1.lookup-method
* 2.replace-method
* 如果存在MethodOverride,则创建代理对象
*/
try {
   mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException ex) {
   throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
           beanName, "Validation of method overrides failed", ex);
}

然后Spring触发扩展点InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(),如果扩展点返回了可用的bean,Spring将不再对目标bean进行实例化。这里你可以返回一个代理对象,然后自己决定什么时候实例化目标bean。

try {
   /**
    * 触发InstantiationAwareBeanPostProcessor扩展
    * 允许它返回代理对象,来避免目标Bean实例化
    * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(java.lang.Class, java.lang.String)
    */
   Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
   if (bean != null) {
       /**
        * 如果InstantiationAwareBeanPostProcessor返回了代理对象,则不再实例化目标Bean,短路操作
        */
       return bean;
   }
} catch (Throwable ex) {
   throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
           "BeanPostProcessor before instantiation of bean failed", ex);
}

resolveBeforeInstantiation()其实就是从容器中取出所有的InstantiationAwareBeanPostProcessor实现类,然后依次调用postProcessBeforeInstantiation()方法。如果扩展点返回了bean对象,紧接着会马上触发postProcessAfterInitialization()方法,跳过目标bean的实例化。

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   Object bean = null;
   if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
       if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
           Class<?> targetType = determineTargetType(beanName, mbd);
           if (targetType != null) {
               // 应用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation处理器
               bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
               if (bean != null) {
                   /**
                    * 如果扩展点返回了可用bean,不再实例化目标bean,紧接着应用after处理器
                    * 应用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation处理器
                    */
                   bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
               }
           }
       }
       mbd.beforeInstantiationResolved = (bean != null);
   }
   return bean;
}

4. createBeanInstance

如果InstantiationAwareBeanPostProcessor扩展点没有返回可用bean,Spring会对目标bean实例化,紧接着调用doCreateBean()方法。

实例化bean的方法是AbstractAutowireCapableBeanFactory#createBeanInstance(),实例化bean的方式有三种:

  • 如果RootBeanDefinition提供了instanceSupplier方法,则直接调用instanceSupplier方法来生成bean对象,避免反射实例化bean的性能消耗。

  • 如果是@Bean方法声明的bean,Spring会从容器中找到factoryBeanName对应的工厂bean,然后反射调用factoryMethodName来创建bean。

  • 通过构造函数实例化。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
   Class<?> beanClass = resolveBeanClass(mbd, beanName);
   if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
       throw new BeanCreationException(mbd.getResourceDescription(), beanName,
               "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
   }
   Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
   if (instanceSupplier != null) {
       return obtainFromSupplier(instanceSupplier, beanName);
   }
   /**
    * 如果是@Bean方法声明的bean,则调用工厂方法来生成bean
    * 从容器中取出factoryBean,反射调用@Bean方法生成bean
    */
   if (mbd.getFactoryMethodName() != null) {
       return instantiateUsingFactoryMethod(beanName, mbd, args);
   }
   boolean resolved = false;
   boolean autowireNecessary = false;
   if (args == null) {
       synchronized (mbd.constructorArgumentLock) {
           /*
               一个类有多个构造函数,每个构造函数都有不同的参数,
               所以需要根据参数锁定构造函数并进行初始化
            */
           if (mbd.resolvedConstructorOrFactoryMethod != null) {
               resolved = true;
               autowireNecessary = mbd.constructorArgumentsResolved;
           }
       }
   }
   // 如果已经解析过则使用解析好的构造函数 , 不需要再次锁定
   if (resolved) {
       if (autowireNecessary) {
           // 构造函数注入
           return autowireConstructor(beanName, mbd, null, null);
       } else {
           // 无参构造函数
           return instantiateBean(beanName, mbd);
       }
   }
   // 根据参数解析构造函数
   Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
   if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
           mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
       //构造函数自动注入
       return autowireConstructor(beanName, mbd, ctors, args);
   }
   // Preferred constructors for default construction?
   ctors = mbd.getPreferredConstructors();
   if (ctors != null) {
       return autowireConstructor(beanName, mbd, ctors, null);
   }
   // 无需特殊处理:只需使用无参构造函数。
   return instantiateBean(beanName, mbd);
}

5. MergedBeanDefinitionPostProcessor

通过**createBeanInstance()**方法实例化的bean只是一个不可用的bean对象,因为这个时候bean的属性还没有填充,依赖也没有注入,初始化方法也没有被调用,后置处理器也还没有执行。

紧接着,Spring会对bean做一些信息收集,收集的信息包括@Autowired、@Value、@Resource等注解,init-method、destroy-method方法等,将这些信息封装成Member对象,存放到RootBeanDefinition的externallyManagedConfigMembers属性里。

收集工作是通过扩展点MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition()进行的,Spring内置了多个实现类来收集信息,通过名字基本就能看出来它们要收集哪些信息。

  • CommonAnnotationBeanPostProcessor

  • AutowiredAnnotationBeanPostProcessor

  • InitDestroyAnnotationBeanPostProcessor

synchronized (mbd.postProcessingLock) {
   if (!mbd.postProcessed) {
       try {
           /**
            * 触发扩展点
            * 解析bean的 @Autowired @Value @Resource注解
            * init destory-method方法
            * 存放到BD的externallyManagedConfigMembers中
            * @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition(org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Class, java.lang.String)
            */
           applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
       } catch (Throwable ex) {
           throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                   "Post-processing of merged bean definition failed", ex);
       }
       mbd.postProcessed = true;
   }
}

6. SmartInstantiationAwareBeanPostProcessor

Bean的信息收集完毕,还有一个问题需要解决。Spring是允许Bean之间存在循环依赖的,比如BeanA有一个属性BeanB,BeanB也有一个属性BeanA,两者互相依赖对方。Spring创建BeanA时发现它依赖BeanB,就会去创建BeanB,创建BeanB时又发现它依赖BeanA,此时又会去创建BeanA,循环依赖就此产生。为了打破这个死循环,Spring的解决方案是,不等BeanA完全创建好,就提前暴露到缓存中,这样在创建BeanB时就可以直接依赖这个半成品BeanA了,循环就此打破。

如果允许提前暴露 bean,那么Spring还会触发一个扩展点SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference()来获得提前暴露 bean的引用,默认是直接原样返回bean。

/**
* 这个时候bean还没初始化,是否要提前暴露 Bean?以便循环依赖
* 条件:单例 & 允许循环依赖 & bean正在创建中
*/
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
       isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
   if (logger.isTraceEnabled()) {
       logger.trace("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
   }
   /**
    * 加入到singletonFactories
    */
   addSingletonFactory(beanName,
           /**
            * 获取提前暴露 Bean的引用,默认原样返回bean
            * 触发扩展点,AOP在这里将advice织入bean中
            * @see SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference(java.lang.Object, java.lang.String)
            */
           () -> getEarlyBeanReference(beanName, mbd, bean));
}

7. populateBean

bean实例生成了,bean的信息也收集完毕了,接下来就是对bean进行属性填充了,方法是populateBean()

Spring此时又会触发一个扩展点InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation(),返回值代表是否要继续填充bean,默认返回true。

/**
* 触发扩展点,返回值代表是否要继续填充bean
* @see InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation(java.lang.Object, java.lang.String)
*/
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
   for (BeanPostProcessor bp : getBeanPostProcessors()) {
       if (bp instanceof InstantiationAwareBeanPostProcessor) {
           InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
           if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
               continueWithPropertyPopulation = false;
               break;
           }
       }
   }
}
if (!continueWithPropertyPopulation) {
   return;
}

如果需要继续填充bean,则通过InstantiationAwareBeanPostProcessor#postProcessProperties()扩展点来完成的bean的填充。执行完这一步,Bean的属性会完成填充,依赖也会被注入。

/**
* 触发扩展点,这里会注入@Autowired、@Resource、@Value等属性
* @see InstantiationAwareBeanPostProcessor#postProcessProperties(org.springframework.beans.PropertyValues, java.lang.Object, java.lang.String) InstantiationAwareBeanPostProcessor#postProcessProperties(org.springframework.beans.PropertyValues, java.lang.Object, java.lang.String)
* @see InstantiationAwareBeanPostProcessor#postProcessPropertyValues(org.springframework.beans.PropertyValues, java.beans.PropertyDescriptor[], java.lang.Object, java.lang.String)
*/
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
   if (pvs == null) {
       pvs = mbd.getPropertyValues();
   }
   for (BeanPostProcessor bp : getBeanPostProcessors()) {
       if (bp instanceof InstantiationAwareBeanPostProcessor) {
           InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
           PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
           if (pvsToUse == null) {
               if (filteredPds == null) {
                   filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
               }
               // 对所有需要依赖检查的属性进行后处理
               pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
               if (pvsToUse == null) {
                   return;
               }
           }
           pvs = pvsToUse;
       }
   }
}

8. initializeBean

属性填充,依赖注入完,接下来就是bean的初始化。

首先会调用invokeAwareMethods()方法来触发Bean实现的各类Aware接口。

private void invokeAwareMethods(final String beanName, final Object bean) {
   if (bean instanceof Aware) {
       if (bean instanceof BeanNameAware) {
           ((BeanNameAware) bean).setBeanName(beanName);
       }
       if (bean instanceof BeanClassLoaderAware) {
           ClassLoader bcl = getBeanClassLoader();
           if (bcl != null) {
               ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
           }
       }
       if (bean instanceof BeanFactoryAware) {
           ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
       }
   }
}

然后触发扩展点BeanPostProcessor#postProcessBeforeInitialization()

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
   /**
    * 触发扩展点
    * @see BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
    */
   wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

如果bean实现了InitializingBean接口,Spring紧接着会触发InitializingBean#afterPropertiesSet()扩展点,再执行init-method。

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
           throws Throwable {
       //判断该bean 如果实现了InitializingBean接口,则调用bean的afterPropertiesSet方法
       boolean isInitializingBean = (bean instanceof InitializingBean);
       // 执行afterPropertiesSet方法
       if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
           if (logger.isTraceEnabled()) {
               logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
           }
           if (System.getSecurityManager() != null) {
               try {
                   AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                       ((InitializingBean) bean).afterPropertiesSet();
                       return null;
                   }, getAccessControlContext());
               } catch (PrivilegedActionException pae) {
                   throw pae.getException();
               }
           } else {
               ((InitializingBean) bean).afterPropertiesSet();
           }
       }
       // 执行initMethod方法
       if (mbd != null && bean.getClass() != NullBean.class) {
           String initMethodName = mbd.getInitMethodName();
           //判断是否指定了init-method方法,如果指定了init-method方法,则再调用制定的init-method
           if (StringUtils.hasLength(initMethodName) &&
                   !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                   !mbd.isExternallyManagedInitMethod(initMethodName)) {
               //调用init-method方法中指定的方法, 是通过反射实现
               invokeCustomInitMethod(beanName, bean, mbd);
           }
       }
   }

initMethods执行完毕,接着触发BeanPostProcessor#postProcessAfterInitialization()扩展点对bean做最后的扩展。

if (mbd == null || !mbd.isSynthetic()) {
   /**
    * 触发扩展点
    * @see BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
    */
   wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;

9. registerDisposableBean

到此为止,bean就创建完毕了,是一个完整的可用的bean了。最后一步,是判断bean是否存在destroy-method,如果有还需要把bean注册到Map容器中,以便bean销毁时调用。

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
   AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
   if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
       if (mbd.isSingleton()) {
           registerDisposableBean(beanName,
                   new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
       } else {
           Scope scope = this.scopes.get(mbd.getScope());
           if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
           }
           scope.registerDestructionCallback(beanName,
                   new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
       }
   }
}

来源:https://javap.blog.csdn.net/article/details/128499937

标签:Spring,Bean,创建
0
投稿

猜你喜欢

  • Java静态代理与动态代理案例详解

    2021-12-09 19:55:44
  • Android so的热升级尝试

    2023-08-07 22:41:59
  • Java集合类的组织结构和继承、实现关系详解

    2023-03-09 10:48:50
  • C#面向对象设计的七大原则

    2021-10-21 04:15:49
  • Winform窗体中打开PDF文件的三种方式

    2023-05-15 19:46:52
  • android 使用kotlin 实现点击更换全局语言(中日英切换)

    2023-11-18 03:08:50
  • 如何利用反射构建元数据查看器

    2021-05-27 00:11:05
  • Java微信支付-微信红包

    2023-11-01 01:07:05
  • C# Winform下载文件并显示进度条的实现代码

    2022-11-26 04:39:02
  • Java ThreadPoolExecutor线程池有关介绍

    2022-11-21 02:03:20
  • android实现简单仪表盘效果

    2023-05-31 22:37:39
  • SpringCloud实战之Feign声明式服务调用

    2022-07-02 08:25:30
  • SpringBoot 整合jdbc和mybatis的方法

    2023-08-10 12:51:09
  • c++换行符知识点总结

    2022-10-05 13:53:01
  • c# winform时钟的实现代码

    2023-04-05 07:40:53
  • 浅谈Java中Collections.sort对List排序的两种方法

    2021-11-18 11:20:22
  • Android自定义View仿探探卡片滑动效果

    2023-03-18 14:54:16
  • Android实现H5与Native交互的两种方式

    2023-01-01 05:35:42
  • android开机自动启动app的解决方法

    2021-08-23 18:56:51
  • java中实现分页的几种常见方式总结

    2021-12-24 13:32:49
  • asp之家 软件编程 m.aspxhome.com