在Spring源码系列:BeanDefinition载入(上)中已经大概捋了一下解析过程,本篇将记录一下bean的注册过程。java
bean的注册就是DefaultListableBeanFactory中registerBeanDefinition方法来完成的。那我就来看registerBeanDefinition这个方法的具体逻辑。缓存
一、beanDefinition类型判断和验证app
这里的验证主要是验证不能将静态工厂方法与方法重写相结合(静态工厂方法必须建立实例);框架
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(),
beanName,"Validation of bean definition failed", ex);
}
}
复制代码
二、尝试从beanDefinitionMap中获取老的beanpost
这里就是先根据beanName从beanDefinitionMap去取BeanDefinition,并将结果给oldBeanDefinition。学习
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
复制代码
三、beanDefinitionMap中已经存在名为beanName的Beandefinitionthis
若是当前beanDefinitionMap中已经存在名为beanName的Beandefinition了(即检查是否有相同名称的beanDefinition已经在Ioc容器中注册过了)。,若是有,则进行如下具体策略:spa
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);
}
复制代码
四、beanDefinitionMap不存在名为beanName的Beandefinitioncode
//检查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;
复制代码
五、执行缓存清除orm
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这个集大成者容器。