Spring源码学习笔记1
Posted sonofthesea
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring源码学习笔记1相关的知识,希望对你有一定的参考价值。
1.Spring中最核心的两个类
1)DefaultListableBeanFactory
XmlBeanFactory继承自DefaultListableBeanFactory,DefaultListableBeanFactory是整个bean加载的核心部分,是Spring加载及注册bean的默认实现
2)XmlBeanDefinitionReader
2.示例代码
BeanFactory bf=new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));
XmlBeanFactory.class
public class XmlBeanFactory extends DefaultListableBeanFactory { private final XmlBeanDefinitionReader reader; public XmlBeanFactory(Resource resource) throws BeansException { this(resource, (BeanFactory)null); } public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader = new XmlBeanDefinitionReader(this); this.reader.loadBeanDefinitions(resource); } }
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return this.loadBeanDefinitions(new EncodedResource(resource));
}
public int loadBeanDefinitions(EncodedResource encodedResource){
....
InputSource inputSource = new InputSource(inputStream);//通过SAX方式解析XML文件
....
this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
3.配置文件的封装
Resource implements InputStreamResource
4.AbstractAutowireCapableBeanFactory.ignoreDependencyInterface()
忽略给定接口的自动装配功能
5.加载Bean
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { int validationMode = this.getValidationModeForResource(resource);//获取xml文件的验证模式 Document doc = this.documentLoader.loadDocument(inputSource, this.getEntityResolver(), this.errorHandler, validationMode, this.isNamespaceAware());//加载XML文件 return this.registerBeanDefinitions(doc, resource);//返回注册bean的信息 } catch (BeanDefinitionStoreException var5) { throw var5; } catch (SAXParseException var6) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var6.getLineNumber() + " in XML document from " + resource + " is invalid", var6); } catch (SAXException var7) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var7); } catch (ParserConfigurationException var8) { throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var8); } catch (IOException var9) { throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var9); } catch (Throwable var10) { throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var10); } }
1)获取xml文件的验证模式
getValidationModeForResource(resource);
protected int getValidationModeForResource(Resource resource) {
int validationModeToUse = this.getValidationMode();
if (validationModeToUse != 1) {
return validationModeToUse;
} else {
//如果没有设定模式则进行自动检测模式
int detectedMode = this.detectValidationMode(resource);
return detectedMode != 1 ? detectedMode : 3;
}
}
protected int detectValidationMode(Resource resource) { if (resource.isOpen()) { throw new BeanDefinitionStoreException("Passed-in Resource [" + resource + "] contains an open stream: " + "cannot determine validation mode automatically. Either pass in a Resource " + "that is able to create fresh streams, or explicitly specify the validationMode " + "on your XmlBeanDefinitionReader instance."); } else { InputStream inputStream; try { inputStream = resource.getInputStream(); } catch (IOException var5) { throw new BeanDefinitionStoreException("Unable to determine validation mode for [" + resource + "]: cannot open InputStream. " + "Did you attempt to load directly from a SAX InputSource without specifying the " + "validationMode on your XmlBeanDefinitionReader instance?", var5); } try {
//将自动检测模式委托给了XmlValidationModeDetector类
return this.validationModeDetector.detectValidationMode(inputStream);
} catch (IOException var4) {
throw new BeanDefinitionStoreException("Unable to determine validation mode for [" + resource + "]: an error occurred whilst reading from the InputStream.", var4);
}
}
}
2)加载XML文件,并得到对应的Document
委托给DocumentLoader类
EntityResolver的用法
EntityResolver的作用是项目本身就可以提供一个如何寻找DTD声明的方法,即由程序来实现寻找DTD声明的过程,比如我们将DTD文件放到项目中某处,在实现时直接将此文档读取并返回给SAX即可。这样就避免了通过网络来寻找相应的声明。
验证文件默认的加载方式是通过URL进行网络下载获取,这样会造成延迟,用户体验也不好,一般的做法都是将验证文件放在自己的工程里。
public interface EntityResolver { public abstract InputSource resolveEntity (String publicId, String systemId) throws SAXException, IOException; }
3)返回注册bean的信息
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//单一职责原则 BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader(); documentReader.setEnvironment(this.getEnvironment()); int countBefore = this.getRegistry().getBeanDefinitionCount();
//加载及注册bean documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource)); return this.getRegistry().getBeanDefinitionCount() - countBefore; }
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; this.logger.debug("Loading bean definitions"); Element root = doc.getDocumentElement(); this.doRegisterBeanDefinitions(root); }
解析并注册BeanDefinitions
protected void doRegisterBeanDefinitions(Element root) { String profileSpec = root.getAttribute("profile"); if (StringUtils.hasText(profileSpec)) { Assert.state(this.environment != null, "Environment must be set for evaluating profiles"); String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; "); if (!this.environment.acceptsProfiles(specifiedProfiles)) { return; } } BeanDefinitionParserDelegate parent = this.delegate; this.delegate = this.createHelper(this.readerContext, root, parent); this.preProcessXml(root);//模板方法模式 this.parseBeanDefinitions(root, this.delegate); this.postProcessXml(root); 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)) { this.parseDefaultElement(ele, delegate);//处理默认Bean声明 } else { delegate.parseCustomElement(ele);//处理自定义Bean声明 } } } } else { delegate.parseCustomElement(root); } }
以上是关于Spring源码学习笔记1的主要内容,如果未能解决你的问题,请参考以下文章
初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段
初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段