SpringIOC源码解析(6)—— BeanDefinition的注册

本文阅读 3 分钟
首页 代码,Java 正文
/** * 往注册表中注册一个新的 BeanDefinition 实例 */
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
      throws BeanDefinitionStoreException;
/** * 移除注册表中它注册的 BeanDefinition 实例 */
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
/** * 从注册表中取得指定的BeanDefinition 实例 */
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
/** * 判断 BeanDefinition 实例是否在注册表中(是否注册) */
boolean containsBeanDefinition(String beanName);

我在Spring专栏的之前的文章中曾经写过,DefaultListableBeanFactory继承了BeanDefinitionRegistry img 同时它里面还有个beanDefinitionMap

/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

所谓的注册就是往beanDefinitionMap中存储相应的<key,value>

再回到DefaultBeanDefinitionDocumentReader的processBeanDefinition方法 img   注册方法传入两个参数,BeanDefinition的包装实例和Registry实例,getRegistry返回的是AbstractBeanDefinitionReader中的成员变量:

@Override
public final BeanDefinitionRegistry getRegistry() { 
   return this.registry;
}

registry是通过该类的构造函数来传入的。

接下来进入到registerBeanDefinition中,

public static void registerBeanDefinition(
      BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
      throws BeanDefinitionStoreException { 

   // Register bean definition under primary name.
   // 将beandefinition及其名字注册到容器里
   String beanName = definitionHolder.getBeanName();
   registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

   // Register aliases for bean name, if any.
   // 如果存在别名则逐个注册进容器
   String[] aliases = definitionHolder.getAliases();
   if (aliases != null) { 
      for (String alias : aliases) { 
         registry.registerAlias(beanName, alias);
      }
   }
}

先将beandefinition及其名字注册到容器里,然后如果存在别名则把别名逐个注册进容器。

再进入到registerBeanDefinition方法里: img 先判断是否是AbstractBeanDefinition实例,由于GenericBeanDefinition就是AbstractBeanDefinition实例,所以肯定要进入 if 里。

  validate是用来校验lookup和replacemethod这两个属性他们对应的重写方法是否存在并且合法。

  接下来就是判重处理了,尝试从注册表里获取BeanDefinition的实例,如果已经存在了会根据容器的配置来决定是否要覆盖掉原先的BeanDefinition,如果允许覆盖则经过各种校验后会覆盖beanDefinitionMap的<key, value> img   如果原先并没有BeanDefinition的实例,则先判断下容器是否已经开始创建bean实例了(这里是bean不是BeanDefinition,前者依赖后者的创建),注册时会锁住map并把实例put进去

img

// 检查是否有同名的BeanDefinition已经在IOC容器中注册
if (existingDefinition != null || containsSingleton(beanName)) { 
   // 尝试重置所有已经注册过的BeanDefinition的缓存,包括BeanDefinition
   // 的父类以及合并的beanDefinition的缓存,所谓的合并BeanDefinition
   // 指的的有parent属性的beandefinition,该BeanDefinition会把parent的
   // BeanDefinition属性合并在一块
   resetBeanDefinition(beanName);
}

resetBeanDefinition是个递归调用的过程,比如本次更新A,而B的parent是A,则B也需要做重置,和B相关的包括B原先合并出来的属性,Bean的单例,以及Bean的后置器处理也都需要去做重置,B变化之后也要看看有没有把B当做parent的,也要做相应操作…

本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://wangjiawei.blog.csdn.net/article/details/120914172
-- 展开阅读全文 --
安全面试之XSS(跨站脚本攻击)
« 上一篇 07-24

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复