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

How to write the container startup source code in Spring5.x

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

Share

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

Today, I will talk to you about how to write the container startup source code in Spring5.x. Many people may not know much about it. In order to make you understand better, the editor has summarized the following for you. I hope you can get something according to this article.

Spring is already a very mature framework, and this article is the first release of the groundbreaking Spring source code analysis. Reading the source code is a very boring, difficult, skillful and significant thing. Everything is difficult at the beginning, I will use my spare time to continue to follow up the serialization of the article. For those who like the source code, it can provide some help.

The simplest code to start spring is as follows:

Import com.ld.test.config.AppConfig;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class TestDemo {public static void main (String [] args) {AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext (AppConfig.class); acac.close ();}}

AnnotationConfigApplicationContext

Let's take a look at the UML diagram of the AnnotationConfigApplicationContext class to make an impression.

Click AnnotationConfigApplicationContext (AppConfig.class); check the source code:

Public AnnotationConfigApplicationContext (Class... AnnotatedClasses) {/ / call the default no-parameter constructor, which contains a lot of initialization logic / / initialize two classes / / AnnotatedBeanDefinitionReader reader; / / ClassPathBeanDefinitionScanner scanner; this () / / register the incoming Class. Class can have either @ Configuration annotation or @ Configuration annotation / @ Configuration / / map.put ("org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass", "full") / / without @ Configuration / / map.put ("org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass", "lite") / how to register? Delegated to the org.springframework.context.annotation.AnnotatedBeanDefinitionReader.register method to register / / input Class to generate BeanDefinition, and then register to BeanDefinitionRegistry register (annotatedClasses); / / refresh the container context refresh ();}

This constructor allows us to pass in one or more class objects. The class object can be annotated by @ Configuration, or it can be a normal Java class.

The parametric constructor calls the non-parametric constructor and clicks the open source code:

Public AnnotationConfigApplicationContext () {/ / implicitly calls the parent constructor to initialize beanFactory. The implementation class is DefaultListableBeanFactory / / super (); / / create AnnotatedBeanDefinitionReader, / / register the BeanDefinition this.reader = new AnnotatedBeanDefinitionReader (this) of the annotated configuration-related processors with the incoming BeanDefinitionRegistry. / / through the later source code exploration, it can also be found that spring does not use this scanner to scan the package to get this.scanner = new ClassPathBeanDefinitionScanner (this) of Bean;}

When a subclass is initialized, the parent class is initialized first, and the parent class parameterless constructor is called by default. AnnotationConfigApplicationContext inherits GenericApplicationContext and creates a concrete implementation class DefaultListableBeanFactory of BeanFactory in the no-parameter constructor of GenericApplicationContext. This is where BeanFactory in spring is instantiated and uses the default implementation of BeanFactory made by DefaultListableBeanFactory.

Public GenericApplicationContext () {this.beanFactory = new DefaultListableBeanFactory ();}

DefaultListableBeanFactory

Two objects are also created in AnnotationConfigApplicationContext's constructor: AnnotatedBeanDefinitionReader and ClassPathBeanDefinitionScanner.

ClassPathBeanDefinitionScanner scanner

Let's talk about the function of scanner first. By looking at the source code, we can find that this scanner is only used when some methods of AnnotationConfigApplicationContext are called manually. (it can also be found that spring does not use this scanner to scan packages for Bean.)

2 、 AnnotatedBeanDefinitionReader

Create an AnnotatedBeanDefinitionReader object. Spring passed the this as an argument to the constructor when it created the reader. In other words, the reader object contains a this object, that is, the AnnotationConfigApplicationContext object. AnnotationConfigApplicationContext implements the BeanDefinitionRegistry interface. Click this.reader = new AnnotatedBeanDefinitionReader (this); source code:

Public AnnotatedBeanDefinitionReader (BeanDefinitionRegistry registry) {this (registry, getOrCreateEnvironment (registry));}

Get the Environment from the incoming BeanDefinitionRegistry object, the AnnotationConfigApplicationContext object (sharing the same Environment), and then call another constructor. Click the open source code:

Public AnnotatedBeanDefinitionReader (BeanDefinitionRegistry registry, Environment environment) {Assert.notNull (registry, "BeanDefinitionRegistry must not be null"); Assert.notNull (environment, "Environment must not be null"); this.registry = registry; this.conditionEvaluator = new ConditionEvaluator (registry, environment, null); / / register processors AnnotationConfigUtils.registerAnnotationConfigProcessors (this.registry) related to annotation configuration in BeanDefinitionRegistry;}

In this constructor, a very important method, AnnotationConfigUtils.registerAnnotationConfigProcessors (this.registry), is executed; as the name implies, spring registers parsing annotations to configure the relevant processors. Click the open source code:

Step 1: set properties

Public static Set registerAnnotationConfigProcessors (BeanDefinitionRegistry registry, @ Nullable Object source) {DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory (registry); if (beanFactory! = null) {if (! (beanFactory.getDependencyComparator () instanceof AnnotationAwareOrderComparator)) {/ / AnnotationAwareOrderComparator is a subclass of OrderComparator and is used to support Spring's Ordered class, @ Order annotation, and @ Priority annotation. BeanFactory.setDependencyComparator (AnnotationAwareOrderComparator.INSTANCE);} if (! (beanFactory.getAutowireCandidateResolver () instanceof ContextAnnotationAutowireCandidateResolver)) {/ / set candidate processors for dependency injection / / you can see that as long as it is not a ContextAnnotationAutowireCandidateResolver type, it can be directly upgraded to the strongest type beanFactory.setAutowireCandidateResolver (new ContextAnnotationAutowireCandidateResolver ());}} / / code omission. }

Some BeanDefinition of spring built-in PostProcessor are registered.

2.1 、 ConfigurationClassPostProcessor

ConfigurationClassPostProcessor is a BeanFactoryPostProcessor and BeanDefinitionRegistryPostProcessor processor, and the BeanDefinitionRegistryPostProcessor processing method can handle annotations such as @ Configuration. The ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry () method handles @ Configuration,@Import,@ImportResource internally and @ Bean inside the class.

The ConfigurationClassPostProcessor class inherits from BeanDefinitionRegistryPostProcessor. The BeanDefinitionRegistryPostProcessor class inherits from BeanFactoryPostProcessor. With BeanDefinitionRegistryPostProcessor, you can create a special post processor to add BeanDefinition to BeanDefinitionRegistry. Unlike BeanPostProcessor, BeanPostProcessor only has a hook for us to add some custom actions when Bean is initialized, while BeanDefinitionRegistryPostProcessor allows us to add some custom actions to BeanDefinition. In the integration of Mybatis and Spring, BeanDefinitionRegistryPostProcessor is used to customize the BeanDefinition of Mapper.

2.2 、 AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor is used to handle @ Autowired annotations and @ Value annotations

2.3 、 RequiredAnnotationBeanPostProcessor

RequiredAnnotationBeanPostProcessor this is used to handle @ Required annotations

2.4 、 CommonAnnotationBeanPostProcessor

Provides support for JSR-250 specification annotations such as @ javax.annotation.Resource, @ javax.annotation.PostConstruct, @ javax.annotation.PreDestroy, etc.

2.5 、 EventListenerMethodProcessor

EventListenerMethodProcessor provides @ PersistenceContext support.

EventListenerMethodProcessor provides @ EventListener support. @ EventListener actually appeared after spring4.2, and you can use the @ EventListener annotation on a Bean method to automatically register an ApplicationListener.

Public static Set registerAnnotationConfigProcessors (BeanDefinitionRegistry registry, @ Nullable Object source) {/ / code omission. Set beanDefs = new LinkedHashSet (8); / / the first question understands RootBeanDefinition-> AbstractBeanDefinition / / the second question understands registerPostProcessor (); if (! registry.containsBeanDefinition (CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {/ / org.springframework.context.annotation.internalConfigurationAnnotationProcessor-ConfigurationClassPostProcessor.class / / this class is very important, it is a BeanDefinitionRegistryPostProcessor RootBeanDefinition def = new RootBeanDefinition (ConfigurationClassPostProcessor.class); def.setSource (source) BeanDefs.add (registerPostProcessor (registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));} / / Code omission. Logic is almost return beanDefs;}

We find that the internally defined class is all with internal.

BeanDefs ">

1. This method gets the DefaultListableBeanFactory object from the incoming BeanDefinitionRegistry object, that is, the AnnotationConfigApplicationContext object.

2. Set the properties for the acquired DefaultListableBeanFactory object

3. Register BeanDefinition in the DefaultListableBeanFactory object and register some BeanDefinition of spring built-in PostProcessor (the introduction to BeanDefinition will be discussed in the next issue). Notice that you are only registering BeanDefinition at this time, and you are not instantiating bean. By default, after executing this method, the BeanDefinition registered in the spring container is:

Register the built-in Processor to the container

Definition.setRole (BeanDefinition.ROLE_INFRASTRUCTURE)

ROLE_INFRASTRUCTURE = 2 is my Bean, which is owned by Spring itself and has nothing to do with your users.

Private static BeanDefinitionHolder registerPostProcessor (BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {definition.setRole (BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition (beanName, definition); return new BeanDefinitionHolder (definition, beanName);}

The so-called registration BeanDefinition is simply to put the BeanDefinition into the beanDefinitionMap of the DefaultListableBeanFactory.registerBeanDefinition object

@ Overridepublic void registerBeanDefinition (String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {Assert.hasText (beanName, "Bean name must not be empty"); Assert.notNull (beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) {try {((AbstractBeanDefinition) beanDefinition). Validate () } catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException (beanDefinition.getResourceDescription (), beanName, "Validation of bean definition failed", ex);}} BeanDefinition existingDefinition = this.beanDefinitionMap.get (beanName); / / the first time existingDefinition comes in must be null if (existingDefinition! = null) {/ / code omitted. This.beanDefinitionMap.put (beanName, beanDefinition);} else {if (hasBeanCreationStarted ()) {/ / Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) {this.beanDefinitionMap.put (beanName, beanDefinition); List updatedDefinitions = new ArrayList (this.beanDefinitionNames.size () + 1); updatedDefinitions.addAll (this.beanDefinitionNames) UpdatedDefinitions.add (beanName); this.beanDefinitionNames = updatedDefinitions; removeManualSingletonName (beanName);}} else {/ / Still in startup registration phase this.beanDefinitionMap.put (beanName, beanDefinition); this.beanDefinitionNames.add (beanName); removeManualSingletonName (beanName);} this.frozenBeanDefinitionNames = null } if (existingDefinition! = null | | containsSingleton (beanName)) {resetBeanDefinition (beanName);}}

That's it: DefaultListableBeanFactory.beanDefinitionMap has only the default spring beanDefinition

The following is the familiar registration of the default 6 post processors:

1.ConfigurationClassPostProcessor

2.AutowiredAnnotationBeanPostProcessor

3.CommonAnnotationBeanPostProcessor

PersistenceAnnotationProcessor of 4.Jpa (no guide package will not register)

5.EventListenerMethodProcessor

6.DefaultEventListenerFactory

3. ClassPathBeanDefinitionScannerpublic AnnotationConfigApplicationContext () {/ * create a Bean definition reader that reads annotations * what is a bean definition? BeanDefinition * * completes the registration of spring internal BeanDefinition (mainly post processor) * / this.reader = new AnnotatedBeanDefinitionReader (this) / * create BeanDefinition scanner * can be used to scan packages or classes, and then convert to bd * * spring the default scan package is not this scanner object * but a ClassPathBeanDefinitionScanner * spring of your own new when executing the project post processor ConfigurationClassPostProcessor New a ClassPathBeanDefinitionScanner when scanning the package * * the scanner here is only so that the programmer can manually call the scan method of the AnnotationConfigApplicationContext object * * / this.scanner = new ClassPathBeanDefinitionScanner (this) }

Next step

Public ClassPathBeanDefinitionScanner (BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @ Nullable ResourceLoader resourceLoader) {Assert.notNull (registry, "BeanDefinitionRegistry must not be null"); this.registry = registry / / this definitely successful if (useDefaultFilters) {/ * register spring scanning class filter * classes with specific annotations will be scanned to * with @ Component, @ Repository, @ Service, @ Controller, @ ManagedBean, @ Named * / registerDefaultFilters () } setEnvironment (environment); setResourceLoader (resourceLoader);}

Only care about the registerDefaultFilters (); method of the last constructor

/ * * Registration filter * classes with @ Component, @ Repository, @ Service, @ Controller, @ ManagedBean, @ Named * annotations will be scanned by spring to * * Register the default filter for {@ link Component @ Component}. *

This will implicitly register all annotations that have the * {@ link Component @ Component} meta-annotation including the * {@ link Repository @ Repository, {@ link Service @ Service}, and * {@ link Controller @ Controller} stereotype annotations. *

Also supports Java EE 6 annotations {@ link javax.annotation.ManagedBean} and * JSR-330's {@ link javax.inject.Named} annotations, if available. * * / @ SuppressWarnings ("unchecked") protected void registerDefaultFilters () {this.includeFilters.add (new AnnotationTypeFilter (Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader (); try {this.includeFilters.add (Class)

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