“This is the fifth day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

Bean life flow

I am sure to do two things:

  • scanning
  • Create a singleton bean that is not lazily loaded

So there are really three steps:

  • Scan the bean
  • Create a bean
  • Other matters

Step 1 – Scan the bean

This step corresponds to the SpringBoot boot step here:

context = createApplicationContext(); / /... public AnnotationConfigServletWebServerApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); }Copy the code

How does scanner scan?

BeanDefinitionRegistryDefaultListableBeanFactory

Why use the former and not the latter? – Minimum knowledge principle

In the scan.

The core in doScan.

 getMetadataReaderFactory().getMetadataReader(resource)
Copy the code

Using ASM technology, class files are processed into processable BDS

To continue, @Component must be included and match conditions for @Conditional must be passed.

Here, after parsing, we simply assign the Bean name to the beanClass of the BeanDefinition.

Object, String, Class, Class, Class, Class, Class

You cannot be a Bean if:

  • Inner classes, abstract classes, interfaces

  • But if there is a method decorated by @lookup, it will be registered as a Bean.

    A lookup annotation is a simple way to have a lookup decorated method return a different value each time a singleton bean calls a Prototype bean.

.

  • Once that’s done, it goes to the BeanDefinitionMap in the BeanFactory.

Step 2 – Initialize the non-lazy-loaded singleton bean

In this step in the context. Refresh the finishBeanFactoryInitialization preInstantiateSingletons, instantiate the singleton beans.

In this step, all BDS (existing in beanDefinitionNames) with A BD name record so far are initialized as beans.

The corresponding code is as follows:

for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // bd.isabstract () refers to the abstract bd, not the abstract bean BD if (! bd.isAbstract() && bd.isSingleton() && ! bd.isLazyInit()) { if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { FactoryBean<? > factory = (FactoryBean<? >) bean; boolean isEagerInit; if (System.getSecurityManager() ! = null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged( (PrivilegedAction<Boolean>) ((SmartFactoryBean<? >) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<? >) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else { getBean(beanName); }}}Copy the code

Abstract the BD

Abstract BD refers to the BD of an abstract bean that has an abstract property of its own.

  • What’s the use?

Parent-child BD can be inherited using (and other) abstractions, and by inheritance we mean not class inheritance, but parent-child relationships

The two are parent-child relationships, and the child BD inherits attributes that are not specifically declared from the parent BD.

In the upper block, subBD will do:

getMergedLocalBeanDefinition(beanName)

GetMergedLocalBeanDefinition – ultimately BD combined

Combine the BD.

A new BD is generated, which contains all the information contained in inheritance and other associations, and is stored in mergedBeanDefinitions.

RootBD: refers to the rootBD, which ultimately contains all the information it should.

The code from here ends up here:

protected RootBeanDefinition getMergedBeanDefinition( String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) throws BeanDefinitionStoreException { synchronized (this.mergedBeanDefinitions) {  RootBeanDefinition mbd = null; RootBeanDefinition previous = null; // Check with full lock now in order to enforce the same merged instance. if (containingBd == null) { mbd = this.mergedBeanDefinitions.get(beanName); } if (mbd == null || mbd.stale) { previous = mbd; if (bd.getParentName() == null) { // Use copy of given root bean definition. if (bd instanceof RootBeanDefinition) { mbd  = ((RootBeanDefinition) bd).cloneBeanDefinition(); } else { mbd = new RootBeanDefinition(bd); } } else { // Child bean definition: needs to be merged with parent. BeanDefinition pbd; try { String parentBeanName = transformedBeanName(bd.getParentName()); if (! beanName.equals(parentBeanName)) { pbd = getMergedBeanDefinition(parentBeanName); } else { BeanFactory parent = getParentBeanFactory(); if (parent instanceof ConfigurableBeanFactory) { pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName); } else { throw new NoSuchBeanDefinitionException(parentBeanName, "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName + "': cannot be resolved without a ConfigurableBeanFactory parent"); } } } catch (NoSuchBeanDefinitionException ex) { throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName, "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex); } // Deep copy with overridden values. mbd = new RootBeanDefinition(pbd); mbd.overrideFrom(bd); } // Set default singleton scope, if not configured before. if (! StringUtils.hasLength(mbd.getScope())) { mbd.setScope(SCOPE_SINGLETON); } // A bean contained in a non-singleton bean cannot be a singleton itself. // Let's correct this on the fly here, since this might be the result of // parent-child merging for the outer bean, in which case the original inner bean // definition will not have inherited the merged outer bean's singleton status. if  (containingBd ! = null && ! containingBd.isSingleton() && mbd.isSingleton()) { mbd.setScope(containingBd.getScope()); } // Cache the merged bean definition for the time being // (it might still get re-merged later on in order to pick up metadata changes) if (containingBd == null && isCacheBeanMetadata()) { this.mergedBeanDefinitions.put(beanName, mbd); } } if (previous ! = null) { copyRelevantMergedBeanDefinitionCaches(previous, mbd); } return mbd; }}Copy the code

tips:

  • Here, you recursively look up the entire BD inheritance tree (not the class inheritance relationship, of course).

    String parentBeanName = transformedBeanName(bd.getParentName()); if (! beanName.equals(parentBeanName)) { pbd = getMergedBeanDefinition(parentBeanName); }Copy the code
  • In this case, we’re going to do a merge.

                         mbd = new RootBeanDefinition(pbd);
                         mbd.overrideFrom(bd);
    Copy the code
  • Then, save:

                     if (containingBd == null && isCacheBeanMetadata()) {
                         this.mergedBeanDefinitions.put(beanName, mbd);
                     }
    Copy the code

    The next step will determine whether it is a factory bean, which we will leave for the next installment.