The loading phase of beandefinition (XML file)

Full moon acridine 2021-02-23 17:48:36
loading phase beandefinition xml file


This series of articles is my study Spring In the process of summing up , Which involves the relevant source code , May not be very friendly to readers , Please combine with my source code comments Spring Source code analysis GitHub Address To read

Spring edition :5.1.14.RELEASE

Before you start reading this series of articles , It is recommended to check it first 《 Deepen understanding Spring IoC( Interview questions )》 This article

For other articles in the series, check out :《 screwing Spring And IoC piece - Article reading guidance 》

BeanDefinition Loading phase of (XML file )

Last article 《Bean Of “ The predecessor ”》 Yes BeanDefinition Introduced ,Bean It's based on BeanDefinition Configuration meta information object generated . We are Spring We usually define a in these two ways Bean: Resources oriented (XML、Properties) Annotation oriented , that Spring How to translate the information defined in these two ways into BeanDefinition Object's , Next, we will analyze Resources oriented (XML、Properties) This way, Spring How is it handled

Get familiar with a piece of code :

dependency-lookup-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- <context:component-scan base-package="org.geekbang.thinking.in.spring.ioc.overview" /> -->
<bean id="user" class="org.geekbang.thinking.in.spring.ioc.overview.domain.User">
<property name="id" value="1"/>
<property name="name" value=" Little horse elder brother "/>
</bean>
</beans>
// establish BeanFactory Containers
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
// XML The configuration file ClassPath route
String location = "classpath:/META-INF/dependency-lookup-context.xml";
// Load the configuration
int beanDefinitionsCount = reader.loadBeanDefinitions(location);
System.out.println("Bean Define the number of loads :" + beanDefinitionsCount);
// Dependency lookup
System.out.println(beanFactory.getBean("user"));;

This code is Spring The program uses IoC Containers , We can see IoC The process of using the container is as follows :

  1. establish BeanFactory object ( Bottom IoC Containers )
  2. establish BeanDefinitionReader object ( Resource resolver ), Related to chapter 1 Step created BeanFactory
  3. adopt BeanDefinitionReader load XML Profile resources , Parse out all of BeanDefinition object
  4. Do dependency lookup

The above first 3 The next step is to analyze Resource resources , take XML Defined in the file Bean It can be interpreted as BeanDefinition Configure meta information objects , Go together BeanDefinitionRegistry Registry registration , At this point, no corresponding Bean object , We need to get... Through dependency search Bean. Of course , We don't usually use this in real scenes Spring, All these jobs will have Spring To complete . Let's take a look at Sping How to load XML Of documents

BeanDefinitionReader Architecture

org.springframework.beans.factory.support.BeanDefinitionReader The class diagram of the interface is as follows :

The overview :

  • org.springframework.beans.factory.support.BeanDefinitionReader Interface ,BeanDefinition Reader

  • org.springframework.beans.factory.support.AbstractBeanDefinitionReader abstract class , Provides a common implementation , The specific resource loading logic is implemented by subclasses

  • org.springframework.beans.factory.xml.XmlBeanDefinitionReader,XML File resource parser , It is concluded that BeanDefinition Configure the meta information object and register

  • org.springframework.beans.factory.support.PropertiesBeanDefinitionReader,Properties File resource parser

BeanDefinitionReader Interface

org.springframework.beans.factory.support.BeanDefinitionReader Interface ,BeanDefinition Reader , The method of loading resources is defined , The code is as follows :

public interface BeanDefinitionReader {
/** return BeanDefinition Registry Center */
BeanDefinitionRegistry getRegistry();
/** return Resource Resource loader , The default is PathMatchingResourcePatternResolver */
@Nullable
ResourceLoader getResourceLoader();
/** Returns the class loader */
@Nullable
ClassLoader getBeanClassLoader();
/** return Bean Name generator for , The default is DefaultBeanNameGenerator */
BeanNameGenerator getBeanNameGenerator();
/** from Resource Resources BeanDefinition And return the quantity */
int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException;
int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException;
int loadBeanDefinitions(String location) throws BeanDefinitionStoreException;
int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException;
}

AbstractBeanDefinitionReader abstract class

org.springframework.beans.factory.support.AbstractBeanDefinitionReader abstract class , Realized BeanDefinitionReader and EnvironmentCapable Interface , The code is as follows :

public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
private final BeanDefinitionRegistry registry;
@Nullable
private ResourceLoader resourceLoader;
@Nullable
private ClassLoader beanClassLoader;
private Environment environment;
private BeanNameGenerator beanNameGenerator = new DefaultBeanNameGenerator();
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
// Determine ResourceLoader to use.
if (this.registry instanceof ResourceLoader) {
this.resourceLoader = (ResourceLoader) this.registry;
}
else {
this.resourceLoader = new PathMatchingResourcePatternResolver();
}
// Inherit Environment if possible
if (this.registry instanceof EnvironmentCapable) {
this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
}
else {
this.environment = new StandardEnvironment();
}
}
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int count = 0;
for (Resource resource : resources) {
count += loadBeanDefinitions(resource);
}
return count;
}
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
// get ResourceLoader object
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
// get Resource Array , because Pattern Pattern matching , There may be more than one Resource . For example, ,Ant Style location
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
// load BeanDefinition People
int count = loadBeanDefinitions(resources);
if (actualResources != null) {
// Add to actualResources in
Collections.addAll(actualResources, resources);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
}
return count;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
// get Resource object
Resource resource = resourceLoader.getResource(location);
// load BeanDefinition People
int count = loadBeanDefinitions(resource);
if (actualResources != null) {
// Add to actualResources in
actualResources.add(resource);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
}
return count;
}
}
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int count = 0;
for (String location : locations) {
count += loadBeanDefinitions(location);
}
return count;
}
// ... Omit the relevant code
}

In the implementation method , Will eventually call int loadBeanDefinitions(Resource resource) This method , This method is implemented in subclasses

XmlBeanDefinitionReader

org.springframework.beans.factory.xml.XmlBeanDefinitionReader,XML File resource parser , It is concluded that BeanDefinition Configure the meta information object and register

Constructors

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
/**
* Disable authentication mode
*/
public static final int VALIDATION_NONE = XmlValidationModeDetector.VALIDATION_NONE;
/**
* Automatically get validation mode
*/
public static final int VALIDATION_AUTO = XmlValidationModeDetector.VALIDATION_AUTO;
/**
* DTD Verification mode
*/
public static final int VALIDATION_DTD = XmlValidationModeDetector.VALIDATION_DTD;
/**
* XSD Verification mode
*/
public static final int VALIDATION_XSD = XmlValidationModeDetector.VALIDATION_XSD;
/** Constants instance for this class. */
private static final Constants constants = new Constants(XmlBeanDefinitionReader.class);
/**
* Verification mode , The default is automatic mode .
*/
private int validationMode = VALIDATION_AUTO;
private boolean namespaceAware = false;
private Class<? extends BeanDefinitionDocumentReader> documentReaderClass = DefaultBeanDefinitionDocumentReader.class;
/**
* Exception handling during parsing
*/
private ProblemReporter problemReporter = new FailFastProblemReporter();
private ReaderEventListener eventListener = new EmptyReaderEventListener();
private SourceExtractor sourceExtractor = new NullSourceExtractor();
@Nullable
private NamespaceHandlerResolver namespaceHandlerResolver;
private DocumentLoader documentLoader = new DefaultDocumentLoader();
@Nullable
private EntityResolver entityResolver;
private ErrorHandler errorHandler = new SimpleSaxErrorHandler(logger);
/**
* XML Verification mode detector
*/
private final XmlValidationModeDetector validationModeDetector = new XmlValidationModeDetector();
/**
* Current thread , Loading EncodedResource aggregate .
*/
private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded = new NamedThreadLocal<>(
"XML bean definition resources currently being loaded");
/**
* Create new XmlBeanDefinitionReader for the given bean factory.
* @param registry the BeanFactory to load bean definitions into,
* in the form of a BeanDefinitionRegistry
*/
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
super(registry);
}
}

loadBeanDefinitions Method

loadBeanDefinitions(Resource resource) Method , analysis Resource Access to resources , The method is as follows :

@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
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);
}
// <1> Gets the Resource Resource collection , Add current Resource, Prevent duplicate loading
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) { // Add the current resource to the record . If it already exists , Throw an exception , Prevent loops from loading the same resource
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
// <2> from Resource The resource acquisition InputStream Stream object ( Support coding )
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// <3> 【 The core 】 Execute load Resource Resource process , It is concluded that BeanDefinition To register
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
} finally {
// Closed flow
inputStream.close();
}
} catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
} finally {
// <4> Removes the currently loaded... From the current thread Resource object
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}

take Resource Encapsulated into EncodedResource object , The goal is to make the resource object settable encoding

  1. Gets the Resource Resource collection , Add current Resource, Prevent duplicate loading
  2. from Resource The resource acquisition InputStream Stream object ( Support coding )
  3. 【 The core 】 call doLoadBeanDefinitions(InputSource inputSource, Resource resource) Method , Execute load Resource Resource process , It is concluded that BeanDefinition To register
  4. Removes the currently loaded... From the current thread Resource object

doLoadBeanDefinitions Method

doLoadBeanDefinitions(InputSource inputSource, Resource resource) Method , Execute load Resource Resource process , It is concluded that BeanDefinition To register , The method is as follows :

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// <1> obtain XML Document example
Document doc = doLoadDocument(inputSource, resource);
// <2> according to Document example , It is concluded that BeanDefinition We need to register , Return the number of registrations
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
// Omit catch Various anomalies
}
  1. call doLoadDocument(InputSource inputSource, Resource resource) Method , obtain XML Document example
  2. call registerBeanDefinitions(Document doc, Resource resource) Method , according to Document example , It is concluded that BeanDefinition We need to register , Return the number of registrations

doLoadDocument Method

doLoadDocument(InputSource inputSource, Resource resource) Method , obtain Resource Resources correspond to XML Document example , The method is as follows :

protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
// <3> adopt DefaultDocumentLoader according to Resource Get one Document object
return this.documentLoader.loadDocument(inputSource,
getEntityResolver(), // <1> obtain `org.xml.sax.EntityResolver` Entity Resolver ,ResourceEntityResolver
this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware()); // <2> obtain XML File validation mode , Guarantee XML The correctness of the document
}
  1. obtain org.xml.sax.EntityResolver Entity Resolver ,ResourceEntityResolver, according to publicId and systemId Get the corresponding DTD or XSD file , Used to deal with XML Document validation , This class compares The key , I'll talk about it later
  2. obtain XML File validation mode , Guarantee XML The correctness of the document , Usually XSD Pattern
    1. Gets the specified authentication mode , If specified manually , Then return directly , Usually not
    2. from Resource Get validation patterns from resources , according to XML Get the content of the file , If you include DOCTYPE The content is DTD Pattern , Otherwise XSD Pattern
    3. If the verification pattern has not been obtained yet , The default is XSD Pattern
  3. adopt DefaultDocumentLoader according to Resource Get one Document object
    1. establish DocumentBuilderFactory object factory, Turn on verification
    2. according to factory establish DocumentBuilder object builder, Set up EntityResolver( The first 1 Step created )、ErrorHandler attribute
    3. adopt builder Yes inputSource(Resource resources ) To analyze , Return to one Document object

The purpose of the above process is to obtain Resource Resources correspond to Document object , Need to go through two processes of verification and Analysis

registerBeanDefinitions Method

registerBeanDefinitions(Document doc, Resource resource) Method , according to Document example , It is concluded that BeanDefinition We need to register , Return the number of registrations , The method is as follows :

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// <1> establish BeanDefinitionDocumentReader object
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// <2> Get registered BeanDefinition Number
int countBefore = getRegistry().getBeanDefinitionCount();
// <3> establish XmlReaderContext object ( Read Resource The context object of the resource )
// <4> according to Document、XmlReaderContext Parse out all of BeanDefinition And register
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// <5> Calculate newly registered BeanDefinition Number
return getRegistry().getBeanDefinitionCount() - countBefore;
}
  1. establish DefaultBeanDefinitionDocumentReader object documentReader
  2. Get registered BeanDefinition Number
  3. establish XmlReaderContext object ( Read Resource The context object of the resource ), Notice that this initializes a DefaultNamespaceHandlerResolver object , Used to handle custom tags (XML file ), Compare The key , stay Subsequent articles I'll talk about
  4. according to Document、XmlReaderContext Parse out all of BeanDefinition And register , call DefaultBeanDefinitionDocumentReader#registerBeanDefinitions(Document doc, XmlReaderContext readerContext) Method
  5. Calculate newly registered BeanDefinition Quantity and return

expand :DTD And XSD The difference between ?

DTD(Document Type Definition), Document type definition , by XML Verification mechanism of documents , Belong to XML Part of the document .DTD It's a guarantee XML An effective way to verify that the document format is correct , It defines the relevant XML The elements of the document 、 attribute 、 arrangement 、 The content type of the element and the hierarchy of the element . Actually DTD Equivalent to XML Medium “ vocabulary ” and “ grammar ”, We can compare XML Document and DTD file See if the document meets the specifications , Are elements and labels used correctly .

DTD At a certain stage, it promotes XML The development of , But there are some in it defects

  1. It's not used XML Format , It's about defining a format , The reusability of parser is poor ; and DTD There is no standard programming interface for building and accessing , This makes it difficult for the parser to parse simply DTD file
  2. DTD Less restrictions on the type of elements ; At the same time, other binding forces are also relatively weak
  3. DTD Poor scalability
  4. Based on regular expressions DTD The description ability of documents is limited

XSD(XML Schemas Definition), namely XML Schema Language , in the light of DTD The defects of the system are caused by W3C stay 2001 Launched in 2013 .XML Schema Is itself a XML file , It uses XML grammar , So it's easy to parse XSD file . be relative to DTD,XSD With the following advantage

  1. XML Schema be based on XML, There is no special grammar
  2. XML Schema Can be like other XML File like parsing and processing
  3. XML Schema Than DTD Provides a richer data type
  4. XML Schema Provide extensible data model
  5. XML Schema Support for comprehensive namespace
  6. XML Schema Support property groups

summary

We are Spring We usually define a in these two ways Bean: Resources oriented (XML、Properties) Annotation oriented , For the first way, if you define a XML file ,Spring Will pass XmlBeanDefinitionReader Load the XML file , Get the Resource Resources org.w3c.dom.Document object , This process will be verified 、 There are two steps to parsing

版权声明
本文为[Full moon acridine]所创,转载请带上原文链接,感谢
https://javamana.com/2021/02/20210223174634713j.html

  1. 开源办公开发平台丨Mysql5.7两套四节点主从结构环境搭建教程(二)
  2. 开源办公开发平台丨Mysql5.7两套四节点主从结构环境搭建教程(一)
  3. Open source office development platform mysql5.7 two sets of four node master-slave structure environment building tutorial (2)
  4. HTTP的“无状态”和REST的“状态转换”
  5. Open source office development platform mysql5.7 two sets of four node master-slave structure environment building tutorial (1)
  6. 【大数据哔哔集20210128】使用Hive计算环比和同比
  7. 【大数据哔哔集20210125】Kafka将逐步弃用对zookeeper的依赖
  8. 【大数据哔哔集20210124】有人问我Kafka Leader选举?我真没慌
  9. 【大数据哔哔集20210123】别问,问就是Kafka高可靠
  10. Spring 事务、异步和循环依赖有什么关系?
  11. Spring 动态代理时是如何解决循环依赖的?为什么要使用三级缓存?
  12. "Stateless" of HTTP and "state transition" of rest
  13. [big data bibiji 20210128] use hive to calculate month on month and year on year
  14. [big data bibiji 20210125] Kafka will gradually abandon its dependence on zookeeper
  15. [big data beeps 20210124] someone asked me about Kafka leader election? I'm not in a panic
  16. [big data bibiji 20210123] don't ask, ask is Kafka highly reliable
  17. jQuery Gantt Package 在Visual Studio中创建一个新的ASP.NET项目
  18. What is the relationship between spring transactions, asynchrony, and circular dependencies?
  19. How to solve circular dependency in spring dynamic proxy? Why use level 3 caching?
  20. Unicode码的二进制转换(Java)
  21. JAVA的函数式接口
  22. JAVA里的元祖类
  23. JQuery Gantt package to create a new ASP.NET project
  24. Binary conversion of Unicode code (Java)
  25. The functional interface of Java
  26. Yuanzu class in Java
  27. Java中的CPU占用高和内存占用高的问题排查
  28. HashMap连环问你能答出几道?
  29. IntelliJ IDEA 还能画思维导图,果然最强 IDE!
  30. java中的反射和代理
  31. Troubleshooting of high CPU and memory usage in Java
  32. How many questions can you answer?
  33. IntelliJ idea can also draw mind maps. It's really the strongest ide!
  34. Reflection and proxy in Java
  35. Java中的CPU占用高和内存占用高的问题排查
  36. Linux OOM(out of memory)
  37. mysql 自定义函数因参数名称报错
  38. Troubleshooting of high CPU and memory usage in Java
  39. Linux OOM(out of memory)
  40. MySQL user defined function error due to parameter name
  41. echarts-gl 3D 地图柱状图可视化GDP
  42. Visualization of histogram of ecarts GL 3D map
  43. 金三银四如何应对Redis面试,一文深入Redis实战实践!
  44. 阿里资深架构师定制金三银四面试整理出来的一份Java核心知识点.pdf
  45. 为什么Java开发工程师工资高,却很多人想转行?
  46. How to deal with the interview of redis!
  47. Ali senior architect customizes a Java core knowledge point sorted out in the interview of golden, silver and four.pdf
  48. Why do java development engineers have high salaries, but many people want to change careers?
  49. 用注解开发SpringMVC
  50. Developing spring MVC with annotations
  51. 编译redis报错/deps/hiredis/libhiredis.a解决
  52. Compile redis report error / DEPs / hirredis / libhirredis. A solution
  53. 用注解开发SpringMVC
  54. Developing spring MVC with annotations
  55. Spring学习笔记-01
  56. Centos安装和卸载docker
  57. Spring learning notes-01
  58. Installing and uninstalling docker in CentOS
  59. Java基础-异常
  60. Java基础-反射