This is the 10th day of my participation in the August Text Challenge.More challenges in August

We’ve seen the spring IOC loading process before, as shown below. Let’s take a look at the ioc loaded source code in the figure below.

Let’s use the decoration analogy to see how each component works.

 

Next is the overall structure diagram of source code analysis. Compared with the above train of thought comb out

 

A source code analysis of the entrance

Usually, our entry is from the main method. Let’s also define a main method here

Public class MainStarter {public static void main(String[] args) {// Reading a configuration from the AnnotationConfigApplicationContext class AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainStarter.class ); context.scan("package name"); Car car = (Car) context.getBean("car"); System.out.println(car.getName()); context.close(); }}Copy the code

 

By the way, let’s see what other classes are involved

/** * this is a configuration class, * in the Configuration class defines the packages of the scan path com. The LXL. www.iocbeanlifecicle * will this is the package Configuration under the annotation class scanning into the ioc container, become a mature bean * / @ Configuration @ComponentScan(basePackages = {"com.lxl.www.iocbeanlifecicle"}) public class MainConfig { }Copy the code

This class has an annotation @Configuration so that the class will be scanned as a bean

There is an annotation @ ComponentScan (backPackage = {} “com. LXL. HTTP: / / www.iocbeanlifecicle”), he said, please scan the com. LXL. www.iocbeanlifecicle package all the classes.

Com. LXL. www.iocbeanlifecicle this package under what kind of? Let’s take a look at the project structure

 

 

This is the complete project structure under this package.

The purpose of each class will be explained gradually below

 

The most important class is BeanFactory

We know that the BeanFactory is the most important thing in loading a class as a bean, so when was it loaded?

Let us track the AnnotationConfigApplicationContext structure method with a parameter

public AnnotationConfigApplicationContext(Class<? >... ComponentClasses) {// Call the constructor this(); Call this() before calling its own constructor; // Retister configures the class register(componentClasses); // refresh(); }Copy the code

This is the time when the AnnotationConfigApplicationContext initialization do three things

First thing: this(); // call its own no-argument constructor. The constructor of the parent class is also called

Second thing: Register (componentClasses); // Call the registry, which loads two BeanDefinitionReader and BeanDefinitionScanner. What is the role of these two? Recall the previous frame diagram

Third thing: refresh(); // This is ioc container refresh, which is very important. Both Spring Boot and Spring MVC have this method. This method encompasses the entire lifecycle of spring IOC loading. And that’s how we’re going to focus on learning

 

Now, when is the BeanFactory loaded?

Its own no-argument constructor is called when the method is initialized, and its parent class’s no-argument constructor is also called when the method is called.

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry { . }Copy the code

Parent is GenericApplicationContext, its a no-parameter constructor is to do a thing

Public GenericApplicationContext () {/ / constructs a the BeanFactory. / / GenericApplicationContext the call the superclass constructor, For the ApplicationContext spring context object initialization the beanFactory / / why is initialized DefaultListableBeanFactory? / / when we were watching the BeanFactory interface found DefaultListableBeanFactory is at the bottom of the implementation, Function is the most complete. / / to check this. The beanFactory = new DefaultListableBeanFactory (); }Copy the code

Initialize DefaultListableBeanFactory.

Question: the BeanFactory has a lot of, why choose DefaultListableBeanFactory initialization time?

Let’s take a look at DefaultListableBeanFactory structure. Shortcut keys Option + Command + U –> Java Class Diagrams

 

 

Through the observation, we found that DefaultListableBeanFactory realized all kinds of the BeanFactory interface, or the BeanDefinitionRegistry interface at the same time.

That is to say, DefaultListableBeanFactory not only the ability of the BeanFactory, as well as the ability of BeanDefinitionRegistry. Its function is the most complete.

So, we are using a very powerful class Bean factory class.

 

AnnotationConfigApplicationContext inherited GenericApplicationContext,

While GenericApplicationContext AnnotationConfigRegistry interface is realized.

So AnnotationConfigApplicationContext AnnotationConfigRegistry ability.

 

3. The readers AnnotatedBeanDefinitionReader bean definition

Then, the first step is called this (). Namely AnnotationConfigApplicationContext no arguments constructor. There are two things you do in this no-argument constructor

Public AnnotationConfigApplicationContext () {/ * * * create a Bean definition reader. * completed internal spring BeanDefinition registered * (mainly the rear processing unit) Read a lot of Spring custom configurations (mainly the rear processor). These classes are spring's original class. * / this. Reader = new AnnotatedBeanDefinitionReader (this); /** * Create a BeanDefinition scanner that can be used to scan packages or classes, And then converted to bd * * Spring default scan pack instead of this scanner object * new a ClassPathBeanDefinitionScanner * Spring in performing engineering ConfigurationClassPostProcessor post processor, To scan the package will be new a ClassPathBeanDefinitionScanner * * the scanner here merely for the programmer can call object AnnotationConfigApplicationContext scan method * manually By calling context.scan("package name"); Scanning process scan configuration class * * / this. Scanner = new ClassPathBeanDefinitionScanner (this); }Copy the code
  1. Initialize AnnotatedBeanDefinitionReader.

  2. Initialize ClassPathBeanDefinitionScanner

Let’s take a look firstAnnotatedBeanDefinitionReader

 

 

For this description, BeanDefinitionReader means to scan configurations or annotations, if defined for sale, for the building. That’s where our potential customers are. That is, the object we need to convert into a bean.

What did the initialization, AnnotatedBeanDefinitionReader?

Focus on this sentence

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); . / / registered annotation type configuration of the processor AnnotationConfigUtils registerAnnotationConfigProcessors (enclosing registry); }Copy the code

Registers handlers for annotation type configurations

AnnotationConfigUtils.registerAnnotationConfigProcessors( this .registry);

/** * Register all relevant annotation post processors in the given registry. * @param registry the registry to operate on * @param source the configuration source element (already extracted) * that this registration was triggered from. May  be {@code null}. * @return a Set of BeanDefinitionHolders, containing all bean definitions * that have actually been registered by this call */ public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @ Nullable Object source) {/ / get the beanFactory DefaultListableBeanFactory the beanFactory = unwrapDefaultListableBeanFactory(registry); / * * * determine whether in the beanFactory AnnotationAwareOrderComparator and ContextAnnotationAutowireCandidateResolver * not add * / if (beanFactory ! = null) { if (! (beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (! (beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } // BeanDefinitionHolder: Set BeanDefinitionHolder <BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8); / / 1. If there is no ConfigurationClassPostProcessor registry configuration class post processor, add an if (! registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); // Build BeanDefinitionHolder and add it to beanDefs beandefs.add (registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } / / 2. If the rigistry, there is no AutowiredAnnotationBeanPostProcessor Autowired annotations beans rear processor, then add an if (! registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); // Build BeanDefinitionHolder and add it to beanDefs beandefs.add (registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor. // 3. Check the support for JSR - 250, if not in the rigistry CommonAnnotationBeanPostProcessor general rear annotation processor, then add an if (jsr250Present &&! registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class); def.setSource(source); // Build BeanDefinitionHolder and add it to beanDefs beandefs.add (registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); } // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor. // 4. To check if the support for jpa, does not contain internalPersistenceAnnotationProcessor, persistence annotations processor, add an if (jpaPresent &&! registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME) ) { RootBeanDefinition def = new RootBeanDefinition(); try { def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader())); } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex); } def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); } / / 5. Check the support for the event listeners, if does not include the event listeners processor internalEventListenerProcessor, add an if (! registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME)); } / / 6. If the factory does not include the event listeners processor internalEventListenerFactory, add an if (! registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME)); } return beanDefs; }Copy the code

Six post-processors are registered here.