【超详细的Spring源码分析 —— 05 Spring对于Bean管理的核心组件源码分析 - 注册Bean Definition】

在上一章中,我留了一个 "BeanDefinition注册到registry" 的尾巴还没分析,这边我把代码入口从新放到下面,以便于回顾:java

/** * 经过解析器delegate去处理给定的bean element, 并解析出相应的bean Definition, 注册到工厂中 */
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // 经过delegate解析bean定义, 获取到一个BeanDefinitionHolder实例
    // 这个实例, 其实就表明了xml文件中的一个完整的bean标签对应的Bean Definition
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    
    // 若是bdHolder不为空, 说明解析成功了, 以后就是注册环节了
    // 注册环节咱们留着在下一篇中详细展开
    if (bdHolder != null) {
    	bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
    	try {
            // 注册最终的BeanDefinition到工厂
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
    	}
    	catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex);
    	}
    	// Send registration event.
    	getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}
复制代码

咱们要关注的是:BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());缓存

1、注册最终的BeanDefinition到工厂

要注册BeanDefinition到工厂,首先咱们得获取到工厂,这里是经过读取器上下文来获取到的 getReaderContext().getRegistry()ide

还记得咱们第四章分析的:建立读取器上下文的代码么,读取器上下文内部是封装了读取器实例的,这就意味着咱们可以经过上下文获取到读取器。工具

紧接着,咱们在第一章分析的,建立读取器时会传入一个 registry 类型的参数,所以经过读取器咱们又可以获取到 registry。ui

所以,咱们就可以经过读取器上下文获取到 registry。this

BeanDefinitionReaderUtils.registerBeanDefinition()spa

这里是调用了一个工具类来实现注册的流程线程

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
    // 获取到Bean的惟一标识
    String beanName = definitionHolder.getBeanName();
    // 重点!!!!
    // 将 bean 定义真正注册到 Bean 工厂中
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    
    // 若是存在别名, 那么会注册别名
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
    	for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
    	}
    }
}
复制代码

咱们接着深刻到 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); 这部分的逻辑:debug

因为对于 registry 的实现是采用的 —— DefaultListableBeanFactory,所以咱们看看这个类对于 registerBeanDefinition() 的实现便可。日志

下面的代码有些长,咱们挑关键的部分分析便可:

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
    // 惟一标识不能为空
    Assert.hasText(beanName, "Bean name must not be empty");
    // 确保Bean定义不能为空
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    
    // 若是Bean定义是 AbstractBeanDefinition 类型, 那么会进行一个验证逻辑
    if (beanDefinition instanceof AbstractBeanDefinition) {
    	try {
            ((AbstractBeanDefinition) beanDefinition).validate();
    	}
    	catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex);
    	}
    }
    
    // 咱们的Bean定义是挨个被解析而后注册到工厂中的
    // 这就意味着工厂中可能已经存在其余Bean定义
    
    // 所以这里会先尝试从工厂中获取一下咱们要注册的bean定义
    // 确保工厂中是不存在这个bean定义的
    // 这里存放 惟一标识+BeanDefinition 的容器beanDefinitionMap是 concurrentHashMap
    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    // 若是已经存在相应的惟一标识了
    if (existingDefinition != null) {
        // 那么为判断是否容许 BeanDefinition 的覆盖
        // 若是不容许就抛出异常
    	// 通常都是不容许的
    	if (!isAllowBeanDefinitionOverriding()) {
    		throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
    	}
    	// 若是容许覆盖, 那么会进行一个bean定义角色的判断
    	// 若是已经存在的bean定义的角色小于当前要存放bean定义的角色, 那么会进行一个日志打印
    	// 通常在开发中也不多会进入这个逻辑
    	else if (existingDefinition.getRole() < beanDefinition.getRole()) {
    		// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
    		if (logger.isInfoEnabled()) {
    			logger.info("Overriding user-defined bean definition for bean '" + beanName +
    					"' with a framework-generated bean definition: replacing [" +
    					existingDefinition + "] with [" + beanDefinition + "]");
    		}
    	}
    	// 若是两者(已经存在的bean定义和要覆盖的bean定义)不相同
    	// 那么打印一个日志
    	else if (!beanDefinition.equals(existingDefinition)) {
    		if (logger.isDebugEnabled()) {
    			logger.debug("Overriding bean definition for bean '" + beanName +
    					"' with a different definition: replacing [" + existingDefinition +
    					"] with [" + beanDefinition + "]");
    		}
    	} 
    	else { // 若是是其余的极端状况, 也会打印一个日志
    		if (logger.isTraceEnabled()) {
    			logger.trace("Overriding bean definition for bean '" + beanName +
    					"' with an equivalent definition: replacing [" + existingDefinition +
    					"] with [" + beanDefinition + "]");
    		}
    	}
    	
    	// 进行一个bean定义的覆盖,放置key-value到map中
    	this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    else { // 若是 concurrentHashMap 中不存在相应的bean定义键值对
    	// 那么会检查这个工厂中bean的建立阶段是否已经启动
    	// 也就是这个工厂中的全部bean它是否被标记为 created
    	// 若是已经启动
    	if (hasBeanCreationStarted()) {
    		// Cannot modify startup-time collection elements anymore (for stable iteration)
    		// 那么会进行一个同步
    		// 防止多个线程同时进行注册的操做
    		synchronized (this.beanDefinitionMap) {
    			this.beanDefinitionMap.put(beanName, beanDefinition);
    			List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
    			updatedDefinitions.addAll(this.beanDefinitionNames);
    			updatedDefinitions.add(beanName);
    			this.beanDefinitionNames = updatedDefinitions;
    			removeManualSingletonName(beanName);
    		}
    	}
    	else { // 不然就会直接注册, 不须要进行同步
    		// Still in startup registration phase
    		this.beanDefinitionMap.put(beanName, beanDefinition);
    		this.beanDefinitionNames.add(beanName);
    		removeManualSingletonName(beanName);
    	}
    	this.frozenBeanDefinitionNames = null;
    }
    
    if (existingDefinition != null || containsSingleton(beanName)) {
        // 重置 BeanDefinition 缓存的处理
    	resetBeanDefinition(beanName);
    }
}
复制代码

当上面这个方法执行完毕后,工厂中的 BeanDefinitionMap 这个容器就已经存放了一个key-value键值对,key=惟一标识、value=beanDefinition。

当整个解析、注册的事件处理完毕后,咱们返回到一开始给出的那个方法中:

/** * 经过解析器delegate去处理给定的bean element, 并解析出相应的bean Definition, 注册到工厂中 */
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // 经过delegate解析bean定义, 获取到一个BeanDefinitionHolder实例
    // 这个实例, 其实就表明了xml文件中的一个完整的bean标签对应的Bean Definition
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    
    // 若是bdHolder不为空, 说明解析成功了, 以后就是注册环节了
    // 注册环节咱们留着在下一篇中详细展开
    if (bdHolder != null) {
    	bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
    	try {
            // 注册最终的BeanDefinition到工厂
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
    	}
    	catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex);
    	}
    	// 发送事件
    	getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}
复制代码

咱们看到最后执行的方法:getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));

这里采用了一个观察者模式,当特定的事件触发(成功完成Bean定义的解析、注册),那么会调用观察者类(读取器上下文)的方法,执行一些特定逻辑。

2、总结

那么这里,整个 Spring 对 Bean 的解析、装配流程就分析完毕了。从宏观上来看,beanDefinitionReader.loadBeanDefinitions() 这个逻辑就完成了。但要注意,截止到目前,咱们只是在工厂中注册了Bean Definition,并无对其完成一个实例化的过程。 实例化的过程还要在后续的逻辑中才开始执行。

因而可知,Spring 对外提供的 API 接口仅仅是冰山一角,底层的实现就如同大海同样深不可测。

那么在下一章将带来:defaultListableBeanFactory.getBean("student", Student.class); ,也就是依赖注入的详细分析。

相关文章
相关标签/搜索