Spring源码学习(二)容器的基本实现
今天 圣诞节的次日 某汉的天气不错 加油 加油🦆
但晚上孝感地震 这里也有震感 希望大家都能平平安安
容器的基础 XmlBeanFactory
着重看一下这个代码的实现
String path= "spring-config.xml";
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(path));
- 了解XSD与DTD的区别,重点看文件头是否包含DOCTYPE
- xsd
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
- dtd
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "https://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
</beans>
- 了解EntityResolve,如上XSD/DTD中
- 在XSD中
publicId: null
systenId: http://www.springframework.org/schema/beans/spring-beans.xsd - 在DTD中
publicId: -//SPRING//DTD BEAN 2.0//EN
systenId: https://www.springframework.org/dtd/spring-beans-2.0.dtd
- 了解profile属性
- 作用是配置两套配置,更方便的进行切换生产环境和开发环境
//在web.xml中
<context-param>
<param-name>Spring.profle.active</param-name>
<param-value>dev</param-value>
</context-param>
配置文件封装
- 进入XmlBeanFactory()
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
- 从进入super(parentBeanFactory);再进入super()
public AbstractAutowireCapableBeanFactory() {
super();
//ignoreDependencyInterface()功能:忽略给定接口的自动装配功能
//eg:当A中有属性B,当Spring在获取A的bean的时候,如果B还没有初始化,那么Spring会自动初始化B
//某些情况下B不会自动初始化,其中一种就是B实现了BeanNameAware接口
//自动装配时忽略给定的依赖接口,典型的应用是通过其他方式解析Application上下文注册依赖,
// 类似于BeanFactory通过BeanFactoryAware进行注入或者ApplicationContext通过ApplicationContextAware进行注入
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
}
- ignoreDependencyInterface用法详见以下链接
https://www.cnblogs.com/VVII/p/12109072.html
- 进入this.reader.loadBeanDefinitions(resource);
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
//new EncodedResource(resource) 主要对编码进行处理,后续会用到
return loadBeanDefinitions(new EncodedResource(resource));
}
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
//先去掉一些不大重要的
···
···
try {
//从封装好的encodedResource中获取Resource并获取其InputStream
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
//org.xml.sax.InputSource
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//核心
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();
}
}
}
- 进入doLoadBeanDefinitions(inputSource, encodedResource.getResource());
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//加载XML文件,获取对于的Document
Document doc = doLoadDocument(inputSource, resource);
//根据返回的doc注册Bean信息
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
············
}
- 获取验证模式
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}
protected int getValidationModeForResource(Resource resource) {
int validationModeToUse = getValidationMode();
//手动指定了验证模式,就使用指定的验证模式
if (validationModeToUse != VALIDATION_AUTO) {
return validationModeToUse;
}
// 未指定则使用自动检测到的
int detectedMode = detectValidationMode(resource);
if (detectedMode != VALIDATION_AUTO) {
return detectedMode;
}
return VALIDATION_XSD;
}
- 如何判别DTD与XSD
public int detectValidationMode(InputStream inputStream) throws IOException {
// Peek into the file to look for DOCTYPE.
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
boolean isDtdValidated = false;
String content;
while ((content = reader.readLine()) != null) {
content = consumeCommentTokens(content);
if (this.inComment || !StringUtils.hasText(content)) {
continue;
}
// 包含DOCTYPE 则是DTD
if (hasDoctype(content)) {
isDtdValidated = true;
break;
}
// 读取到<开始符号,验证模式一定会在开始符号之前
if (hasOpeningTag(content)) {
// End of meaningful data...
break;
}
}
// 包含"DOCTYPE" 则是DTD,否则就是XSD,Spring是这样判别的
return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
}
catch (CharConversionException ex) {
// Choked on some character encoding...
// Leave the decision up to the caller.
return VALIDATION_AUTO;
}
finally {
reader.close();
}
}
- EntityResolver
protected EntityResolver getEntityResolver() {
if (this.entityResolver == null) {
// Determine default EntityResolver to use.
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader != null) {
this.entityResolver = new ResourceEntityResolver(resourceLoader);
}
else {
this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());
}
}
return this.entityResolver;
}
//BeansDtdResolver
@Override
@Nullable
public InputSource resolveEntity(@Nullable String publicId, @Nullable String systemId) throws IOException {
if (logger.isTraceEnabled()) {
logger.trace("Trying to resolve XML entity with public ID [" + publicId +
"] and system ID [" + systemId + "]");
}
if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {
int lastPathSeparator = systemId.lastIndexOf('/');
int dtdNameStart = systemId.indexOf(DTD_NAME, lastPathSeparator);
if (dtdNameStart != -1) {
String dtdFile = DTD_NAME + DTD_EXTENSION;
if (logger.isTraceEnabled()) {
logger.trace("Trying to locate [" + dtdFile + "] in Spring jar on classpath");
}
try {
Resource resource = new ClassPathResource(dtdFile, getClass());
InputSource source = new InputSource(resource.getInputStream());
source.setPublicId(publicId);
source.setSystemId(systemId);
if (logger.isTraceEnabled()) {
logger.trace("Found beans DTD [" + systemId + "] in classpath: " + dtdFile);
}
return source;
}
catch (FileNotFoundException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in classpath", ex);
}
}
}
}
// Fall back to the parser's default behavior.
return null;
}
//DelegatingEntityResolver
@Override
@Nullable
public InputSource resolveEntity(@Nullable String publicId, @Nullable String systemId)
throws SAXException, IOException {
if (systemId != null) {
if (systemId.endsWith(DTD_SUFFIX)) {
return this.dtdResolver.resolveEntity(publicId, systemId);
}
else if (systemId.endsWith(XSD_SUFFIX)) {
return this.schemaResolver.resolveEntity(publicId, systemId);
}
}
// Fall back to the parser's default behavior.
return null;
}
- 获取Document
@Override
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);
}
- 解析并注册Definitions
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//getRegistry() :返回BeanDefinitionRegistry
// countBefore :记录统计前BeanDefinition的个数
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
- 从 documentReader.registerBeanDefinitions(doc, createReaderContext(resource));进入
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
···················
// 空方法,留给子类实现
preProcessXml(root);
//
parseBeanDefinitions(root, this.delegate);
// 空方法,留给子类实现
postProcessXml(root);
this.delegate = parent;
}
- 进入parseBeanDefinitions()
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)) {
// 对于默认的bean解析
parseDefaultElement(ele, delegate);
}
else {
// 对于自定义的bean解析
delegate.parseCustomElement(ele);
}
}
}
}
else {
// 对于自定义的bean解析
delegate.parseCustomElement(root);
}
}
❀❀ (ง •_•)ง little little 🦆🦆 ❀❀❀❀ ♕♕♕♕♕

浙公网安备 33010602011771号