• Spring源码十九:Bean实例化流程二


    上一篇我们在Spring源码十八:Bean实例化流程一 中,主要讨论了Spring在实例化前的两重要准备工作,1、获取我们前面注册好的BeanDefinition,将GenericBeanDefinition封装为RootBeanDefinition如果Bean Definition只存在父容器中,还会进行合并操作,然后做了严谨的异常判断处理。2、如果bean配置了依赖的bean的名称,还会检查下配置的依赖,是否已经处于bean依赖的引用链上了,如果没有处于bean依赖引用链上,就会提前来实例化bean依赖的那些bean。最后找到实例化的入口。

     今天我们开始分析下单例bean是如何创建:咱们接着上一篇代码往下看

    getSingleton

    再进入代码中看下逻辑:

    1. public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
    2. Assert.notNull(beanName, "Bean name must not be null");
    3. synchronized (this.singletonObjects) {
    4. // 从单例缓存中获取Bean的实例
    5. Object singletonObject = this.singletonObjects.get(beanName);
    6. if (singletonObject == null) {
    7. // 如果当前bean正在销毁标志为true,则抛出异常。 默认:singletonsCurrentlyInDestruction = false
    8. if (this.singletonsCurrentlyInDestruction) {
    9. throw new BeanCreationNotAllowedException(beanName,
    10. "Singleton bean creation not allowed while singletons of this factory are in destruction " +
    11. "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
    12. }
    13. if (logger.isDebugEnabled()) {
    14. logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
    15. }
    16. // 将当前beanName放入singletonsCurrentlyInCreation列表中,标志当前bean正在被创建
    17. beforeSingletonCreation(beanName);
    18. boolean newSingleton = false;
    19. boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
    20. if (recordSuppressedExceptions) {
    21. this.suppressedExceptions = new LinkedHashSet<>();
    22. }
    23. try {
    24. // !!!! 调用简单工厂方法来实例化bean !!!! //
    25. singletonObject = singletonFactory.getObject();
    26. // 标志当前bean是第一次过来,默认是false
    27. newSingleton = true;
    28. }
    29. catch (IllegalStateException ex) {
    30. // Has the singleton object implicitly appeared in the meantime ->
    31. // if yes, proceed with it since the exception indicates that state.
    32. // 再努力一次,如果通过简单工厂创建失败: 尝试从单例缓存中,获取beanName对应的单例bean
    33. singletonObject = this.singletonObjects.get(beanName);
    34. // 缓存里还是没有,此时再将异常抛出
    35. if (singletonObject == null) {
    36. throw ex;
    37. }
    38. }
    39. catch (BeanCreationException ex) {
    40. if (recordSuppressedExceptions) {
    41. for (Exception suppressedException : this.suppressedExceptions) {
    42. ex.addRelatedCause(suppressedException);
    43. }
    44. }
    45. throw ex;
    46. }
    47. finally {
    48. if (recordSuppressedExceptions) {
    49. this.suppressedExceptions = null;
    50. }
    51. // 从singletonsCurrentlyInCreation列表中移出,标志当前beanName对应的bean已经创建完成了。
    52. afterSingletonCreation(beanName);
    53. }
    54. if (newSingleton) {
    55. // 看到了嘛,看到了嘛,第一次标志在这里用的,单例缓存入的地方也再这里,哈哈 我们找到啦
    56. addSingleton(beanName, singletonObject);
    57. }
    58. }
    59. return singletonObject;
    60. }
    61. }

    这段代码是Spring框架中用于创建和获取单例bean实例的一部分。以下是对这段代码的分析:

    1. 使用lambda表达式:代码中使用了Java 8的lambda表达式来创建一个匿名的 ObjectFactory 实例。这个 ObjectFactory 会在需要时调用其 getObject() 方法来创建bean。

    2. getSingleton()方法getSingleton(beanName, singletonFactory) 方法被调用来获取名为 beanName 的单例bean。如果这个bean尚未被创建,singletonFactory.getObject() 将被调用以创建它。

    3. createBean()方法:在lambda表达式中,如果bean不存在,将调用 createBean(beanName, mbd, args) 方法来创建bean。这个方法负责完整的bean创建过程,包括依赖注入、初始化等步骤。

    4. 异常处理:如果在创建bean的过程中抛出了 BeansException(例如,由于循环依赖或其他bean创建问题),代码将执行以下操作:

      • 调用 destroySingleton(beanName) 来从单例缓存中移除部分创建的bean实例。这是必要的,因为创建过程中可能会因为解决循环依赖而提前将bean放入缓存。
      • 抛出原始的 BeansException,以通知调用者bean创建失败。
    5. 获取bean实例:如果bean成功创建,sharedInstance 将包含新创建的bean实例。然后,调用 getObjectForBeanInstance(sharedInstance, name, beanName, mbd) 方法来获取bean实例对象。这个方法可能执行额外的处理,比如应用 FactoryBean 的逻辑或处理bean的后置处理(post-processing)。

    6. 单例缓存:整个过程中,Spring使用 singletonObjects 作为缓存来存储已经创建的单例bean。这样,后续请求相同bean时可以直接从缓存中获取,而不需要重新创建。

    这段代码体现了Spring框架中创建单例bean的复杂性,包括异常安全、延迟初始化和对循环依赖的处理。通过使用 ObjectFactory 和lambda表达式,Spring能够以一种灵活且高效的方式来管理bean的生命周期。

    createBean

    上面我已经找到真正创建bean的地方,也看到Spring是通过简单工厂创建实例的也验证了人命常说的bean工厂、工厂模式。同时也看到单例bean首次创建,会放入单例缓存池中。但是整个方法有个内部类,当然这里是Java8的函数式接口实现的,咱们跳出来看下这个默认方法是做了什么逻辑处理。通过这个方法来

    看到上图标注的地方createBean见名知意,应该是这个方法包含了实例化的核心逻辑,咱们进入方法内部一探究竟之前简单分析一下:在这个内部类里首先会通过createBean来实例化一个bena,如果实例化的过程中出现了异常,就会调用方法destroy Singleton方法,来清除单利bean相关的一系列缓存信息。

    1. /**
    2. * Central method of this class: creates a bean instance, 创建bean实例对象
    3. * populates the bean instance, applies post-processors, etc. 填充bean实例、应用后置处理器
    4. * @see #doCreateBean
    5. */
    6. @Override
    7. protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    8. throws BeanCreationException {
    9. if (logger.isTraceEnabled()) {
    10. logger.trace("Creating instance of bean '" + beanName + "'");
    11. }
    12. RootBeanDefinition mbdToUse = mbd;
    13. // Make sure bean class is actually resolved at this point, and
    14. // clone the bean definition in case of a dynamically resolved Class
    15. // which cannot be stored in the shared merged bean definition. 判断需要创建的bean是否可以实例化、是否可以通过当前类加载器加载
    16. Class resolvedClass = resolveBeanClass(mbd, beanName);
    17. if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    18. mbdToUse = new RootBeanDefinition(mbd);
    19. mbdToUse.setBeanClass(resolvedClass);
    20. }
    21. // Prepare method overrides. 准备bean中的方法覆盖
    22. try {
    23. mbdToUse.prepareMethodOverrides();
    24. }
    25. catch (BeanDefinitionValidationException ex) {
    26. throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
    27. beanName, "Validation of method overrides failed", ex);
    28. }
    29. try {
    30. // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. 给BeanPostProcessors一个返回代理而不是目标bean实例的机会。
    31. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 如果bean配置类后置处理器PostProcessor,则这里返回一个proxy代理对象
    32. if (bean != null) {
    33. return bean;
    34. }
    35. }
    36. catch (Throwable ex) {
    37. throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
    38. "BeanPostProcessor before instantiation of bean failed", ex);
    39. }
    40. try {
    41. Object beanInstance = doCreateBean(beanName, mbdToUse, args); // bean实例对象创建方法
    42. if (logger.isTraceEnabled()) {
    43. logger.trace("Finished creating instance of bean '" + beanName + "'");
    44. }
    45. return beanInstance;
    46. }
    47. catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
    48. // A previously detected exception with proper bean creation context already,
    49. // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
    50. throw ex;
    51. }
    52. catch (Throwable ex) {
    53. throw new BeanCreationException(
    54. mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    55. }
    56. }

     

    总结

  • 相关阅读:
    Python:实现mobius function莫比乌斯函数算法(附完整源码)
    Android -- 每日一问:你在Android开发中遇到的技术难题是什么,你是怎么解决的?
    【python运维脚本实践】python实践篇之使用Python处理有序文件数据的多线程实例
    Java 中奖
    机器人中的数值优化(十二)——带约束优化问题简介、LP线性规划
    Brachistochrone:使用变分法找到最快下降曲线
    Java输入任意字符串,找出回文信息
    Python处理Excel表格文件(读取和写入,pandas版)
    Oracle特殊恢复:异常掉电导致的ORA-600 [kfrValAcd30]故障处理
    Postman 如何获取请求结果并设置到请求头中
  • 原文地址:https://blog.csdn.net/weixin_40735063/article/details/140268232