Spring源码深度解析 学习笔记(一)加载xml文件中的bean(一)

从xml加载bean

  • 前言
  • 核心类
  • 容器的基础XmlBeanFactory(已弃用)

前言

至于为什么要从老书开始,虽然有些不妥,但也有点随意的成分在,旁边有什么书就从那本开始了。XmlBeanFactory 其实已经被spring3.1开始废弃了,但是还是有东西可以学习的。之后如果博主的能力有提高,会去将最新版的核心代码整理一篇出来,与之前的做下比较。
以下基本是对源码的分析

核心类

  1. DefaultListableBeanFactory

Spring源码深度解析 学习笔记(一)加载xml文件中的bean(一)_第1张图片
先给老哥们上一张图,很复杂,各种继承实现。
以下两点明确下:

  1. 接口:定义方法,java中接口可以多继承
  2. 继承:继承父类的默认实现,无需子类再定义
  • AliasRegistry: 定义对Alias(别名)的增删改操作。
  • SimpleAliasRegistry:实现了AliasRegistry,提供了默认实现
/** Map from alias to canonical name. */
// 提供了map作为 别名的缓存
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
  • SingletonBeanRegistry:定义了注册和查询单例的方法
  • DefaultSingletonBeanRegistry:继承了SimpleAliasRegistry,实现了SingletonBeanRegistry的默认方法。继承的好处就是向上造型,并且java不支持多继承,所以为了最底层的DefaultListableBeanFactory拥有全面的功能,需要父类就开始继承,以便拥有所有相关接口的默认实现
  • FactoryBeanRegistrySupport:继承DefaultSingletonBeanRegistry,增加了对FactoryBean的特殊处理功能
  • BeanFactory:定义了获取bean和属性的方法
  • HierarchicalBeanFactory:增加了对parentFactory对支持
  • ConfigurableBeanFactory: 提供配置BeanFactory的各种方法
  • ListableBeanFactory: 根据条件获取bean的配置list
  • BeanDefinitionRegistry:继承了AliasRegistry,包含他的方法,并且定义了对BeanDefinition的增删改查的功能。
  • AbstractBeanFactory: 综合了FactoryBeanRegistrySupport和ConfigurableBeanFactory的功能。
  • AutowireCapableBeanFactory:定义了自动注入、创建bean、初始化、以及应用bean的后处理器
  • AbstractAutowireCapableBeanFactory:综合AbstractBeanFactory的功能,对AutowireCapableBeanFactory有默认实现。
  • ConfigurableListableBeanFactory:定义了“忽略依赖注入的类型和接口”的方法,bean的配置清单
  • DefaultListableBeanFactory:大杂烩,大部分都有了默认实现,主要是对bean注册后的处理。

容器的基础XmlBeanFactory(已弃用)

XmlBeanFactory bf = new XmlBeanFactory(new ClassPatchResource("test.xml"));
// 会调用到 XmlBeanFactory里面的一个构造器
public XmlBeanFactory(Resource resource) throws BeansException {
	// 再调用另一个构造器
	this(resource, null);
}
// 类里面的 reader对象,
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
	super(parentBeanFactory);
	// 使用类里面对reader对象对loadBeanDefinitions(加载Bean方法,根据资源)
	this.reader.loadBeanDefinitions(resource);
}

传入资源的时候会将资源传递给 XmlBeanDefinitionReader 去加载资源,再进入loadBeanDefinitions

@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
	// 传入 EncodedResource 对象是想判断是否有 编码 的要求
	return loadBeanDefinitions(new EncodedResource(resource));
}

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
	// 断言 encodedResource 不能为 null
	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();
	if (currentResources == null) {
		// 没有则创建
		currentResources = new HashSet<>(4);
		this.resourcesCurrentlyBeingLoaded.set(currentResources);
	}
	if (!currentResources.add(encodedResource)) {
		throw new BeanDefinitionStoreException(
				"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
	}
	try {
		// 得到resource里面的inputStream流
		InputStream inputStream = encodedResource.getResource().getInputStream();
		try {
			// 构造InputSource。 A single input source for an XML entity.
			InputSource inputSource = new InputSource(inputStream);
			// 如果存在编码要求,则会对inputSource进行设置。
			if (encodedResource.getEncoding() != null) {
				inputSource.setEncoding(encodedResource.getEncoding());
			}
			// 传入inputSource (含有 resource 的输入流(inputStream)) 和  封装在encodedResource中的resource
			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()) {
			this.resourcesCurrentlyBeingLoaded.remove();
		}
	}
}

上面做了一些准备工作,对resource资源的封装。
doLoadBeanDefinitions 才是去做加载工作

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
		throws BeanDefinitionStoreException {
	try {
		// 验证xml文件流的格式,并转换成 document 对象
		Document doc = doLoadDocument(inputSource, resource);
		// 解析并注册 beanDefinition
		int count = registerBeanDefinitions(doc, resource);
		if (logger.isDebugEnabled()) {
			logger.debug("Loaded " + count + " bean definitions from " + resource);
		}
		return count;
	} catch(Exception e) {
		// 省略捕捉的异常
		...
	}
}

// 根据得到xml文件解析成 Document 对象
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
	// inputSource: xml文件的输入流
	// getEntityResolver: 判断xml文件需要 dtd 还是 xsd 验证文件的获取方式
	// errorHandler: 错误日志一类
	// getValidationModeForResource 获取 dtd 或者 xsd 的验证模型
	// isNamespaceAware:XML解析器是否应该支持XML命名空间
	return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
			getValidationModeForResource(resource), isNamespaceAware());
}

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
	// 创建默认的documentReader,DefaultBeanDefinitionDocumentReader
	BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
	// 得到现有的beanDefinition个数
	int countBefore = getRegistry().getBeanDefinitionCount();
	// 将解析doc对象的工作委派给documentReader来完成,这里默认的是DefaultBeanDefinitionDocumentReader 类
	documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
	return getRegistry().getBeanDefinitionCount() - countBefore;
}

@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
	this.readerContext = readerContext;
	// 解析并注册 beanDefinition
	doRegisterBeanDefinitions(doc.getDocumentElement());
}

protected void doRegisterBeanDefinitions(Element root) {
	BeanDefinitionParserDelegate parent = this.delegate;
	this.delegate = createDelegate(getReaderContext(), root, parent);
	// profile 解析,这里的profile是指环境设置,类似dev、pro,开发环境和生产环境
	if (this.delegate.isDefaultNamespace(root)) {
		// 在root节点得到 profile 属性
		String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
		if (StringUtils.hasText(profileSpec)) {
			String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
					profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			// 对环境参数设置 profile参数
			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;
			}
		}
	}
	// 设计模式中的模版方法 ,hook 钩子
	preProcessXml(root);
	// 解析xml中的节点
	parseBeanDefinitions(root, this.delegate);
	postProcessXml(root);
	this.delegate = parent;
}

// 解析xml中的节点
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);
	}
}

// 解析默认命名空间,元素的类型
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
	// 默认解析 4种ele
	// 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);
	}
}

你可能感兴趣的:(spring)