Spring源码01--BeanDefinition的加载流程

Bean的初始化过程

涉及IOC容器的相关设计,bean是在IOC容器中实现的。
 

Spring IOC容器

IOC 容器是Spring的基本组件,IoC 容器(又名DI 容器)是Spring 实现自动依赖注入的组件, Spring通过IOC 容器管理对象的创建及其生命周期,并向类注入依赖项。 IoC 容器可以创建指定类的对象,并在运行时通过构造函数、属性或方法注入所有依赖对象,并在适当的时候销毁它。实际就是Map结构。key存bean名称或ID,value存bean对应的定义成的beanDefiniton
一般IOC容器需要具备一下功能:

  1. Bean的注册,需要告诉IOC容器需要管理哪些对象。
  2. Bean的解析,IOC容器需要解析出对象的依赖并根据配置进行依赖注入。
  3. Bean的生命周期管理,IOC容器需要管理Bean的生命周期。
     

Spring容器设计

主要分为两个容器系列:
一个是实现BeanFactory接口的简单容器系列,实现了容器的基本功能;
另一个是ApplicationContext应用上下文,是更高级的容器,在简单容器的基础上增加了许多特性。
在这里插入图片描述
在这里插入图片描述

Bean的创建过程

  1. bean的加载流程,实际就是BeanDefiniton的注册
    (1)BeanDefinition 的加载。bean的注册实际上就是将bean定义成BeanDefiniton,随后放入Spring容器中;所谓的容器实际指的是一个Map,key代表bean的名称,value代表bean对用的BeanDefinition,这种注册Bean的方法由BeanFactory的子类去实现。
    (2)容器的初始化。

BeanDefinition继承体系
在这里插入图片描述
以下通过对BeanDefinition源码进行调试,先编写测试类

package com.yhw.controller;

import com.yhw.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringDemo {
	public static void main(String[] args) {
		ApplicationContext app = new ClassPathXmlApplicationContext("classpath:spring-config.xml");
		User user = (User) app.getBean("user");
		user.hello();
		System.out.println(user.getTeacher().getName());
	}
}

1.1 基于配置文件的BeanDefinitoin加载流程
ClassPathXmlApplicationContext
在这里插入图片描述

AbstractApplicationContext中的核心方法refresh
在这里插入图片描述
doLoadBeanDefinition
流的处理,解析成DOC文档
在这里插入图片描述
registerBeanDefinitions(返回解析配置文件的个数)

//处理doc文档
	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		// doc解析器
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		// 已经解析的BeanDefinition数量,配置文件有多个,循环一个个解析
		int countBefore = getRegistry().getBeanDefinitionCount();
		// 解析doc
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		// 返回本次解析配置文件个数
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

DefaultBeanDefinitionDocumentReader.registerBeanDefinition()

@Override
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		// 获取doc结点,入参evaluate(doc.getDocumentElement())
		doRegisterBeanDefinitions(doc.getDocumentElement());
	}

DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions()

protected void doRegisterBeanDefinitions(Element root) {
		// Any nested <beans> elements will cause recursion in this method. In
		// order to propagate and preserve <beans> default-* attributes correctly,
		// keep track of the current (parent) delegate, which may be null. Create
		// the new (child) delegate with a reference to the parent for fallback purposes,
		// then ultimately reset this.delegate back to its original (parent) reference.
		// this behavior emulates a stack of delegates without actually necessitating one.
		// beans内部定义bean,如果没定义某些信息,直接调用外部的beans
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);

		if (this.delegate.isDefaultNamespace(root)) {
			// 获取profile,spring中配置的激活环境,这里判断是否需要加载这个节点
			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());
					}
					// 环境没激活,直接返回,代表一个xml文件解析的结束
					return;
				}
			}
		}
		// 模板方法 需要一些细节处理
		preProcessXml(root);
		// 解析bean标签
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);

		this.delegate = parent;
	}

DefaultBeanDefinitionDocumentReader.parseBeanDefinitions()

	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		// 从根节点开始遍历
		// 判断是否默认
		//默认的包括<import />、<alias />、<bean /> 和 <beans />
		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;
					// 如果是默认标签,走默认标签解析方法(parseDefaultElement)
					if (delegate.isDefaultNamespace(ele)) {
						parseDefaultElement(ele, delegate);
					}
					else {
						//否则,走parseCustomElement解析方法,也就是子标签的解析
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

对子标签的解析

// 子标签的解析
	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
			// 解析外层bean一样的流程
			doRegisterBeanDefinitions(ele);
		}
	}

解析ele节点(非默认节点),默认节点一般包括bean、alias等
在这里插入图片描述

包装方法parseBeanDefinitonElement()
拿到bean的id或者name值,配置别名
在这里插入图片描述
判断beanname是否存在,并开始创建BeanDefinition

// 检测beanname是否已存在,内部用set存储beanname(id),避免重复
		if (containingBean == null) {
			checkNameUniqueness(beanName, aliases, ele);
		}

		// 创建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.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);
			// 包装一下,控制台输出类似不能为空字眼
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}

		return null;

DefaultListableBeanFactory.registerBeanDefinition(BeanDefiniton的注册)

// 根据beanname获取BeanDefinition
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		// 已存在BeanDefinition对象,
		if (existingDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				// 判断是否可覆盖
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			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 + "]");
				}
			}
			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 + "]");
				}
			}
			// BeanDefinition注册,实际将BeanDefinition存入beanDefinitionMap
			this.beanDefinitionMap.put(beanName, beanDefinition);

判断是否有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 {
				// Still in startup registration phase
				// 注册beanDefinition 也就是保存在map中
				// 至此BeanDefinition注册成功,后面都是循环注册所有xml文件中定义的bean(beans标签的解析由外到内)
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;

有别名的话绑定别名

// 创建BeanDefinition
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		// 拿到bean的名字
		String beanName = definitionHolder.getBeanName();
		// bean的注册
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				// 有别名的话绑定别名
				registry.registerAlias(beanName, alias);
			}
		}
	}

执行结束
在这里插入图片描述
1.2 基于配置类的BeanDefinition加载流程
测试Demo
在这里插入图片描述
配置类的解析同样用到refresh,最后BeanDefinition都会在refresh方法中加载到工厂中
在这里插入图片描述
在这里插入图片描述
BeanDefinition的注册

// 注册BeanDefinition
	private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {
		//直接搞了一个beanDefinition
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		// 判断是不是需要跳过,配置类是否有Condition注解,满足指定条件,则会加载对应的实例或类,写在类或方法上,例如获取window或者Linux类型
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(supplier);
		// 解析abd的scope类型
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		// 设置作用域,默认单例
		abd.setScope(scopeMetadata.getScopeName());
		// bean的名字
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
		// 解析bean的一些注解值
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		//qualifiers注解处理  我们这里为null   在注入其他bean的时候分析
		if (qualifiers != null) {
			for (Class<? extends Annotation> qualifier : qualifiers) {
				if (Primary.class == qualifier) {
					abd.setPrimary(true);
				}
				else if (Lazy.class == qualifier) {
					abd.setLazyInit(true);
				}
				else {
					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
				}
			}
		}
		// bean的个性化处理 前提时bean实现了beanDefinitionCustomizer接口
		if (customizers != null) {
			for (BeanDefinitionCustomizer customizer : customizers) {
				customizer.customize(abd);
			}
		}

		// 包装
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		// 注册BeanDefinition,就是将其放入map中,并将别名与bean的名字绑定
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

配置类与配置文件加载的区别:
在refreshBeanFactory中,设置id后直接返回beanfactory,
而xml版,在这里解析xml文件,注册beandefinition等信息
在这里插入图片描述
 

总结

BeanDefinition的加载流程
BeanDefinition 的扫描注册过程分了三个阶段:

BeanDefinition 的扫描
即从 class 类定义中扫描出 BeanDefinition

BeanDefinition 基本属性的填充
基本属性包括:@Lazy、@Primary、@DependsOn、@Role、@Description 等。

BeanDefinition 的注册
BeanDefinition 最终会注册到 BeanDefinitionRegistry 中

所以,BeanDefinition 的注册主要是将 bean 的定义从 class 类定义中扫描出来,并注册到 BeanDefinitionRegistry 中

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超级无敌暴龙战士塔塔开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值