在 Spring源码系列:BeanDefinition载入(上) 中已经大概捋了一下解析过程,本篇将记录一下bean的注册过程。
bean的注册就是DefaultListableBeanFactory中registerBeanDefinition方法来完成的。那我就来看registerBeanDefinition这个方法的具体逻辑。
这里的验证主要是验证不能将静态工厂方法与方法重写相结合(静态工厂方法必须创建实例);
if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Validation of bean definition failed", ex); } }
这里就是先根据beanName从beanDefinitionMap去取BeanDefinition,并将结果给oldBeanDefinition。
BeanDefinition oldBeanDefinition; oldBeanDefinition = this.beanDefinitionMap.get(beanName);
如果当前beanDefinitionMap中已经存在名为beanName的Beandefinition了(即检查是否有相同名称的beanDefinition已经在Ioc容器中注册过了)。,如果有,则进行以下具体策略:
if (oldBeanDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { //省略异常代码 } else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { //省略异常代码 } else if (!beanDefinition.equals(oldBeanDefinition)) { //提示覆盖log信息 } else { //提示覆盖log信息 } //覆盖原有的Beandefinition this.beanDefinitionMap.put(beanName, beanDefinition); }
//检查bean的创建阶段是否已经开始,也就是说是否已经创建了 if (hasBeanCreationStarted()) { //Cannot modify startup-time collection elements anymore (for stable iteration) // 无法修改启动时间收集元素(用于稳定迭代)(译注) //注册过程需要保证数据的一致性,所有需要加锁同步 synchronized (this.beanDefinitionMap) { //注册到beanDefinitionMap中 this.beanDefinitionMap.put(beanName, beanDefinition); //下面就是将当前beanName存放到beanDefinitionNames中 List<String> updatedDefinitions = new ArrayList<String>( this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; //如果单例模式的bean名单中有该bean的name,那么移除掉它。 //也就是说着,将一个原本是单例模式的bean重新注册成一个普通的bean if (this.manualSingletonNames.contains(beanName)) { Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames); updatedSingletons.remove(beanName); this.manualSingletonNames = updatedSingletons; } } } // 仍处于启动阶段,bean还没有开始注册 else { // Still in startup registration phase this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); this.manualSingletonNames.remove(beanName); } this.frozenBeanDefinitionNames = null;
1:oldBeanDefinition如果存在,且执行到了这里也没有抛出异常,说明该BeanDefinition已经被覆盖,缓存需要更新。
2:如果是单例模式的bean对象则Set中包含该beanName,执行到这里说明该BeanDefinition已经从一个单例模式的bean变为了一个普通的bean,所以缓存也需要更新。
if (oldBeanDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); }
OK,我们来看下resetBeanDefinition这个方法:
这个方法的作用就是重置给定bean的所有bean定义缓存,包括从它派生的bean的缓存。
protected void resetBeanDefinition(String beanName) { // 如果已经创建,则删除给定bean的合并bean定义。 clearMergedBeanDefinition(beanName); // 如果有的话,从singleton 高速缓存中删除相应的bean。 //但是这也不是必须的,而只是为了覆盖上下文的默认bean //(就是从manualSingletonNames中移除) destroySingleton(beanName); //递归的方式来 重置具有给定bean作为父项的所有bean定义。 for (String bdName : this.beanDefinitionNames) { if (!beanName.equals(bdName)) { BeanDefinition bd = this.beanDefinitionMap.get(bdName); if (beanName.equals(bd.getParentName())) { resetBeanDefinition(bdName); } } } }
Bean的注册就到这里了,下一篇学习的是DefaultListableBeanFactory这个集大成者容器。