Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

The loading process of Spring BeanDefinition

2025-02-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly explains "the loading process of Spring BeanDefinition". Interested friends may wish to have a look at it. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "the loading process of Spring BeanDefinition".

I. XML definition

The loading of   XML configuration is implemented by AbstractXmlApplicationContext, which is implemented as follows:

  mainly instantiates a XmlBeanDefinitionReader object, sets an Environment object to it (the specific process can be described in the previous article), and then calls XmlBeanDefinitionReader to parse. Follow it directly and get the following content:

  parameter inputSource is the XML configuration file, and Resource is the description of the configuration file, which mainly describes the location of the configuration file in classpath and the loader that can be used to load the configuration file. The doLoadDocument method is relatively simple, mainly loading the specified configuration file and returning a JDK built-in XML parsing Document object so that the XML DOM node can be parsed.

  focuses on the registerBeanDefinitions method, as follows:

  this method is finally delegated to BeanDefinitonDocumentReader to complete the parsing of Bean. Before that, a series of related objects are initialized. These include:

Using DefaultBeanDefinitionDocumentReader as the implementation of BeanDefinitionDocumentReader interface

A XmlReaderContext is created to hold various related objects used in the parsing process, such as the resource description object Resource, ReaderEventListener event listeners, XmlBeanDefinitionReader, and NamespaceHandlerResolver namespace parsers. The key point is DefaultNamespaceHandlerResolver, which completes the parsing of the custom XML format, which will be explained later.

  delegates the parsing process to DefaultBeanDefinitionDocumentReader to handle the initial related objects. This class focuses on the parseBeanDefinitions method. Before calling the method, initialize a BeanDefinitionParserDelegate object, as follows:

  and pass the delegate object into the parseBeanDefinitions method. BeanDefinitionParserDelegate mainly provides the parsing process of XML files whose namespace is http://www.springframework.org/schema/beans (hereinafter abbreviated as beans space). The namespace defines four main XML tags, beans, bean, import, and alias, and the attributes corresponding to these tags. The following is an example of the namespace, defining a basic Bean.

  should note that after initializing BeanDefinitionParserDelegate, the above parses the default attributes on the tag on XML, including global attributes such as default-lazy-init, default-merge, default-autowire, default-dependency-check, default-autowire-candidates, default-init-method and default-destroy-method.

 , take a look at the parseBeanBefinitoins method:

  this method determines the namespace to which the current node belongs, which is divided into default namespace and custom namespace, where the default namespace refers to the beans space mentioned above. For the default namespace, each DOM child node is parsed one by one, the namespace of the child node is determined, and finally delegated to two methods: the parseDefaultElement method that handles the default namespace and the parseClustomElement method that handles the custom namespace.

As shown above, the   parseDefautlElement method processes each tag defined in the beans space:

When parsing the import tag, the configuration file specified by the resource attribute is read, and the bean definition in the file is parsed after loading.

When parsing the alias tag, the name and alias attributes of the tag are read and added to the BeanRegistry cache.

When parsing bean tags, the process is directly delegated to BeanDefinitionParserDelegate. The process is as follows:

For step 3.d, the process is as follows:

Get the value of the class attribute

Get the value of the parent attribute

Initialize GenericBeanDefinition instance

Parse the attributes of the bean node and set them to BeanDefinition, including: scope, abstract, lazy-init, autowired, dependency-check, autowire-candidate, primary, init-method, destroy-method, factory-method, factory-bean

Parse the description child node to get the description content of the value setting bean

Parse the list of meta child nodes to get additional metadata information about key and value settings

Parse the list of lookup-method child nodes to get the injection information of name and bean value setting method

Parse the list of replaced-method child nodes to get the method information that the value setting requires a dynamic proxy

Parse the list of constructor-arg child nodes to get the value setting construction parameter information

Parse the list of property child nodes to get the value setting attribute information

Parse the list of qualifier child nodes and get the value for setting

Get the value of the id property as beanName

Get the value of the name attribute as aliases, which can be configured to split with, or;, and will be used as an alias for the bean; if the id value is empty and name is not empty, the first name value is used as the id value

Check the uniqueness of beanName and aliases

Parse other bean configurations and generate GenericBeanDefinition objects

If beanName is empty, assign one to it

After parsing the configuration of bean above,   will process the configuration of other namespaces in the child nodes, and use the decorate method of NamespaceHandler to modify the content of Bean definition. This part will be discussed later using the following content.

When parsing beans tags, recursive processing occurs

  as above, the default namespace is mainly used to parse the definition of bean. After the above processing, the resolution of the bean definition has been completed, and the instance object will be registered to the context for saving.

  the parseClustomElement method is introduced below. As the name implies, this method is mainly used to deal with XML tags of custom namespaces, and can be used as an extension of spring XML configuration processing, as follows:

  is mainly delegated to NamespaceHandlerResolver. By finding the Handler of the corresponding node corresponding to the namespace, call the parse method of the Handler for processing.

As   said earlier, NamespaceHandlerResolver uses DefaultNamespaceHandlerResolver as its implementation, and the trace resolve method goes in as follows:

The   process is:

Gets the list of existing Handler processes, and returns a Map,Key as the XML namespace. The value may be a Spring object representing the corresponding Handler type or an instantiated Handler object, depending on whether it has been called before.

If it refers to a Handler object, it returns directly

If it is a String object, indicating that it has not been initialized, initialize the class, execute the init initialization method, and then return it to Map

  for the acquisition of the Handler processing list in step (1), Spring scans all the spring.handlers configuration files in the META-INF in the classpath, reads everything into a Map and returns it.

  as above, the spring.handlers file provided for the spring-context module provides support for customizing the namespace tags of the module. The following is an example of a custom namespace:

  mainly introduces spring-configured tags and annotation-config tags in context space.

  so far, bean resolution under XML configuration has been introduced.

II. Annotation configuration

  the following describes the process of Spring loading bean with annotations, as follows, the configuration required to enable annotation loading:

  according to the previous content, component-scan is the tag in the http://www.springframework.org/schema/context namespace, and the processing object is defined in the spring.handlers file of the spring-context module, corresponding to the class org.springframework.context.config.ContextNamespaceHandler, as follows:

When   looks at this class, you can see that component-scan is handled by ComponentScanBeanDefinitionParser, as follows:

The main processes of   are:

Get the content of the base-package attribute and assign it to basePackage

Replace placeholder content in basePackage

Split the basePackage according to the,;\ t\ n separator to get multiple packet paths

Parse the component-scan configuration content and return the ClassPathBeanDefinitionScanner object

Parsing and setting use-default-filters parameters

Parsing and setting resource-pattern parameters

Parsing and setting name-generator parameters

Parse setting parameters such as scope-resolver, scoped-proxy, etc.

Parse and set include-filter, exclude-filter and other parameters. Org.springframework.stereotype is added by default when the ClassPathBeanDefinitionScanner object is re-initialized. Notes on Component, javax.annotation.ManagedBean and javax.inject.Named

Call the doScan method of ClassPathBeanDefinitionScanner to perform the scan, register the matching class into the context and return

Parse the annotation-config parameter, and if it is true (default is true), then automatically register a series of annotation processing class definitions for post-parsing to the context. Here we focus on steps (5) and (6) below.

When   (5) performs a scan, it traverses all the paths returned in step (3). For each path, the findCandidateComponents method of the parent class ClassPathScanningCandidateComponentProvider is called to return all the Bean that meet the requirements under that path, as follows:

  ClassPathScanningCandidateComponentProvider will find all the classes in the specified path and wrap them as Resource [] objects. For each Resource, it will use the SimpleMetadataReaderFactory factory class to create a new SimpleMetadataReader object for each Resouce object, which is used to parse the information of the class. It should be noted that when initializing the SimpleMetadataReader object, the parsing action will be performed, saving the results as ClassMetadata data and AnnotationMetadata data. The former is used to store the definition information of the class, including the class name and whether the interface is used. Contains information such as attributes, which contains all the annotation information. After obtaining the SimpleMetadataReader object, it is determined whether the class conforms to the content defined in include-filter and exclude-filter defined by component-scanner. Note that objects such as @ Component are included by default, so all classes with @ Component annotations and @ component meta annotations (such as @ Service, @ Repository) are loaded by default. If it meets the requirements, the class is wrapped as a ScannedGenericBeanDefinition object, and it is checked that the class cannot be an interface and cannot rely on an internal non-static class, and if so, it is added to the list to be returned.

After   executes the above findCandidateComponents method, it assigns a beanName to it for internal use, and then calls the processCommonDefinitionAnnotations method of AnnotationConfigUtils, which parses some basic annotation properties on the BeanDefinition returned above and sets them, including @ Lazy, @ Primary, @ DependsOn, @ Role, and @ Description. After completing this step, it is determined whether the bean already exists, and if not, it is added to the context.

The code for step (6) of   is as follows:

  focuses on the second half, calling AnnotationConfigUtils's registerAnnotationConfigProcessors method, which adds a series of annotation processing class definitions for post-parsing to the context, including:

Add ConfigurationClassPostProcessor processor (BeanDefinitionRegistryPostProcessor), add @ Configuration function, corresponding to bean is org.springframework.context.annotation.internalConfigurationAnnotationProcessor

Add AutowiredAnnotationBeanPostProcessor processors (SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor), add @ Autowired,@Value function, corresponding to bean is org.springframework.context.annotation.internalAutowiredAnnotationProcessor

Add RequiredAnnotationBeanPostProcessor processors (SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor), add @ Required function, corresponding to bean is org.springframework.context.annotation.internalRequiredAnnotationProcessor

Add CommonAnnotationBeanPostProcessor processors (InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, BeanPostProcessor), add @ PostConstruct, @ PreDestroy functions, corresponding to bean is org.springframework.context.annotation.internalCommonAnnotationProcessor

Add PersistenceAnnotationBeanPostProcessor processors (InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor), add @ PersistenceUnit, @ PersistenceContext functions, corresponding to bean is org.springframework.context.annotation.internalPersistenceAnnotationProcessor

Add EventListenerMethodProcessor, add @ EventListener function, corresponding to bean is org.springframework.context.event.internalEventListenerProcessor

Add DefaultEventListenerFactory. Corresponding bean is org.springframework.context.event.internalEventListenerFactory.

Each bean above   will determine whether the definition has been changed before it is added, and if it does not exist, it will be added. Therefore, the corresponding processing function can be modified by adding the corresponding bean.

  PS: step (6) the post-processing method of adding comments is actually the main processing method of the tag function of annotation-config. From the above, we can see that the processing class of annotation-config is AnnotationConfigBeanDefinitionParser. In fact, the registerAnnotationConfigProcessors method of AnnotationConfigUtils is called inside this class to complete the annotation function. The specific code is as follows:

III. API callback

  combines the content started by Spring and the above content to get the following callback sequence of APIs

  because InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor and other APIs inherit from MergedBeanDefinitionPostProcessor APIs, and MergedBeanDefinitionPostProcessor APIs inherit from BeanPostrProcessor. There is overlap in the implementation classes. Here, sort them according to the order explained.

At this point, I believe you have a deeper understanding of the "loading process of Spring BeanDefinition". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report