Spring-IoC注入过程

7 篇文章 0 订阅
6 篇文章 0 订阅
本文基于spring5.1.6

一、大体流程

  1. 使用ResourceLoader加载资源
  2. 创建Bean工厂
  3. 获得BeanDefinition
  4. 装载资源
    资源定位、装载、注册
    装载。装载就是 BeanDefinition 的载入
//加载资源
ClassPathResource resource = new ClassPathResource("bean.xml");
//创建bean工厂
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//xml解析器
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
//装载资源
reader.loadBeanDefinitions(resource);

不理解资源解析的请参考Spring-Resource源码解析

1.1 new XmlBeanDefinitionReader(factory)其实是调用的父类的构造方法

关系

public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader,EnvironmentCapable
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader

关系图

1.2AbstractBeanDefinitionReader

  1. 创建对象就是初始化资源加载器和环境的过程
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	this.registry = registry;

	// 确定加载器如果BeanDefinitionRegistry是一个资源加载器,那么就使用它作为加载器,否则使用路径匹配加载器
	if (this.registry instanceof ResourceLoader) {
		this.resourceLoader = (ResourceLoader) this.registry;
	}
	else {
		this.resourceLoader = new PathMatchingResourcePatternResolver();
	}

	//EnvironmentCapable:Spring中所有的应用上下文类都实现了此接口。这个接口的主要作用是用于类型检查的
	if (this.registry instanceof EnvironmentCapable) {
		this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
	}
	else {
		this.environment = new StandardEnvironment();
	}
}

环境类Environment

/**
*	环境的一些参数
*/
public interface Environment extends PropertyResolver {
	//获取激活的配置
	String[] getActiveProfiles();
	//默认的配置
	String[] getDefaultProfiles();
	//废弃的方法通过字符串的配置判断是否可以使用该配置
	@Deprecated
	boolean acceptsProfiles(String... profiles);
	//通过Profiles对象判断是否可以使用该配置
	boolean acceptsProfiles(Profiles profiles);

}

public interface PropertyResolver {

	boolean containsProperty(String key);
	//获取参数
	@Nullable
	String getProperty(String key);
	//获取参数,如果为空,返回默认值
	String getProperty(String key, String defaultValue);
	//返回指定的对象的字节码对象
	@Nullable
	<T> T getProperty(String key, Class<T> targetType);
	//返回指定的对象的字节码类,如果为空返回默认值
	<T> T getProperty(String key, Class<T> targetType, T defaultValue);
	//获取要求的参数
	String getRequiredProperty(String key) throws IllegalStateException;
	//获取要求的参数的对象的字节码对象
	<T> T getRequiredProperty(String key, Class<T> targetType) throws IllegalStateException;
	//解析占位符
	String resolvePlaceholders(String text);
	//解析要求的占位符
	String resolveRequiredPlaceholders(String text) throws IllegalArgumentException;

}

1.3加载过程

loadBeanDefinitions会将资源进行编码,然后执行的是下面的代码

将encodedResource放入Set,去重
将encodedResource转成流并且将Resource对象传入doLoadBeanDefinitions,详见1.4源码

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
	Assert.notNull(encodedResource, "EncodedResource must not be null");
	if (logger.isTraceEnabled()) {
		logger.trace("Loading XML bean definitions from " + encodedResource);
	}
	//resourcesCurrentlyBeingLoaded是一个ThreadLocal对象
	Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
	//如果是空的,那么就初始化一个set
	if (currentResources == null) {
		currentResources = new HashSet<>(4);
		this.resourcesCurrentlyBeingLoaded.set(currentResources);
	}
	//如果set集合添加不进去,那么抛出异常,说明已经加载过了,防止重复加载
	if (!currentResources.add(encodedResource)) {
		throw new BeanDefinitionStoreException(
				"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
	}
	try {
		//转换成流
		InputStream inputStream = encodedResource.getResource().getInputStream();
		try {
			InputSource inputSource = new InputSource(inputStream);
			if (encodedResource.getEncoding() != null) {
				//设置编码
				inputSource.setEncoding(encodedResource.getEncoding());
			}
			//见下方源码1.4
			return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
		}
		finally {
			inputStream.close();
		}
	}
	catch (IOException ex) {
		throw new BeanDefinitionStoreException(
				"IOException parsing XML document from " + encodedResource.getResource(), ex);
	}
	finally {
		currentResources.remove(encodedResource);
		if (currentResources.isEmpty()) {
			//ThreadLocal必须要remove掉,防止线程池下的线程复用
			this.resourcesCurrentlyBeingLoaded.remove();
		}
	}
}

1.4doLoadBeanDefinitions方法

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

	try {
		//获取Document 实例
		Document doc = doLoadDocument(inputSource, resource);
		//注册到ioc容器中详见1.5
		int count = registerBeanDefinitions(doc, resource);
		if (logger.isDebugEnabled()) {
			logger.debug("Loaded " + count + " bean definitions from " + resource);
		}
		return count;
	}
	catch (BeanDefinitionStoreException ex) {
		throw ex;
	}
	catch (SAXParseException ex) {
		throw new XmlBeanDefinitionStoreException(resource.getDescription(),
				"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
	}
	catch (SAXException ex) {
		throw new XmlBeanDefinitionStoreException(resource.getDescription(),
				"XML document from " + resource + " is invalid", ex);
	}
	catch (ParserConfigurationException ex) {
		throw new BeanDefinitionStoreException(resource.getDescription(),
				"Parser configuration exception parsing XML from " + resource, ex);
	}
	catch (IOException ex) {
		throw new BeanDefinitionStoreException(resource.getDescription(),
				"IOException parsing XML document from " + resource, ex);
	}
	catch (Throwable ex) {
		throw new BeanDefinitionStoreException(resource.getDescription(),
				"Unexpected exception parsing XML document from " + resource, ex);
	}
}

1.5 registerBeanDefinitions

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
	//利用反射创建对象详见1。6
	BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
	//registry是不是有点眼熟XmlBeanDefinitionReader extends AbstractBeanDefinitionReader
	//在创建XmlBeanDefinitionReader的时候初始化了registry和environment
	//也就是DefaultListableBeanFactory 
	//获取容器总数量
	int countBefore = getRegistry().getBeanDefinitionCount();
	//将Resource包装成XmlReaderContext详见1.7
	documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
	//返回成功的个数beanDefinitionMap新增的数量
	return getRegistry().getBeanDefinitionCount() - countBefore;
}

1.6 instantiateClass

public static <T> T instantiateClass(Class<T> clazz) throws BeanInstantiationException {
	Assert.notNull(clazz, "Class must not be null");
	//如果是接口,抛出异常
	if (clazz.isInterface()) {
		throw new BeanInstantiationException(clazz, "Specified class is an interface");
	}
	try {
		//如果不是接口,根据反射实例化对象
		return instantiateClass(clazz.getDeclaredConstructor());
	}
	catch (NoSuchMethodException ex) {
		Constructor<T> ctor = findPrimaryConstructor(clazz);
		if (ctor != null) {
			return instantiateClass(ctor);
		}
		throw new BeanInstantiationException(clazz, "No default constructor found", ex);
	}
	catch (LinkageError err) {
		throw new BeanInstantiationException(clazz, "Unresolvable class definition", err);
	}
}

1.7registerBeanDefinitions

@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
	this.readerContext = readerContext;
	//详见1.8
	doRegisterBeanDefinitions(doc.getDocumentElement());
}

1.8doRegisterBeanDefinitions

@SuppressWarnings("deprecation")  // for Environment.acceptsProfiles(String...)
protected void doRegisterBeanDefinitions(Element root) {
	//解析器
	BeanDefinitionParserDelegate parent = this.delegate;
	//this.delegate重新指向新的delegate
	this.delegate = createDelegate(getReaderContext(), root, parent);
	//根节点是否为默认的命名空间,node.getNamespaceURI()为空
	//或者为BeanDefinitionParserDelegate.BEANS_NAMESPACE_URI
	//"http://www.springframework.org/schema/beans"
	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);
			// 如果这个配置不合法
			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);
	//解析BeanDefinitions,详见1.9parseBeanDefinitions
	parseBeanDefinitions(root, this.delegate);
	//什么都没做,需要子类来实现
	postProcessXml(root);

	this.delegate = parent;
}

1.9parseBeanDefinitions

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)) {
					//处理默认的元素
					parseDefaultElement(ele, delegate);
				}
				else {
					//处理自定义的元素
					delegate.parseCustomElement(ele);
				}
			}
		}
	}
	else {
		//处理自定义的元素
		delegate.parseCustomElement(root);
	}
}

2.0 parseDefaultElement处理默认的元素

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)) {
		//2.2processBeanDefinition
		processBeanDefinition(ele, delegate);
	}
	//beans标签
	else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
		//调用1.9的方法继续往下解析即解析bean
		doRegisterBeanDefinitions(ele);
	}
}

2.1parseCustomElement处理客户自定义的元素

@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
	String namespaceUri = getNamespaceURI(ele);
	if (namespaceUri == null) {
		return null;
	}
	NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
	if (handler == null) {
		error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
		return null;
	}
	return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

2.2 processBeanDefinition

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	//解析ele并且将bean封装到BeanDefinitionHolder
	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
	//如果不为空
	if (bdHolder != null) {
		//获取属性
		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
		try {
			// 注册到IOC容器
			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));
	}
}

2.3parseBeanDefinitionElement 从xml中解析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)) {
		//将name属性值进行分割放入aliases中
		String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
		aliases.addAll(Arrays.asList(nameArr));
	}
	//将id作为beanName,也就是说,id优先级最高
	String beanName = id;
	//id不存在的时候
	if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
		//是否真的有值,把aliases的第一个元素放进来,那么把name作为beanname
		beanName = aliases.remove(0);
		if (logger.isTraceEnabled()) {
			logger.trace("No XML 'id' specified - using '" + beanName +
					"' as bean name and " + aliases + " as aliases");
		}
	}

	if (containingBean == null) {
		//检查是否唯一如果存在抛出异常,如果不存在那么缓存起来
		checkNameUniqueness(beanName, aliases, ele);
	}
	//获取beanDefinition
	AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
	if (beanDefinition != null) {
		//如果别名和id都为空的情况
		if (!StringUtils.hasText(beanName)) {
			try {
				//如果不为空的情况下获取beanName
				if (containingBean != null) {
					beanName = BeanDefinitionReaderUtils.generateBeanName(
							beanDefinition, this.readerContext.getRegistry(), true);
				}
				else {
					//根据上下文生成beanName
					beanName = this.readerContext.generateBeanName(beanDefinition);
					// 获取真正的java类名
					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;
}

2.4registerBeanDefinition

public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

	// 获取bean名称
	String beanName = definitionHolder.getBeanName();
	//注册到IOC容器中
	registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
	//注册别名
	String[] aliases = definitionHolder.getAliases();
	if (aliases != null) {
		for (String alias : aliases) {
			registry.registerAlias(beanName, alias);
		}
	}
}

2.5 registerBeanDefinition

@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);
		}
	}
	//通过Map查询是否存在BeanDefinition
	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
	//如果存在
	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 + "]");
			}
		}
		//如果不存在BeanDefinition
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("Overriding bean definition for bean '" + beanName +
						"' with an equivalent definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		//注册进去IOC容器
		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<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
				updatedDefinitions.addAll(this.beanDefinitionNames);
				updatedDefinitions.add(beanName);
				this.beanDefinitionNames = updatedDefinitions;
				if (this.manualSingletonNames.contains(beanName)) {
					Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
					updatedSingletons.remove(beanName);
					this.manualSingletonNames = updatedSingletons;
				}
			}
		}
		else {
			// Still in startup registration phase
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			this.manualSingletonNames.remove(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

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

小结

1. 将Resource转成EncodedResource设置编码
2. 通过Resource和Resource的流获取Document
3. 通过命名空间(BEANS_NAMESPACE_URI = “http://www.springframework.org/schema/beans”;)判断是否是用户自定义的xml,然后解析不同的xml(我们这里只分析默认的)
4. 根据标签解析xml,spring解析import、alias、bean、beans
5. 解析bean标签、将Element对象封装成BeanDefinitionHolder
6. 将beanName作为key,BeanDefinition作为value保存到beanDefinitionMap中
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值