Spring IOC源码之(2)obtainFreshBeanFactory

obtainFreshBeanFactory作为refresh中重要方法之一,主要承担了创建容器,解析配置文件、注解类中的bean信息,并注册进容器等相关工作。此时的bean是一个还未初始化的实例,接下来就一步步去了解Spring源码

在prepareRefresh中分析了容器在创建之前所做的一些准备工作。接下来就开始进入容器及bean创建的源码中,在分析之前,将上一篇的贯穿始终的整体分析图(往后都取名为分析图)拷贝过来,方便后续源码分析能随时了解整体结构的演变

Spring IOC源码之(2)obtainFreshBeanFactory_第1张图片

 跟随源码来到AbstractRefreshableApplicationContext中

// 和GenericApplicationContext不同是,每次的刷新都会创建一个新的容器实例,后者自始而终都是同一个容器
@Override
protected final void refreshBeanFactory() throws BeansException {
    // 每次刷新前,都会改变上一个容器的标识位,并清除里面的Bean
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        // 给容器起一个全局唯一的标识
        beanFactory.setSerializationId(getId());
        // 定制是否相同的Bean是否进行覆盖,以及是否支持循环引用
        customizeBeanFactory(beanFactory);
        // 父类定义了加载动作,真正的实现会落到具体的子类中去完成
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

 进入到AbstractXmlApplicationContext源码中。没研源码之前,网上或者听同事说Spring是一个分工明确,耦合性比较低,扩展性高的框架,研究了之后发现Spring对这几点做到了极致

@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // 定义了从XML读取bean定义信息类
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // Configure the bean definition reader with this context's
    // resource loading environment.
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    // 同时也留给子类对reader进行定制化处理
    initBeanDefinitionReader(beanDefinitionReader);
    loadBeanDefinitions(beanDefinitionReader);
}

对上述中提到的Reader,发现bean定义信息来源不同,其对应的reader也不同,同时上下文也会对应着不同,此时我重新修改下分析图。

Spring IOC源码之(2)obtainFreshBeanFactory_第2张图片

接下来容器会将配置文件通过ResouceLoader转换为Resource,并转换为Document,直奔主题。Spring源码挨个分析的话,那就不用吃饭了,看着就会饱。

// DefaultBeanDefinitionDocumentReader源码
protected void doRegisterBeanDefinitions(Element root) {
    // 当beans中嵌套beans,当前的方法会被递归调用,delegate引用的是上一次的值
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);

    if (this.delegate.isDefaultNamespace(root)) {
        // beans指定profile属性和spring.profiles.active相对应
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                    profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                            "] not matching: " + getReaderContext().getResource());
                }
                return;
            }
        }
    }
    // 钩子方法
    preProcessXml(root);
    // 重点方法
    parseBeanDefinitions(root, this.delegate);
    // 钩子方法
    postProcessXml(root);
    // 调用结束前会将delegate恢复到上一轮的初始值,模拟出一个委托堆栈
    this.delegate = parent;
}

 根据节点的不同去解析不同的元素

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
	if (delegate.isDefaultNamespace(root)) {
		NodeList nl = root.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element) {
				Element ele = (Element) node;
				if (delegate.isDefaultNamespace(ele)) {
                    // 解析默认的标签beans、bean、import、alias
					parseDefaultElement(ele, delegate);
				}
				else {
                    // 解析上面之外的标签
					delegate.parseCustomElement(ele);
				}
			}
		}
	}
	else {
		delegate.parseCustomElement(root);
	}
}

我们先以标签作为主线去探讨各个实例bean是如何创建的。 

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
	// 解析import标签
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
		importBeanDefinitionResource(ele);
	}
    // alias
	else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
		processAliasRegistration(ele);
	}
    // bean
	else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
		processBeanDefinition(ele, delegate);
	}
    // beans,嵌套,递归调用
	else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
		// recurse
		doRegisterBeanDefinitions(ele);
	}
}
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
	if (bdHolder != null) {
		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
		try {
			// 最终丢给DefaultListableBeanFactory去进行注册
			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));
	}
}

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
    // 获取id和name(也就是bean的别名)
	String id = ele.getAttribute(ID_ATTRIBUTE);
	String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    
	List aliases = new ArrayList();
	if (StringUtils.hasLength(nameAttr)) {
		String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
		aliases.addAll(Arrays.asList(nameArr));
	}

	String beanName = id;
    // 如果bean没有给id,则以name(别名)中的第一个作为bean的id
	if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
		beanName = aliases.remove(0);
		if (logger.isDebugEnabled()) {
			logger.debug("No XML 'id' specified - using '" + beanName +
					"' as bean name and " + aliases + " as aliases");
		}
	}

	if (containingBean == null) {
		checkNameUniqueness(beanName, aliases, ele);
	}
    // 将配置文件中的bean转换为BeanDefinition,并设置相应的属性值
	AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
	if (beanDefinition != null) {
		if (!StringUtils.hasText(beanName)) {
			try {
				if (containingBean != null) {
					beanName = BeanDefinitionReaderUtils.generateBeanName(
							beanDefinition, this.readerContext.getRegistry(), true);
				}
				else {
					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.
					String beanClassName = beanDefinition.getBeanClassName();
					if (beanClassName != null &&
							beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
							!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
						aliases.add(beanClassName);
					}
				}
				if (logger.isDebugEnabled()) {
					logger.debug("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);
        // 包装为BeanDefinitionHolder
		return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
	}
	return null;
}

 DefaultListableBeanFactory注册Bean到容器中

@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");

	if (beanDefinition instanceof AbstractBeanDefinition) {
		try {
			((AbstractBeanDefinition) beanDefinition).validate();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
					"Validation of bean definition failed", ex);
		}
	}

	BeanDefinition oldBeanDefinition;

	oldBeanDefinition = this.beanDefinitionMap.get(beanName);
	if (oldBeanDefinition != null) {
        // 如果存在相同名字的bean,默认是可以覆盖老的bean
		if (!isAllowBeanDefinitionOverriding()) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
					"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
							"': There is already [" + oldBeanDefinition + "] bound.");
		}
		else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
			// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
			if (this.logger.isWarnEnabled()) {
				this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
						"' with a framework-generated bean definition: replacing [" +
						oldBeanDefinition + "] with [" + beanDefinition + "]");
			}
		}
        // bean的名字相同,BeanDefinition不同就先记录一个日志
		else if (!beanDefinition.equals(oldBeanDefinition)) {
			if (this.logger.isInfoEnabled()) {
				this.logger.info("Overriding bean definition for bean '" + beanName +
						"' with a different definition: replacing [" + oldBeanDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		else {
			if (this.logger.isDebugEnabled()) {
				this.logger.debug("Overriding bean definition for bean '" + beanName +
						"' with an equivalent definition: replacing [" + oldBeanDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}
	else {
		if (hasBeanCreationStarted()) {
			// Cannot modify startup-time collection elements anymore (for stable iteration)
			synchronized (this.beanDefinitionMap) {
				this.beanDefinitionMap.put(beanName, beanDefinition);
				List updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
				updatedDefinitions.addAll(this.beanDefinitionNames);
				updatedDefinitions.add(beanName);
				this.beanDefinitionNames = updatedDefinitions;
				if (this.manualSingletonNames.contains(beanName)) {
					Set updatedSingletons = new LinkedHashSet(this.manualSingletonNames);
					updatedSingletons.remove(beanName);
					this.manualSingletonNames = updatedSingletons;
				}
			}
		}
		else {
			// beanDefinitionMap是用于存放BeanDefinition
			this.beanDefinitionMap.put(beanName, beanDefinition);
            // beanDefinitionNames用于存放bean的名字
			this.beanDefinitionNames.add(beanName);
            // 用于存放手动注册的bean
			this.manualSingletonNames.remove(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

	if (oldBeanDefinition != null || containsSingleton(beanName)) {
		resetBeanDefinition(beanName);
	}
}

只是简单的介绍下整体流程,其实该分支还是挺复杂。整个Spring就像一个大树,根和枝众多,难以逐一分析透彻,倒不如按照一个主线理解其大致脉络即可。如下我总结的大致脉络图。

Spring IOC源码之(2)obtainFreshBeanFactory_第3张图片

小弟不才,如有错误,望指正!!!

你可能感兴趣的:(spring)