前言
这一章是就上一章的一个拓展说明,对通过文件输入流来分析spring是如何对xml配置文件来进行解析的!
核心代码
//获取输入流,这是7的代码特性,InputStream实现了Closeable接口,不必手动关闭流
try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
//sax解析
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
//将显式设置的编码设置进去
inputSource.setEncoding(encodedResource.getEncoding());
}
//do开头的方法是spring内部调用的方法不希望被外界所使用
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
//不调用会产生内存泄漏
this.resourcesCurrentlyBeingLoaded.remove();
}
}
首先看doLoadBeanDefinitions的方法
//doc获取到的文档对象
Document doc = doLoadDocument(inputSource, resource);
//完成解析
int count = registerBeanDefinitions(doc, resource);
下面是一堆异常catch我就不贴了,这里面这个方法返回的是读取bean的个数,在这里吗又有两个核心的方法doLoadDocument和registerBeanDefinitions
doLoadDocument流程解析
/**
* 使用配置的DocumentLoader实际加载指定的文档。
* Actually load the specified document using the configured DocumentLoader.
* @param inputSource the SAX InputSource to read from
* @param resource the resource descriptor for the XML file
* @return the DOM Document
* @throws Exception when thrown from the DocumentLoader
* @see #setDocumentLoader
* @see DocumentLoader#loadDocument
*/
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}
isNamespaceAware:返回XML解析器是否应了解XML名称空间。
documentLoader是什么?
private DocumentLoader documentLoader = new DefaultDocumentLoader();
loadDocument方法:
@Override
//完成对doc文档的读取
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);
}
然后把当前对象的document对象给返回回去!
registerBeanDefinitions解析
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//获取到解析之前的定义在bean工厂下面的bean的数量
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//现在解析完的减去已经解析过得,防止配置文件中有相互引用的问题,会导致再次引用!
return getRegistry().getBeanDefinitionCount() - countBefore;
}
首先我们看createBeanDefinitionDocumentReader:
在进入
主要是使用了Java反射的机制
/**
* 使用给定构造函数实例化类的便捷方法。
* 请注意,如果给定了不可访问的(即非公共的)构造函数,则此方法尝试将构造函数设置为可访问,
* 并支持带有可选参数和默认值的Kotlin类。
*
* Convenience method to instantiate a class using the given constructor.
* <p>Note that this method tries to set the constructor accessible if given a
* non-accessible (that is, non-public) constructor, and supports Kotlin classes
* with optional parameters and default values.
* @param ctor the constructor to instantiate
* @param args the constructor arguments to apply (use {@code null} for an unspecified
* parameter, Kotlin optional parameters and Java primitive types are supported)
* @return the new instance
* @throws BeanInstantiationException if the bean cannot be instantiated
* @see Constructor#newInstance
*/
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
//爆破访问
ReflectionUtils.makeAccessible(ctor);
//Kotlin判断
if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
return KotlinDelegate.instantiateClass(ctor, args);
}
//java类走下面判断
else {
Class<?>[] parameterTypes = ctor.getParameterTypes();
Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
Object[] argsWithDefaultValues = new Object[args.length];
for (int i = 0 ; i < args.length; i++) {
if (args[i] == null) {
Class<?> parameterType = parameterTypes[i];
argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
}
else {
argsWithDefaultValues[i] = args[i];
}
}
//获取对象实例
return ctor.newInstance(argsWithDefaultValues);
}
}
catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/16383.html