Spring容器系列-启动原理(下)

Spring容器系列-启动原理(下)

   从上一篇文章《Spring容器系列-启动原理(上)》中,介绍了Spring容器初始化的核心方法refresh()的整体情况。这篇文章来详细展开介绍。其中比较重要的方法会标记上***

   一、refresh中的12个方法

   1.  prepareRefresh

   主要作用:记录下容器启动时间,标记"已启动"状态

   2. obtainFreshBeanFactory ***

   主要作用:创建bean工厂,如果已经有则销毁,没有则创建。将配置文件解析成一个个 Bean 定义,注册到 BeanFactory中。

   里面实现对beanDefinition的装载(说到底核心是一个key为beanName,value为beanDefinition的 map)

1 //用于保存BeanDefinition
2 //key:beanName value:BeanDefinition
3 
7 private final Map<string,BeanDefinition>beanDefinitionMap new ConcurrentHashMap<>(256);

   下面根据代码进行说明:    

    refresh()中通过obtainFreshBeanFactory()去解析 xml 文件,并且创建 BeanFactory(获取到的是DefaultListableBeanFactory类的实例)。

    这一步主要看AbstractRefreshableApplicationContext#refreshBeanFactory()中的loadBeanDefinitions()。

 1 protected final void refreshBeanFactory() throws BeansException {
 2     //如果BeanFactory不为空,则清除BeanFactory和里面的实例
 3     if (hasBeanFactory()) {
 4         destroyBeans();
 5         closeBeanFactory();
 6     }
 7     try {
 8         //BeanFactory 实例工厂
 9         DefaultListableBeanFactory beanFactory = createBeanFactory();
10         beanFactory.setSerializationId(getId());
11         //设置是否可以循环依赖 allowCircularReferences
12         //是否允许使用相同名称重新注册不同的bean实现.
13         customizeBeanFactory(beanFactory);
14         //解析xml,并把xml中的标签封装成BeanDefinition对象
15         loadBeanDefinitions(beanFactory);
16         this.beanFactory = beanFactory;
17     }
18     catch (IOException ex) {
19         throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
20     }
21 }

   3. prepareBeanFactory ***

   主要作用:设置BeanFactory的类加载器,添加一些默认的后置处理器,添加默认的系统环境bean:环境配置、系统属性、系统环境变量

   说明:上一步 obtainFreshBeanFactory 已经把工厂建好了,但是还不能投入使用,因为工厂里什么都没有,还需要配置一些东西

   4. postProcessBeanFactory ***

   主要作用:空方法 - 模版方法,由子类重写。让子类有机会在 BeanFactory 准备就绪后对其进行进一步的处理或配置:例如添加自定义的BeanPostProcessor、注册特定类型的Bean等。

   说明:这里采用模版方法设计模式,空方法,留给子类来实现

   5. invokeBeanFactoryPostProcessors ***

   主要作用:在应用上下文中调用所有注册的 BeanFactoryPostProcessor 实现类的 postProcessBeanFactory 方法,以便对 BeanFactory 进行进一步的定制和处理

   说明:通常情况下,开发者可以通过实现 BeanFactoryPostProcessor 接口,在 postProcessBeanFactory 方法中编写自己的定制逻辑,以满足特定的需求。当调用 invokeBeanFactoryPostProcessors(beanFactory) 方法时,Spring 将自动扫描并调用所有注册的 BeanFactoryPostProcessor 实现类的 postProcessBeanFactory 方法,完成容器的预处理工作。

   6.  registerBeanPostProcessors ***

   主要作用:将自定义的配置文件中的BeanPostProcessor提取出来并注册进入beanFactory

   说明:这些后置处理器实现了 BeanPostProcessor 接口,用于在容器中的 Bean 创建、初始化、销毁等生命周期阶段进行特定操作。通过注册后置处理器,可以对容器中的 Bean 进行额外的处理,例如,AOP 切面的织入、自定义注解的处理、事件监听等。

   注册后置处理器是 Spring 框架实现灵活性和扩展性的重要手段之一,可以让开发者根据具体需求定制自己的处理逻辑,并将其无缝地集成到 Spring 容器中。

   在 Spring 中,注册后置处理器时会按照以下顺序进行排序:

   首先,将实现了 PriorityOrdered 接口的后置处理器添加到 priorityOrderedPostProcessors 集合中,并按照 Ordered 接口或 @Order 注解的顺序进行排序。

   然后,将实现了 Ordered 接口或使用 @Order 注解标注的后置处理器添加到 orderedPostProcessorNames 集合中。

   最后,将未实现以上接口或注解的后置处理器添加到 nonOrderedPostProcessorNames 集合中。

   后置处理器的类型包括:

   实现了 BeanPostProcessor 接口的后置处理器,用于在 Bean 实例化、依赖注入和初始化阶段对 Bean 进行额外的处理。

   实现了 BeanFactoryPostProcessor 接口的后置处理器,用于在 BeanFactory 标准初始化后对 BeanFactory 进行额外的处理。

   实现了 MergedBeanDefinitionPostProcessor 接口的后置处理器,用于在 Bean 定义合并前后对 Bean 进行额外的处理。

   MergedBeanDefinitionPostProcessor 接口是 BeanFactoryPostProcessor 的一个子接口,用于在 Bean 定义合并阶段进行操作,例如,可以通过这个后置处理器修改 Bean 的定义信息。
   7.  initMessageSource

   主要作用:初始化消息源,为 Spring 应用程序的国际化功能提供支持
   8.  initApplicationEventMulticaster

   主要作用:初始化事件管理类

   9.  onRefresh

   主要作用:模版方法,由子类重写。用于在容器刷新时执行特定的自定义操作:如创建Tomcat,Jetty等WEB服务器

   说明:在该方法中,可以添加任何希望在容器刷新完成后执行的逻辑,比如启动定时任务、初始化缓存、加载配置文件等等。通过重写这个方法,可以扩展容器刷新的行为,使得容器更适应特定的应用场景或业务需求。

   10.  registerListeners

   主要作用:注册监听器

   11.  finishBeanFactoryInitialization *** 

   主要作用:实例化所有剩余的(非懒加载)的单例 Bean    

   此处只分析实际起作用的DefaultListableBeanFactory#PreInstantiateSingletons() 方法。

   Spring在实例化的时候会进行判断,只有单例,并且不是LazyInit的Bean才会在初始化过程中创建,其他的比如Prototype或Lazy的只有在使用到时会通过getBean来创建。

   下面我们来分析实例化Bean的过程:

 1 @Override
 2     public void preInstantiateSingletons() throws BeansException {
 3         // 先得到BeanDefinitionMap中已经注册的所有Bean Definition名称
 4         List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
 5         // 依次遍历所有的名称
 6         for (String beanName : beanNames) {
 7             // 获取bd(Bean Definition),判断当前bd所代表的类不是Abstract的,也不是需要延迟加载的并且是单例的。
 8             RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
 9             if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
10                 // 判断当前bd代表的类是否为工厂,此方法内部会调用依次getObject方法,由于Spring自己的类(BeanPostProcessor)在前面注册时已经实例化,故可以直接获取到。而自定义的Bean并不会生成对象,会通过bd来判断是否为工厂Bean,此处先不讨论FactoryBean的情况,先来分析普通Bean
11                 if (isFactoryBean(beanName)) {
12                     Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
13                     if (bean instanceof FactoryBean) {
14                         final FactoryBean<?> factory = (FactoryBean<?>) bean;
15                         boolean isEagerInit;
16                         if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
17                             isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
18                                             ((SmartFactoryBean<?>) factory)::isEagerInit,
19                                     getAccessControlContext());
20                         }
21                         else {
22                             isEagerInit = (factory instanceof SmartFactoryBean &&
23                                     ((SmartFactoryBean<?>) factory).isEagerInit());
24                         }
25                         if (isEagerInit) {
26                             getBean(beanName);
27                         }
28                     }
29                 }
30                 else {
31                     // 这里从ioc容器中获取bean,如果不存在则创建
32                     getBean(beanName);
33                 }
34             }
35         }
36     }

    在preInstantiateSingletons方法里调用了AbstractBeanFactorygetBean方法。最终调用doGetBean()方法,下面我们看AbstractBeanFactory#doGetBean方法:

  1  protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
  2      //1.处理bean名称解析
  3      String beanName = this.transformedBeanName(name);
  4      Object sharedInstance = this.getSingleton(beanName);
  5      Object beanInstance;
  6      //从单例缓存中判断是否存在这个示例,可能来源于Spring启动的时候,也有可能来源于Spring 启动时初始化了非懒加载的对象
  7      if (sharedInstance != null && args == null) {
  8          if (this.logger.isTraceEnabled()) {
  9              if (this.isSingletonCurrentlyInCreation(beanName)) {
 10                  this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
 11              } else {
 12                  this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
 13              }
 14          }
 15          //如果单例工厂存在这个bean,则通过调用getObject方法获取bean实例
 16          beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
 17      } else {
 18          //如果当前线程存在这个实例,则抛出异常
 19          if (this.isPrototypeCurrentlyInCreation(beanName)) {
 20              throw new BeanCurrentlyInCreationException(beanName);
 21          }
 22          //2.获取当前bean工厂的父工厂,然后获取bean,此处是递归查找
 23          BeanFactory parentBeanFactory = this.getParentBeanFactory();
 24          if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
 25              String nameToLookup = this.originalBeanName(name);
 26              if (parentBeanFactory instanceof AbstractBeanFactory) {
 27                  
 28                  return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
 29              }
 30  
 31              if (args != null) {
 32                  //调用父工厂的getBean方法
 33                  return parentBeanFactory.getBean(nameToLookup, args);
 34              }
 35  
 36              if (requiredType != null) {
 37                  //根据类型获取bean
 38                  return parentBeanFactory.getBean(nameToLookup, requiredType);
 39              }
 40  
 41              return parentBeanFactory.getBean(nameToLookup);
 42          }
 43          //如果参数为检查类型,则设置名称为beanName的bean实例已经创建的标识
 44          if (!typeCheckOnly) {
 45              this.markBeanAsCreated(beanName);
 46          }
 47  
 48          StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);
 49  
 50          try {
 51              if (requiredType != null) {
 52                  beanCreation.tag("beanType", requiredType::toString);
 53              }
 54  
 55              RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
 56              this.checkMergedBeanDefinition(mbd, beanName, args);
 57              //3.获取bean的依赖属性
 58              String[] dependsOn = mbd.getDependsOn();
 59              String[] var12;
 60              if (dependsOn != null) {
 61                  var12 = dependsOn;
 62                  int var13 = dependsOn.length;
 63  
 64                  for(int var14 = 0; var14 < var13; ++var14) {
 65                      String dep = var12[var14];
 66                      //检查是否存在循环依赖
 67                      if (this.isDependent(beanName, dep)) {
 68                          throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
 69                      }
 70                      //向注册器中注册这个依赖的bean
 71                      this.registerDependentBean(dep, beanName);
 72  
 73                      try {
 74                          //获取并解决当前bean
 75                          this.getBean(dep);
 76                      } catch (NoSuchBeanDefinitionException var31) {
 77                          throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var31);
 78                      }
 79                  }
 80              }
 81              //根据 scope 处理当前bean
 82              if (mbd.isSingleton()) {
 83                  sharedInstance = this.getSingleton(beanName, () -> {
 84                      try {
 85                          return this.createBean(beanName, mbd, args);
 86                      } catch (BeansException var5) {
 87                          this.destroySingleton(beanName);
 88                          throw var5;
 89                      }
 90                  });
 91                  beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
 92              } else if (mbd.isPrototype()) {
 93                  var12 = null;
 94  
 95                  Object prototypeInstance;
 96                  try {
 97                      this.beforePrototypeCreation(beanName);
 98                      prototypeInstance = this.createBean(beanName, mbd, args);
 99                  } finally {
100                      this.afterPrototypeCreation(beanName);
101                  }
102  
103                  beanInstance = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
104              } else {
105                  String scopeName = mbd.getScope();
106                  if (!StringUtils.hasLength(scopeName)) {
107                      throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
108                  }
109                  //5.类型转换
110                  Scope scope = (Scope)this.scopes.get(scopeName);
111                  if (scope == null) {
112                      throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
113                  }
114  
115                  try {
116                      Object scopedInstance = scope.get(beanName, () -> {
117                          this.beforePrototypeCreation(beanName);
118  
119                          Object var4;
120                          try {
121                              var4 = this.createBean(beanName, mbd, args);
122                          } finally {
123                              this.afterPrototypeCreation(beanName);
124                          }
125  
126                          return var4;
127                      });
128                      beanInstance = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
129                  } catch (IllegalStateException var30) {
130                      throw new ScopeNotActiveException(beanName, scopeName, var30);
131                  }
132              }
133          } catch (BeansException var32) {
134              beanCreation.tag("exception", var32.getClass().toString());
135              beanCreation.tag("message", String.valueOf(var32.getMessage()));
136              //清楚创建bean
137              this.cleanupAfterBeanCreationFailure(beanName);
138              throw var32;
139          } finally {
140              beanCreation.end();
141          }
142      }
143  
144      return this.adaptBeanInstance(name, beanInstance, requiredType);
145  }

   说明:transformedBeanName(name)是为了获取Bean真正的名称,它会去掉name前面的'&',而getSingleton(beanName)是从父类容器singletonObjects中取的这个Bean的实例。在Spring中还有很多这样的容器,比如DefaultListableBeanFactory中的beanDefinitionMap,它就是的IOC容器真正保存Bean的地方,它是一个HashMap。类似的还有FactoryBeanRegistrySupport中的factoryBeanObjectCache等。

   DefaultSingletonBeanRegistry#getSingleton方法:

   检查缓存:通过调用getSingleton方法,这里针对单例对象会检查一级、二级、三级缓存

 1  //singletonObjects 一级缓存,存放单例成品对象
 2  private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
 3  //singletonFactories 三级缓存,存放单例工厂对象
 4  private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
 5  //earlySingletonObjects 二级缓存,存放单例工厂的产品对象
 6  private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);
 7  @Nullable
 8  protected Object getSingleton(String beanName, boolean allowEarlyReference) {
 9      Object singletonObject = this.singletonObjects.get(beanName);
10      if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
11          singletonObject = this.earlySingletonObjects.get(beanName);
12          if (singletonObject == null && allowEarlyReference) {
13              synchronized(this.singletonObjects) {
14                  singletonObject = this.singletonObjects.get(beanName);
15                  if (singletonObject == null) {
16                      singletonObject = this.earlySingletonObjects.get(beanName);
17                      if (singletonObject == null) {
18                          ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
19                          if (singletonFactory != null) {
20                              singletonObject = singletonFactory.getObject();
21                              this.earlySingletonObjects.put(beanName, singletonObject);
22                              this.singletonFactories.remove(beanName);
23                          }
24                      }
25                  }
26              }
27          }
28      }
29      return singletonObject;
30  }

    12.  finishRefresh

    主要作用:完成应用程序的上下文刷新,广播事件。其中包括:完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人。

 二、refresh()方法中比较重要的类/接口进行梳理

    1. BeanFactory 接口

    BeanFactory 是IoC容器的基础接口。用于管理Bean的工厂,它负责创建、解析和管理Bean对象。在容器启动时,会先创建 BeanFactory,然后根据配置信息加载并初始化 Bean。

    2. BeanDefinition 接口

    Spring 实例化要通过 BeanDefinition。因为 Class 是无法完成 bean 的抽象,比如 bean 的作用域,bean 的注入模型,bean 是否是懒加载等等信息,Class是无法抽象出来的,故而需要一个 BeanDefinition 类来抽象这些信息。

    BeanDefinition类图如下:

   3.  BeanDefinitionRegistry 接口

   BeanDefinitionRegistry 是 Spring 框架中的一个接口,用于注册和管理 BeanDefinition,即用于定义和描述 Spring 中的 Bean。

   BeanDefinitionRegistry 接口定义了一系列方法,包括注册、移除、检索 BeanDefinition 等。通过这些方法,可以向 Spring 容器注册各种类型的 BeanDefinition,包括单例、原型、懒加载等,并指定它们的依赖关系、作用域、初始化方法、销毁方法等。

   通过使用 BeanDefinitionRegistry,开发人员可以动态地向 Spring 容器注册新的 BeanDefinition,从而实现灵活的 IoC(控制反转)和 DI(依赖注入)功能 

   4. ConfigurableListableBeanFactory 接口

   它继承自 ListableBeanFactory 和 ConfigurableBeanFactory 接口,主要用于配置和管理 BeanFactory。

   总的来说,ConfigurableListableBeanFactory 提供了对 Spring IoC 容器的高级配置和管理功能,是 Spring 中 BeanFactory 的一个可配置的扩展接口。

   5.  DefaultListableBeanFactory 类

   它是Spring 框架中最常用的 IOC 容器实现之一,它支持 XML 配置和基于注解的配置,并提供了丰富的功能和灵活性,因此被广泛应用于各种类型的 Spring 应用中。

   它实现了 ConfigurableListableBeanFactory 和 BeanDefinitionRegistry 接口,提供了对 Bean 的定义和管理的基本功能。

   DefaultListableBeanFactory 是一个基本功能的 BeanFactory,它实现了 BeanDefinitionRegistry 接口。它的继承结构如下:

 

    DefaultListableBeanFactory 也是通过一个 HashMap 来管理 BeanDefinition 的,它比 SimpleBeanDefinitionRegistry多了一些其他的数据存储,使用上也更复杂。 

    下面是其中一部分代码:

 1 //用于保存BeanDefinition
 2 /key:beanName value:BeanDefinition
 3 private final Map<String,BeanDefinition>beanDefinitionMap new ConcurrentHashMap<>(256);
 4 
 5 //已注册的beanName,按注册的顺序有序
 6 private volatile List<string>beanDefinitionNames new ArrayList<>(256);
 7 
 8 
 9 //手动注册的singleton bean的名字,按注册的顺序有序
10 private volatile Set<string>manualsingletonNames new LinkedHashSet<>(16);

   其中 registerBeanDefinition() 方法: 

   负责管理 Spring IoC 容器中的 BeanDefinition,确保每个 Bean 都有一个唯一的名称,并处理覆盖和更新 BeanDefinition 的逻辑。

   6.  BeanFactoryPostProcessor 接口

   BeanFactoryPostProcessor 负责在 BeanFactory 加载 BeanDefinition 之后,但在 Bean 实例化之前,对 BeanFactory 进行处理。这样可以在容器启动过程中对 BeanFactory 进行修改,比如注册自定义的 BeanDefinition,修改属性值,添加属性转换器等。

   7. ApplicationContext 接口

   ApplicationContext 实际上是 BeanFactory 的一个子接口,它扩展了 BeanFactory 的功能,提供了更多的企业级特性,比如国际化、事件发布、应用上下文的层级结构等。在 Spring 中,ApplicationContext 是 Spring IoC 容器的一种,而 BeanFactory 是 IoC 容器的基础接口。

   ApplicationContext 不直接暴露 BeanFactory 的所有功能,而是通过代理模式对其进行封装和增强,使其具有更多的功能。这种封装和增强的方式让 ApplicationContext 具有了更强大的特性,比如自动装配、AOP(面向切面编程)、事件处理等,从而更适合于企业级应用的开发。

   8. PostProcessorRegistrationDelegate 类

  是 Spring 框架中用于处理后置处理器(BeanPostProcessor)的注册工具类。其主要作用是负责管理后置处理器的注册和执行顺序

 

  参考链接:https://cloud.tencent.com/developer/article/2302663

posted @ 2024-06-17 17:37  欢乐豆123  阅读(1)  评论(0编辑  收藏  举报