前言
这篇文章是接上一篇文章《IOC启动流程(二)》,上一章节我们见到了Spring IOC容器的容器创建和配置加载两个大的流程,接来下分析Bean的解析以及Bean的注册流程。这里我终于可以把IOC启动流程的大图放上来了,你可以根据该图来看我接下来的流程分析
Bean的解析:XmlBeanDefinitionReader
Spring IOC启动创建完容器之后,最终委托XmlBeanDefinitionReader#loadBeanDefinitions
加载Bean。
XmlBeanDefinitionReader通过 ResourcePatternResolver
加载配置XML转换为 Resource
对象并封装成InputSource 文档解析源,然后XmlBeanDefinitionReader
通过DocumentLoader.loadDocument
把InputSource(XML配置文件)解析成Document
。最后调用registerBeanDefinitions
方法解析和注册Bean :见XmlBeanDefinitionReader#loadBeanDefinitions源码如下:
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//将 XML 文件转换为 Document 对象,通过 documentLoader来解析
Document doc = doLoadDocument(inputSource, resource);
//【重要】解析和注册Bean的消息流程
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
...省略...
下面是:DefaultDocumentLoader#loadDocument
加载文档源码:
//XML解析成Document,调用documentLoader.loadDocument完成
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
//创建文档解析工厂
DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
if (logger.isTraceEnabled()) {
logger.trace("Using JAXP provider [" + factory.getClass().getName() + "]");
}
//创建文档解析器
DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
//执行解析了
return builder.parse(inputSource);
}
下面是registerBeanDefinitions方法,即:Bean的解析和注册流程:
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//Bean的文档解析器,由 DefaultBeanDefinitionDocumentReader 实现
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//容器中Bean的数量
int countBefore = getRegistry().getBeanDefinitionCount();
//通过 DefaultBeanDefinitionDocumentReader .registerBeanDefinitions 注册Bean
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//统计解析的Bean的个数
return getRegistry().getBeanDefinitionCount() - countBefore;
}
这里创建了DefaultBeanDefinitionDocumentReader
Bean的文档解析器,调用其registerBeanDefinitions
方法来注册Bean,见:DefaultBeanDefinitionDocumentReader#registerBeanDefinitions
DefaultBeanDefinitionDocumentReader#registerBeanDefinitions
DefaultBeanDefinitionDocumentReader
委派BeanDefinitionParserDelegate
进行Document的解析工作
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
//获取根元素,调用doRegisterBeanDefinitions方法
doRegisterBeanDefinitions(doc.getDocumentElement());
}
protected void doRegisterBeanDefinitions(Element root) {
//创建BeanDefinitionParserDelegate,它是Bean解析委派器,定义了XML的各种元素的解析
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
// We cannot use Profiles.of(...) since profile expressions are not supported
// in XML config. See SPR-12458 for details.
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
//解析之前的动作,空方法,可以通过复写该方法做扩展
preProcessXml(root);
//解析Document,从root开始,委派给BeanDefinitionParserDelegate来解析
parseBeanDefinitions(root, this.delegate);
//解析之后的动作,空方法,可以通过复写该方法做扩展
postProcessXml(root);
this.delegate = parent;
}
该方法中创建了BeanDefinitionParserDelegate
,它定义了Spirng的xml中的所有的元素,然后委派它来对Document进行解析,继续跟 BeanDefinitionParserDelegate.parseBeanDefinitions
方法
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//判断是否使用默认的Spring的xml默认的命名空间
if (delegate.isDefaultNamespace(root)) {
//获取根元素下的所有元素
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//判断节点是XML的节点
if (node instanceof Element) {
Element ele = (Element) node;
//判断命名空间
if (delegate.isDefaultNamespace(ele)) {
//按照Spring默认的命名空间解析元素
parseDefaultElement(ele, delegate);
}
else {
//使用自定义的规则解析
delegate.parseCustomElement(ele);
}
}
}
}
else {
//使用自定义的规则解析
delegate.parseCustomElement(root);
}
}
这里判断了命名空间之后,调用 parseDefaultElement
方法进行解析文档
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//如果Element是 <import> 元素,就执行 importBeanDefinitionResource 导入其他配置文件
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//如果是 <alias> 就调用processAliasRegistration 注册 alias别名
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//如果是 <bean> 元素就走 processBeanDefinition,解析Bean
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
//如果是 <beans> 就走 doRegisterBeanDefinitions 注册多个Bean
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
这里判断了 import ,alias ,bean ,beans几种元素,分别走不同的方法进行解析。
Import 解析
下面是对 importBeanDefinitionResource
方法的分析 ,该方法的主要作用是解析<import 导入的配置文件,然后把其中的Bean的解析出来注册到Spring容器中,还是调用的是 XmlBeanDefinitionReader#loadBeanDefinitions
方法来完成Bean的加载的。
/**
* Parse an "import" element and load the bean definitions
* from the given resource into the bean factory.
*/
protected void importBeanDefinitionResource(Element ele) {
//得到<import resource="配置路径" resouce即:导入的配置路径
String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
if (!StringUtils.hasText(location)) {
//没导入任何文件,直接返回
getReaderContext().error("Resource location must not be empty", ele);
return;
}
//解析系统属性,解析占位符
// Resolve system properties: e.g. "${user.dir}"
location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
Set<Resource> actualResources = new LinkedHashSet<>(4);
//给定导入的文件的位置是绝对URI还是相对URI
// Discover whether the location is an absolute or relative URI
boolean absoluteLocation = false;
try {
absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
}
catch (URISyntaxException ex) {
// cannot convert to an URI, considering the location relative
// unless it is the well-known Spring prefix "classpath*:"
}
//绝对路径
// Absolute or relative?
if (absoluteLocation) {
try {
//使用XmlBeanDefinitionReader加载导入的配置文件
int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
if (logger.isTraceEnabled()) {
logger.trace("Imported " + importCount + " bean definitions from URL location [" + location + "]");
}
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error(
"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
}
}
else {
//相对路径
// No URL -> considering resource location as relative to the current file.
try {
int importCount;
//把配置文件加载成相对路径的Resource对象 ,就是要找到导入读文件,然后返回它的Resource对象
Resource relativeResource = getReaderContext().getResource().createRelative(location);
if (relativeResource.exists()) {
//如果文件存在,使用XmlBeanDefinitionReader加载导入的配置文件
importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
actualResources.add(relativeResource);
}
else {
//如果不存在,使用资源加载器的相对路径来拼接文件地址,然后使用XmlBeanDefinitionReader加载导入的配置文件
String baseLocation = getReaderContext().getResource().getURL().toString();
importCount = getReaderContext().getReader().loadBeanDefinitions(
StringUtils.applyRelativePath(baseLocation, location), actualResources);
}
if (logger.isTraceEnabled()) {
logger.trace("Imported " + importCount + " bean definitions from relative location [" + location + "]");
}
}
catch (IOException ex) {
getReaderContext().error("Failed to resolve current resource location", ele, ex);
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error(
"Failed to import bean definitions from relative location [" + location + "]", ele, ex);
}
}
Resource[] actResArray = actualResources.toArray(new Resource[0]);
//发布一个import成功的事件
getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}
alias 别名注册
下面是对 processAliasRegistration
方法的解析,方法的作用是 解析<alias 给定的别名元素,向注册表注册别名。
/**
* Process the given alias element, registering the alias with the registry.
*/
protected void processAliasRegistration(Element ele) {
//获取 元素的name属性
String name = ele.getAttribute(NAME_ATTRIBUTE);
//获取元素的alias属性
String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
//做了一下判断,name和alias是否为空
boolean valid = true;
if (!StringUtils.hasText(name)) {
getReaderContext().error("Name must not be empty", ele);
valid = false;
}
if (!StringUtils.hasText(alias)) {
getReaderContext().error("Alias must not be empty", ele);
valid = false;
}
if (valid) {
//如果定义了name或者alis
try {
//注册alias ,调用 AliasRegistry 的 registerAlias 来注册
//默认实现 .SimpleAliasRegistry#registerAlias
getReaderContext().getRegistry().registerAlias(name, alias);
}
catch (Exception ex) {
getReaderContext().error("Failed to register alias '" + alias +
"' for bean with name '" + name + "'", ele, ex);
}
//alias注册完之后,发布一个事件
getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
}
}
上面方法 获取到元素的name和alias属性后,调用 SimpleAliasRegistry#registerAlias
来注册Bean的名字,其实就是使用一个ConcurrentHashMap
来存储。
public class SimpleAliasRegistry implements AliasRegistry {
/** Logger available to subclasses. */
protected final Log logger = LogFactory.getLog(getClass());
/** Map from alias to canonical name. */
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
...省略...
@Override
public void registerAlias(String name, String alias) {
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
//加锁
synchronized (this.aliasMap) {
if (alias.equals(name)) {
//如果name和alias相同,从map中移除
this.aliasMap.remove(alias);
if (logger.isDebugEnabled()) {
logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
}
}
else {
//通过alias获取map中的值
String registeredName = this.aliasMap.get(alias);
if (registeredName != null) {
if (registeredName.equals(name)) {
// An existing alias - no need to re-register
return;
}
if (!allowAliasOverriding()) {
throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
name + "': It is already registered for name '" + registeredName + "'.");
}
if (logger.isDebugEnabled()) {
logger.debug("Overriding alias '" + alias + "' definition for registered name '" +
registeredName + "' with new target name '" + name + "'");
}
}
//判断名字循环引用问题
checkForAliasCircle(name, alias);
//以alias为key name为值保持到ma
this.aliasMap.put(alias, name);
if (logger.isTraceEnabled()) {
logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
}
}
}
}
bean 的解析
下面是对 processBeanDefinition方法的解析,将解析的工作委托给BeanDefinitionParserDelegate
,然后通过BeanDefinitionReaderUtils
调用BeanDefinitionRegistry
进行Bean的注册
/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//委托为BeanDefinitionParserDelegate 解析 Bean , BeanDefinitionHolder是对 BeanDefinition 的封装
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//如果需要,装饰 Bean 定义
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
//注册Bean
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));
}
}
跟一下 BeanDefinitionParserDelegate#parseBeanDefinitionElement(BeanDefinition)
方法
//解析提供的<bean>元素
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//获取id属性
String id = ele.getAttribute(ID_ATTRIBUTE);
//获取name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
//处理名字,添加到aliases集合中
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
//如果ID为空,把第一个name赋值被 beanName
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isTraceEnabled()) {
//未指定ID,使用beanName 作为 name
logger.trace("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
//检查id,name,aliases的唯一性
checkNameUniqueness(beanName, aliases, ele);
}
//解析Bean元素 , 得到beanDefinition
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
//为给定的Bean生成一个唯一的名字
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
//为解析的 Bean 使用别名向 IOC 容器注册
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
//为解析的 Bean 使用别名注册时,为了向后兼容
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isTraceEnabled()) {
logger.trace("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
//把beanDefinition封装成BeanDefinitionHolder
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
这里调用了
AbstractBeanDefinition parseBeanDefinitionElement
方法 讲 Element 元素(Bean) 解析成 BeanDefinition
,然后封装成 BeanDefinitionHolder
返回,下面是parseBeanDefinitionElement
方法的源码:
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
//获取到Bean的class属性
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
String parent = null;
//获取parent属性,如果有的话
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
//为给定的类名和父名创建一个 bean 定义,new 了一个GenericBeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//解析Bean的属性配置,全都设置到BeanDefinition对象中
//比如:scope,abstract,lazy-init,autowire,depends-on,primary,
//init-method,destroy-method,factory-method,factory-bean
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//设置Bean的Description属性
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//对Bean的 的 元信息(meta) 属性做解析
parseMetaElements(ele, bd);
//对lookup-Method属性做解析
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//对replaced-Method属性做解析
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//对构造方法 constructor-arg 做解析,把构造器参数会保存到BeanDefinition.
parseConstructorArgElements(ele, bd);
//对 property属性做解析,把property封装成 MutablePropertyValues保存到BeanDefinition
parsePropertyElements(ele, bd);
//对Qualifier属性做解析
parseQualifierElements(ele, bd);
//为bean设置资源,就是配置文件的Resource对象
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
return null;
}
上面对一个<bean />
的所有的属性,及子元素都做了解析,相关属性和依赖关系都封装到了BeanDefinition
对象中具体的细节就不进去展开了,你可以自己断点进去看。我们可以看下BeanDefinition这个类
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable {
...省略部分代码...
//bean的class
@Nullable
private volatile Object beanClass;
//bean的scope
@Nullable
private String scope;
private boolean abstractFlag;
//是否是lazyInit懒加载
private boolean lazyInit;
private int autowireMode;
private int dependencyCheck;
@Nullable
private String[] dependsOn;
private boolean autowireCandidate;
private boolean primary;
private final Map<String, AutowireCandidateQualifier> qualifiers;
//工厂名
@Nullable
private String factoryBeanName;
//工厂方法
@Nullable
private String factoryMethodName;
//构造器参数
@Nullable
private ConstructorArgumentValues constructorArgumentValues;
//property注入
@Nullable
private MutablePropertyValues propertyValues;
@Nullable
private MethodOverrides methodOverrides;
//初始方法
@Nullable
private String initMethodName;
//销毁方法
@Nullable
private String destroyMethodName;
private boolean enforceInitMethod;
private boolean enforceDestroyMethod;
private boolean synthetic;
private int role;
//描述
@Nullable
private String description;
//配置文件资源
@Nullable
private Resource resource;
Bean的注册
到这里Bean的解析就告一段落,代码回到 DefaultBeanDefinitionDocumentReader#processBeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//委托为BeanDefinitionParserDelegate 解析 Bean , BeanDefinitionHolder是对 BeanDefinition 的封装
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//如果需要,装饰 Bean 定义,只有命名空间不是默认的时候才会走这
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
//注册Bean
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
我们已经走完了 BeanDefinitionParserDelegate .parseBeanDefinitionElement
解析Bean的方法,接下来该走 BeanDefinitionReaderUtils#registerBeanDefinition
注册Bean的方法了
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
//获取Bean的名字
String beanName = definitionHolder.getBeanName();
//调用BeanDefinitionRegistry 注册器注册BeanDefinition
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
//注册别名,如果BeanDefinition有
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
这里调用了 BeanDefinitionRegistry 注册器 的registerBeanDefinition方法注册bean,然后还会调用registerAlias注册别名,先看一下registerBeanDefinition方法,这里走的是GenericApplicationContext#registerBeanDefinition
:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
//调用工厂的注册Bean方法
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
调用 this.beanFactory.registerBeanDefinition
方法,代码来到DefaultListableBeanFactory#registerBeanDefinition
DefaultListableBeanFactory#registerBeanDefinition
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
//用来存储BeanDefinition
/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
//验证 beanDefinition
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
//根据Bean的名字从 beanDefinitionMap 缓存中获取 BeanDefinition ,
// 也就是说BeanDefinitionMap是存放在一个ConcurrentHashMap中
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
//如果已经存在这个Bean , 是允许 Bean 定义覆盖
if (!isAllowBeanDefinitionOverriding()) {
//如果不允许覆盖,抛出异常
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
...省略...
//把beanDefinition 存放到 一个 ConcurrentHashMap中 ,覆盖掉以前的Bean
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
//如果Map中没有这个Bean,检查这个工厂的 bean 创建阶段是否已经开始
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 {
//默认走这里,,把beanDefinition 存放到 一个 ConcurrentHashMap中
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
//把bean的name保存到 List<String> beanDefinitionNames = new ArrayList<> 集合中
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
//如果 Map中已经存在这个Bean, 或者单利缓存 : singletonObjects = new ConcurrentHashMap 中包含这个Bean
if (existingDefinition != null || containsSingleton(beanName)) {
//重置给定 bean 的所有 bean 定义缓存
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
这里我们看到,BeanDefinition是存储到一个ConcurrentHashMap
中的,代码首先中Map中获取该Bean,如果存在该Bean,且设置了允许Bean的覆盖,就会把BeanDefinition存储到Map中覆盖之前的Map中的BeanDefinition。
如果Map中没有这个Bean就会以name为key把BeanDefinition存储到ConcurrentHashMap中,bean的name也会保存到一个beanDefinitionNames = new ArrayList(256)
中。
总结
到这里文章就结束了,本章内容是基于XML的IOC启动流程源码分析,下面做个总结
- 我们最开始分析了IOC容器常见工厂,及相关的核心类
- IOC入口从ClasspathXmlApplicationContext开始,通过父类创建ResourcePatternResolver用来加载Bean的资源文件
- 保存资源文件的location
- 调用父类AbstractApplicationContext的refresh方法刷新容器,方法通过子类AbstractRefreshableApplicationContext创建容器工厂(创建的是DefaultListableBeanFactory),以及加载Bean。
- 加载Bean的工作最终委托给XmlBeandifinetionReader,它通过ResourcePatternResolver加载资源文件Resource,调用DefualtDocumentLoader将Resource转为Document对象,然后委派BeanDefinitionParserDelegate去解析Bean
- BeanDefinitionParserDelegate解析完Bean之后,把Bean的属性,构造器参数,依赖关系等全都封装成BeanDefinition对象。
- 然后BeanDefinitionParserDelegate调用BeanDefinitionReaderUtils注册Bean
- BeanDefinitionReaderUtils最终调用BeanDefinitionRegister来注册BeanDefinition,然后把BeanDefinition注册到DefaultListableBeanFactory的一个ConcurrentHashMap中。