首页 > 编程语言 >Spring IOC源码(八):IOC容器之 完成容器的初始化

Spring IOC源码(八):IOC容器之 完成容器的初始化

时间:2022-12-25 19:47:20浏览次数:50  
标签:容器 RootBeanDefinition mbd beanName 缓存 bean 源码 IOC previous

1、源码解析

1.1、整体逻辑剖析

  finishBeanFactoryInitialization(beanFactory);初始化非懒加载的单实例,完成IOC容器的初始化操作。
 1 // 完成IOC容器的初始化操作
 2 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
 3    // 为上下文初始化类型转换器
 4    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
 5          beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
 6       beanFactory.setConversionService(
 7             beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
 8    }
 9    // 如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器,主要用于注解属性值的解析
10    if (!beanFactory.hasEmbeddedValueResolver()) {
11       beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
12    }
13    // 尽早初始化loadTimeWeaverAware bean,以便尽早注册它们的转换器,用于AOP
14    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
15    for (String weaverAwareName : weaverAwareNames) {
16       getBean(weaverAwareName);
17    }
18    // 禁止使用临时类加载器进行类型匹配
19    beanFactory.setTempClassLoader(null);
20    // 冻结所有的bean定义,说明注册的bean定义将不被修改或任何进一步的处理(在Bean实例化阶段)
21    beanFactory.freezeConfiguration();
22    // 实例化剩下的单例对象
23    beanFactory.preInstantiateSingletons();
24 }

  完成IOC容器的核心方法在beanFactory.preInstantiateSingletons();这一步骤中。preInstantiateSingletons方法是在ConfigurableListableBeanFactory接口中定义,由其子类DefaultListableBeanFactory实现。

 1 // FactoryBean创建对象的实例名前缀
 2 String FACTORY_BEAN_PREFIX = "&";
 3 
 4 // 实例化IOC容器的单例对象
 5 public void preInstantiateSingletons() throws BeansException {
 6    // 创建一个beanDefinitionNames的一个副本
 7    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
 8    
 9    // 触发所有非延迟加载单例bean的初始化,遍历集合的对象
10    for (String beanName : beanNames) {
11       // 合并父级BeanDefinition
12       RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
13       // 条件判断,非抽象,单例,非懒加载
14       if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
15          // 判断是否实现了FactoryBean接口
16          if (isFactoryBean(beanName)) {
17             // 根据&+beanName来获取具体的对象
18             Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
19             // 类型转换处理
20             if (bean instanceof FactoryBean) {
21                FactoryBean<?> factory = (FactoryBean<?>) bean;
22                // 判断这个FactoryBean是否希望立即初始化
23                boolean isEagerInit;
24                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
25                   isEagerInit = AccessController.doPrivileged(
26                         (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
27                         getAccessControlContext());
28                }
29                else {
30                   isEagerInit = (factory instanceof SmartFactoryBean &&
31                         ((SmartFactoryBean<?>) factory).isEagerInit());
32                }
33                //  如果希望急切的初始化,则通过beanName获取bean实例
34                if (isEagerInit) {
35                   getBean(beanName);
36                }
37             }
38          }
39          // 如果beanName对应的bean不是FactoryBean,只是普通的bean,通过beanName获取bean实例
40          else {
41             getBean(beanName);
42          }
43       }
44    }
45 
46    // 遍历beanNames,触发所有SmartInitializingSingleton的后初始化回调
47    for (String beanName : beanNames) {
48       // 获取beanName对应的bean实例
49       Object singletonInstance = getSingleton(beanName);
50       // 判断singletonInstance是否实现了SmartInitializingSingleton接口
51       if (singletonInstance instanceof SmartInitializingSingleton) {
52          // 类型转换
53          SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
54          // 触发SmartInitializingSingleton实现类的afterSingletonsInstantiated方法
55          if (System.getSecurityManager() != null) {
56             AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
57                smartSingleton.afterSingletonsInstantiated();
58                return null;
59             }, getAccessControlContext());
60          }
61          else {
62             smartSingleton.afterSingletonsInstantiated();
63          }
64       }
65    }
66 }

1、获取所有的beanDefinition的名称集合beanNames ;

2、遍历beanNames集合,触发所有非延迟加载单例bean的初始化   ·根据beanName获取beanName合并后的本地RootBeanDefinition;   ·若bean定义信息非抽象、为单例、并且为非懒加载的。   ·判断bean对象是否实现了FactoryBean接口。若实现了FactoyBean接口,将&+beanName作为新的bean名称,通过getBean获取FactoryBean类型的(&+beanName)对象实例,若FactoryBean是否需要及时初始化标识为true,则通过getBean(beanName)获取beanName的bean实例;   ·若没有实现FactoryBean接口,只是普通的Bean, 通过getBean获取beanName的bean实例。   ·再次遍历beanNames集合,初始化bean实例的回调处理   ·通过beanName在三级缓存中获取对应的单例bean实例;   ·单例bean实例实现了SmartInitializingSingleton接口,执行bean实例化后的回调处理。

1.2、细节逻辑剖析

1、合并本地bean定义信息 - getMergedLocalBeanDefinition

  getMergedLocalBeanDefinition是在抽象类AbstractBeanDefinition中实现的。
  1 // 已经合并的bean定义信息的缓存
  2 private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
  3 
  4 // 获取beanName合并后的本地RootBeanDefinition
  5 protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
  6    // 按照beanName从缓存mergedBeanDefinitions中获取beanName对应的RootBeanDefinition对象
  7    RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
  8    // 如果mbd不为null 且 不需要重新合并定义
  9    if (mbd != null && !mbd.stale) {
 10       // 返回缓存中beanName对应的RootBeanDefinition
 11       return mbd;
 12    }
 13    // 获取beanName对应的合并Bean定义,如果beanName对应的BeanDefinition是子BeanDefinition,
 14    // 则通过与父级合并返回RootBeanDefinition
 15    return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
 16 }
 17 
 18 // 如果给定的beanDefinition是子beanDefinition,合并父级bean定义,返回RootBeanDefinition对象
 19 protected RootBeanDefinition getMergedBeanDefinition(
 20       String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
 21       throws BeanDefinitionStoreException {
 22 
 23    // 同步:使用从bean名称映射到合并的RootBeanDefinition集合进行加锁
 24    synchronized (this.mergedBeanDefinitions) {
 25       // 用于存储bd的MergedBeanDefinition
 26       RootBeanDefinition mbd = null;
 27       //该变量表示从bean名称映射到合并的RootBeanDefinition集合中取到的mbd且该mbd需要重新合并定义
 28       RootBeanDefinition previous = null;
 29       // 立即检查完全锁定,以强制执行相同的合并实例,如果没有包含bean定义
 30       if (containingBd == null) {
 31          // 从bean名称映射到合并的RootBeanDefinition集合中获取beanName对应的BeanDefinition作为mbd
 32          mbd = this.mergedBeanDefinitions.get(beanName);
 33       }
 34       // 如果mbd为null或者mdb需要重新合并定义
 35       if (mbd == null || mbd.stale) {
 36          // 将mdn作为previous
 37          previous = mbd;
 38          // 如果获取不到原始BeanDefinition的父Bean名
 39          if (bd.getParentName() == null) {
 40             // 使用给定的RootBeanDefinition的副本,如果原始BeanDefinition是RootBeanDefinition对象
 41             if (bd instanceof RootBeanDefinition) {
 42                // 深拷贝一份bd的Bean定义赋值给mdb
 43                mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
 44             } else {
 45                // 创建一个新的RootBeanDefinition作为bd的深层副本并赋值给mbd
 46                mbd = new RootBeanDefinition(bd);
 47             }
 48          }
 49          else {
 50             // 子bean定义:需要与父bean合并,定义一个父级BeanDefinition变量
 51             BeanDefinition pbd;
 52             try {
 53                // 获取beanDefinition父级Bean对应的实际beanName (剔除'&'前缀、解析别名)
 54                String parentBeanName = transformedBeanName(bd.getParentName());
 55                // 如果当前bean名不等于父级bean名
 56                if (!beanName.equals(parentBeanName)) {
 57                   // 获取parentBeanName的"合并的"BeanDefinition赋值给pdb
 58                   pbd = getMergedBeanDefinition(parentBeanName);
 59                }
 60                // 如果父定义的beanName与bd的beanName相同,则拿到父BeanFactory,
 61                // 只有在存在父BeanFactory的情况下,才允许父定义beanName与自己相同,否则就是将自己设置为父定义
 62                else {
 63                   BeanFactory parent = getParentBeanFactory();
 64                   // 如果父BeanFactory是ConfigurableBeanFactory,则通过父BeanFactory获取父定义的MergedBeanDefinition
 65                   if (parent instanceof ConfigurableBeanFactory) {
 66                      // 使用父工厂获取parentBeanName对应的合并BeanDefinition赋值给pdb
 67                      pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
 68                   }
 69                   else {
 70                      // 如果父工厂不是ConfigurableBeanFactory,抛出没有此类bean定义异常,父级bean名为parentBeanName等于名为beanName的bean名;
 71                      // 没有AbstractBeanFactory父级无法解决
 72                      throw new NoSuchBeanDefinitionException(parentBeanName,
 73                            "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
 74                            "': cannot be resolved without a ConfigurableBeanFactory parent");
 75                   }
 76                }
 77             }
 78             catch (NoSuchBeanDefinitionException ex) {
 79                throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
 80                      "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
 81             }
 82             // 使用父定义pbd构建一个新的RootBeanDefinition对象
 83             mbd = new RootBeanDefinition(pbd);
 84             // 使用原始bd定义信息覆盖父级的定义信息
 85             mbd.overrideFrom(bd);
 86          }
 87          // 如果mbd之前没有配置过作用域,设置单例作用域
 88          if (!StringUtils.hasLength(mbd.getScope())) {
 89             mbd.setScope(SCOPE_SINGLETON);
 90          }
 91          // 非单例bean中包含的bean本身不能是单例。
 92          // 因为这可能是外部bean的父子合并的结果,在这种情况下,原始内部bean定义将不会继承合并的外部bean的单例状态。
 93          // 如果有传包含bean定义且包含bean定义不是单例但mbd又是单例
 94          if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
 95             // 让mbd的作用域设置为跟containingBd的作用域一样
 96             mbd.setScope(containingBd.getScope());
 97          }
 98          // 暂时缓存合并的bean定义(稍后可能仍会重新合并以获取元数据更正),如果没有传入包含bean定义 且 当前工厂是同意缓存bean元数据
 99          if (containingBd == null && isCacheBeanMetadata()) {
100             //将beanName和mbd的关系添加到 从bean名称映射到合并的RootBeanDefinition集合中
101             this.mergedBeanDefinitions.put(beanName, mbd);
102          }
103       }
104       // 如果存在上一个从bean名称映射到合并的RootBeanDefinition集合中取出的mbd
105       // 且该mbd需要重新合并定义
106       if (previous != null) {
107          // 拿previous来对mdb进行重新合并定义
108          copyRelevantMergedBeanDefinitionCaches(previous, mbd);
109       }
110       // 返回MergedBeanDefinition
111       return mbd;
112    }
113 }
114 
115 /**
116  * 复制相关的合并bean定义缓存,或者说拿previous来对mdb进行重新合并定义
117  * @param previous
118  * @param mbd
119  */
120 private void copyRelevantMergedBeanDefinitionCaches(RootBeanDefinition previous, RootBeanDefinition mbd) {
121    // 如果其中一个为null,返回false,mbd和previous的当前Bean类名称相同,工厂bean名称相同,工厂方法名相同
122    if (ObjectUtils.nullSafeEquals(mbd.getBeanClassName(), previous.getBeanClassName()) &&
123          ObjectUtils.nullSafeEquals(mbd.getFactoryBeanName(), previous.getFactoryBeanName()) &&
124          ObjectUtils.nullSafeEquals(mbd.getFactoryMethodName(), previous.getFactoryMethodName())) {
125       // 获取mbd的目标类型
126       ResolvableType targetType = mbd.targetType;
127       // 获取previous的目标类型
128       ResolvableType previousTargetType = previous.targetType;
129       // 如果mdb的目标类型为null或者mdb的目标类型与previous的目标类型相同
130       if (targetType == null || targetType.equals(previousTargetType)) {
131          // 设置mbd的目标类型为previous的目标类型
132          mbd.targetType = previousTargetType;
133          // 设置mbd的工厂bean标记为previous的工厂bean标记
134          mbd.isFactoryBean = previous.isFactoryBean;
135          // 设置mbd的用于缓存给定bean定义的确定的Class为previous的用于缓存给定bean定义的确定的Class
136          mbd.resolvedTargetType = previous.resolvedTargetType;
137          // 设置mbd的工厂方法返回类型为previous的工厂方法返回类型
138          mbd.factoryMethodReturnType = previous.factoryMethodReturnType;
139          // 设置mbd的用于缓存用于自省的唯一工厂方法候选为previous的用于缓存用于自省的唯一工厂方法候选
140          mbd.factoryMethodToIntrospect = previous.factoryMethodToIntrospect;
141       }
142    }
143 }

1、根据beanName从mergedBeanDefinitions缓存中获取beanName对应的RootBeanDefinition对象,如果缓存中存在bean定义信息并且bean定义信息不需要重新合并定义,返回缓存中的对象;

2、若缓存中的对象不存在或者mbd需要重新定义,则合并父级BeanDefinition并返回RootBeanDefinition.   ·若beanName的bd(beanDefinition)无pbd(父级BeanDefinition)   ·如果原始的bd为rbd(RootBeanDefinition)类型,原始的bd深拷贝一份,作为副本   ·若原始的bd不为rbd类型,创建RootBeanDefinition对象,对原始bd对深深拷贝,   ·若beanName的bd(beanDefinition)有pbd(父级BeanDefinition)   ·获取父级bd对应的实际beanName类名称;   ·若原始bd的beanName与父级pbd的beanName不一致,获取parentBeanName合并的BeanDefinition赋值给pbd;   ·若原始bd的beanName与父级pbd的beanName一致,拿到父级BeanFactory,父级BeanFactory获取父级bd的MergedBeanDefinition。   ·使用pbd(parentBeanDefinition)构建RootBeanDefinition对象;   ·使用原始bd覆盖pbd的信息。     1. 如果在给定的bean定义中指定,则将覆盖beanClass     2. 将始终从给定的bean定义中获取abstract,scope,lazyInit,autowireMode,dependencyCheck和dependsOn     3. 将给定bean定义中ConstructorArgumentValues,propertyValues,methodOverrides 添加到现有的bean定义中     4. 如果在给定的bean定义中指定,将覆factoryBeanName,factoryMethodName,initMethodName,和destroyMethodName 3、如果存在上一个从bean名称映射到合并的RootBeanDefinition集合中取出的mbd,并且该mbd需要重新合并定义   ·1. 设置mbd的目标类型为previous的目标类型   ·2. 设置mbd的工厂bean标记为previous的工厂bean标记   ·3. 设置mbd的用于缓存给定bean定义的确定的Class为previous的用于缓存给定bean定义的确定的Class   ·4. 设置mbd的工厂方法返回类型为previous的工厂方法返回类型   ·5. 设置mbd的用于缓存用于自省的唯一工厂方法候选为previous的用于缓存用于自省的唯一工厂方法候选 4、返回设置完成的mbd

2、getBean - 获取beanName

  getBean是抽象类AbstractBeanDefinition中实现的。
1 // 通过beanName获取bean实例
2 public Object getBean(String name) throws BeansException {
3    // 此方法是实际获取bean的方法,也是触发依赖注入的方法
4    return doGetBean(name, null, null, false);
5 }
  该方法时实例化单例对象的核心方法,核心方法 getBean -> doGetBean -> createBean -> doCreateBean,先做下了解,后续单独拿出一章节来分析。

3、getSingleton - 从缓存中获取bean实例

  getSingleton是在抽象类AbstractBeanDefinition中实现的。
 1 // 一级缓存 
 2 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
 3 // 二级缓存
 4 private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
 5 // 三级缓存
 6 private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
 7 
 8 // 通过beanName返回已注册的单例对象
 9 @Nullable
10 protected Object getSingleton(String beanName, boolean allowEarlyReference) {
11    // 从一级缓存(存放完整的bean)中获取beanName对应的单例对象
12    Object singletonObject = this.singletonObjects.get(beanName);
13    // 如果一级缓存中没有,并且该beanName对应的单例bean正在创建中
14    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
15       // 从早期单例对象缓存(存放已实例化未初始化的bean)中获取单例对象(之所以称为早期单例对象,是因为earlySingletonObjects里
16       // 的对象都是通过体提前曝光的ObjectFactory创建出来的,还未进行属性填充等操作)
17       singletonObject = this.earlySingletonObjects.get(beanName);
18       // 如果在早期单例对象缓存中也没有,并且允许创建早期单例对象引用
19       if (singletonObject == null && allowEarlyReference) {
20          //如果为空,则锁定全局变量并进行处理
21          synchronized (this.singletonObjects) {
22             // 双重检验锁 - DCL
23             singletonObject = this.singletonObjects.get(beanName);
24             if (singletonObject == null) {
25                singletonObject = this.earlySingletonObjects.get(beanName);
26                if (singletonObject == null) {
27                   // 当某些方法需要提前初始化的时候则会调用addSingletonFactory方法将对应的ObjectFactory初始化策略存储在singletonFactories
28                   ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
29                   if (singletonFactory != null) {
30                      // 如果存在单例对象工厂,则通过工厂创建一个单例对象
31                      singletonObject = singletonFactory.getObject();
32                      // 记录在缓存中,二级缓存和三级缓存的对象不能同时存在
33                      this.earlySingletonObjects.put(beanName, singletonObject);
34                      // 从三级缓存中移除
35                      this.singletonFactories.remove(beanName);
36                   }
37                }
38             }
39          }
40       }
41    }
42    return singletonObject;
43 }
  根据beanName从缓存中获取对应的实例,引入一级、二级、三级缓存的概念。 1、一级缓存 - singletonObjects   单例对象的缓存,存放<beanname, beaninstance="">的键值对,存放完整的bean用于保存BeanName和创建bean实例之间的关系。 2、二级缓存 - earlySingletonObjects   存放提前暴露的Bean,Bean 是不完整的,未完成属性注入和执行 初始化(init) 方法,保存BeanName和创建bean实例之间的关系,与singletonFactories的不同之处在于,当一个单例bean被放到这里之后,那么当bean还在创建过程中就可以通过getBean方法获取到,可以方便进行循环依赖的检测。 3、三级缓存 - singletonFactories   存放的是 Bean 工厂,工厂的作用主要是生产 Bean存放到二级缓存中用于保存BeanName和创建bean的工厂之间的关系。 4、afterSingletonsInstantiated - bean实例化后的处理

2、总结

  1、遍历beanNames集合,合并beanName的父级BeanDefinition对象,返回RootBeanDefinition对象;   2、如果rbd为非抽象,单例,非懒加载的,判断bean是否实现了FactoryBean接口,若实现了FactoryBean接口,beanName需要加'&'作为前缀组成新的beanName,通过getBean方法创建或获取bean实例;若未实现FactoryBean接口,直接通过beanName从getBean方法创建或获取bean实例。   3、再次遍历beanNames集合,触发bean初始化后的回调处理。  

标签:容器,RootBeanDefinition,mbd,beanName,缓存,bean,源码,IOC,previous
From: https://www.cnblogs.com/RunningSnails/p/17004453.html

相关文章