Spring IOC Source Parsing

Note that it takes a long, long time to read this article.

This article is about Spring IOC Source Parsing (Part I) In the sequel, the previous article introduced how to start Spring using XML, and then tracked the creation of Bean Factory containers, the parsing of configuration files, the registration of beans, and so on.

12. finishBeanFactoryInitialization()

Super-long warning ahead...

We mentioned just now that beans have not been initialized yet. This method is responsible for initializing all singleton bean s that are not lazily loaded.

It's started.

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {

        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }
        //Initialize LoadTime Weaver Aware-type Bean s first
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }
       //Stop using temporary class loaders for type matching
        beanFactory.setTempClassLoader(null);
      //Freeze all bean definitions, that is, registered bean definitions will not be modified or reprocessed
        beanFactory.freezeConfiguration();
      //Initialization
        beanFactory.preInstantiateSingletons();
    }

Look down at the meaning of the code that is not explained above.

conversionService

The most practical scenario for this type of bean is to use it when converting the parameters passed from the front end to the parameters format on the back-end controller method.

For example, the front end needs to pass a String, and the back end can do this when it uses Date acceptance.


public class StringToDateConverter implements Converter<String, Date> {

    @Override
    public Date convert(String date) {
        try {
            return dateFormat.parse(date);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Date conversion failed!");
            return null;
        }
        
    }
}

Get another bean

<bean id="conversionService"
  class="org.springframework.context.support.ConversionServiceFactoryBean">
  <property name="converters">
    <list>
      <bean class="cn.shiyujun.utils.StringToDateConverter"/>
    </list>
  </property></bean>
EmbeddedValueResolver

Using Embedded Value Resolver, it is easy to read the properties of configuration files.

@Component
public class PropertiesUtil implements EmbeddedValueResolverAware {

    private StringValueResolver resolver;

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.resolver = resolver;
    }


    /**
     * Just pass in the attribute name when you get the attribute.
     */
    public String getPropertiesValue(String key) {
        StringBuilder name = new StringBuilder("${").append(key).append("}");
        return resolver.resolveStringValue(name.toString());
    }

}
Initialization

Knock on the blackboard, the point is...

Here we analyze the beanFactory.preInstantiateSingletons() method

public void preInstantiateSingletons() throws BeansException {
   if (this.logger.isDebugEnabled()) {
      this.logger.debug("Pre-instantiating singletons in " + this);
   }
   // This. bean Definition Names saves all beanNames
   List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

   for (String beanName : beanNames) {

      // Merge the configuration in the parent Bean with the parent attribute in the idea <Bean id=""class="""parent="/>.
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

      // Not abstract, singular, and not lazy to load
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         // Processing FactoryBean
         if (isFactoryBean(beanName)) {
            //Add the "&" sign before the bean Name
            final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
            // Determine whether the current FactoryBean is an implementation of SmartFactoryBean
            boolean isEagerInit;
            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
               isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                  @Override
                  public Boolean run() {
                     return ((SmartFactoryBean<?>) factory).isEagerInit();
                  }
               }, getAccessControlContext());
            }
            else {
               isEagerInit = (factory instanceof SmartFactoryBean &&
                     ((SmartFactoryBean<?>) factory).isEagerInit());
            }
            if (isEagerInit) {

               getBean(beanName);
            }
         }
         else {
            // Initialization is not a direct use of FactoryBean
            getBean(beanName);
         }
      }
   }


  
   // If the bean implements the Smart Initializing Singleton interface, it is called back here.
   for (String beanName : beanNames) {
      Object singletonInstance = getSingleton(beanName);
      if (singletonInstance instanceof SmartInitializingSingleton) {
         final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
         if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
               @Override
               public Object run() {
                  smartSingleton.afterSingletonsInstantiated();
                  return null;
               }
            }, getAccessControlContext());
         }
         else {
            smartSingleton.afterSingletonsInstantiated();
         }
      }
   }
}

As you can see, whether it's FactoryBean or not, getBean(beanName) is finally called, so keep looking at this method.

@Override
public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}

protected <T> T doGetBean(
      final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
      throws BeansException {
   // Getting the Bean Name handles two situations, one is FactoryBean (with'&'in front of it), and the other is that it can get the Bean by alias, so here it is converted to the most orthodox Bean Name.
  //The main logic is to remove aliases if they are FactoryBean s and not post codes after getting real names from aliases.
   final String beanName = transformedBeanName(name);

   //Final Return Value
   Object bean; 

   // Check if initialized
   Object sharedInstance = getSingleton(beanName);
  //If it has been initialized and no args parameter is passed, it means get, take it out and return it directly.
   if (sharedInstance != null && args == null) {
      if (logger.isDebugEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.debug("...");
         }
         else {
            logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      // Here, if it's a normal Bean, return it directly, and if it's a FactoryBean, return the instance object it created.
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

   else {
       // If this bean of prototype type type type exists
      if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
      }

      // If the current BeanDefinition does not exist and has a parent BeanFactory
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         String nameToLookup = originalBeanName(name);
        // Returns the query result of the parent container
         if (args != null) {
            return (T) parentBeanFactory.getBean(nameToLookup, args);
         }
         else {
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         }
      }

      if (!typeCheckOnly) {
         // TypeeCheckOnly is false, putting the current bean Name into an alreadyCreated Set of Sets.
         markBeanAsCreated(beanName);
      }

      /*
       * This is the time to create bean s
       */
      try {
         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // Initialize all dependent beans first, dependencies defined in dependent-on
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
            for (String dep : dependsOn) {
               // Check for cyclic dependencies
               if (isDependent(beanName, dep)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
               }
               // Register dependencies
               registerDependentBean(dep, beanName);
               // Initialize dependencies first
               getBean(dep);
            }
         }

         // If it is singular
         if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
               @Override
               public Object getObject() throws BeansException {
                  try {
                     // Perform the creation of beans, as follows
                     return createBean(beanName, mbd, args);
                  }
                  catch (BeansException ex) {
                     destroySingleton(beanName);
                     throw ex;
                  }
               }
            });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }

         // If it is prototype
         else if (mbd.isPrototype()) {
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               // Execute Create Bean
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }

         // If it's not singleton and prototype, then it's custom scope, such as session type in Web project, which is implemented by the application of custom scope.
         else {
            String scopeName = mbd.getScope();
            final Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
            }
            try {
               Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                  @Override
                  public Object getObject() throws BeansException {
                     beforePrototypeCreation(beanName);
                     try {
                        // Execute Create Bean
                        return createBean(beanName, mbd, args);
                     }
                     finally {
                        afterPrototypeCreation(beanName);
                     }
                  }
               });
               bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            }
            catch (IllegalStateException ex) {
               throw new BeanCreationException(beanName,
                     "Scope '" + scopeName + "' is not active for the current thread; consider " +
                     "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                     ex);
            }
         }
      }
      catch (BeansException ex) {
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
   }

   //Check the type of bean
   if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
      try {
         return getTypeConverter().convertIfNecessary(bean, requiredType);
      }
      catch (TypeMismatchException ex) {
         if (logger.isDebugEnabled()) {
            logger.debug("Failed to convert bean '" + name + "' to required type '" +
                  ClassUtils.getQualifiedName(requiredType) + "'", ex);
         }
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
   }
   return (T) bean;
}

Looking at the above method, we know that Spring itself only defines two kinds of Scopes, and we also know how several Scopes of Spring MVC are implemented.
Then we find that at first we will judge whether the bean exists or not, and if it exists, it will return directly. If it doesn't exist, go ahead and look at the createBean method

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
   if (logger.isDebugEnabled()) {
      logger.debug("Creating instance of bean '" + beanName + "'");
   }
   RootBeanDefinition mbdToUse = mbd;

   // Ensure that Class in BeanDefinition is loaded
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

   // Prepare method overrides if <lookup-method/> and <replaced-method/> are defined in the bean
   try {
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }

   try {
      // Return directly if there is an agent
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
         return bean; 
      }
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }
   // Create bean s
   Object beanInstance = doCreateBean(beanName, mbdToUse, args);
   if (logger.isDebugEnabled()) {
      logger.debug("Finished creating instance of bean '" + beanName + "'");
   }
   return beanInstance;
}

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
      throws BeanCreationException {

   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
     //If it is. factoryBean, it is deleted from the cache
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      // Instantiate Bean, which is the end point. Here's how
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
    //bean instance
   final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    //bean type
   Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
   mbd.resolvedTargetType = beanType;

   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         try {
            // Loop calls implement the postProcessMergedBeanDefinition method of the MergedBeanDefinitionPostProcessor interface
           // Spring has several default implementations of this interface, one of which you are most familiar with is the operation of the @Autowire annotation
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
         mbd.postProcessed = true;
      }
   }

 
   // Solving the problem of cyclic dependence
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {
      if (logger.isDebugEnabled()) {
         logger.debug("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }
     //When creating A, A depends on B, which allows for cyclic dependency by (8) putting A as an ObjectFactory in a singleton factory for early exposure, where B needs to refer to A, but A is creating, taking ObjectFactory from the singleton factory.
      addSingletonFactory(beanName, new ObjectFactory<Object>() {
         @Override
         public Object getObject() throws BeansException {
            return getEarlyBeanReference(beanName, mbd, bean);
         }
      });
   }

   Object exposedObject = bean;
   try {
      // It's important to be responsible for attribute assembly. Here's how it works
      populateBean(beanName, mbd, instanceWrapper);
      if (exposedObject != null) {
         // Here are various callbacks after processing bean s are initialized, such as init-method, InitializingBean interface, BeanPostProcessor interface.
         exposedObject = initializeBean(beanName, exposedObject, mbd);
      }
   }
   catch (Throwable ex) {
      if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
         throw (BeanCreationException) ex;
      }
      else {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      }
   }
    //Similarly, if there is a cyclic dependency
   if (earlySingletonExposure) {
      Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {
         if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
         }
         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
               if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                  actualDependentBeans.add(dependentBean);
               }
            }
            if (!actualDependentBeans.isEmpty()) {
               throw new BeanCurrentlyInCreationException(beanName,
                     "Bean with name '" + beanName + "' has been injected into other beans [" +
                     StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                     "] in its raw version as part of a circular reference, but has eventually been " +
                     "wrapped. This means that said other beans do not use the final version of the " +
                     "bean. This is often the result of over-eager type matching - consider using " +
                     "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
            }
         }
      }
   }

   // Register bean s in the corresponding Scope
   try {
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }

   return exposedObject;
}

The first initialized bean s back here, do you think it's over? No, there are several other important points.

Create bean instance createBeanInstance ()
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
   // Ensure that the class is loaded
   Class<?> beanClass = resolveBeanClass(mbd, beanName);

   // Access privileges of validation classes
   if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
            "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
   }
   
   if (mbd.getFactoryMethodName() != null)  {
      // Instance by Factory Method
      return instantiateUsingFactoryMethod(beanName, mbd, args);
   }

  //Is it the first time?
   boolean resolved = false;
  //Whether to use constructor injection or not
   boolean autowireNecessary = false;
   if (args == null) {
      synchronized (mbd.constructorArgumentLock) {
         if (mbd.resolvedConstructorOrFactoryMethod != null) {
            resolved = true;
            autowireNecessary = mbd.constructorArgumentsResolved;
         }
      }
   }
   if (resolved) {
      if (autowireNecessary) {
         return autowireConstructor(beanName, mbd, null, null);
      }
      else {
         // non-parameter constructor
         return instantiateBean(beanName, mbd);
      }
   }

   // Judging whether to use a parametric constructor
   Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
   if (ctors != null ||
         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
         mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
      // Constructor Dependency Injection
      return autowireConstructor(beanName, mbd, ctors, args);
   }

   // Calling a parametric constructor
   return instantiateBean(beanName, mbd);
}

Take a look at an unqualified structure.

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
   try {
      Object beanInstance;
      final BeanFactory parent = this;
      if (System.getSecurityManager() != null) {
         beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {

               return getInstantiationStrategy().instantiate(mbd, beanName, parent);
            }
         }, getAccessControlContext());
      }
      else {
         // Realization of concrete instantiation, look down
         beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
      }
      BeanWrapper bw = new BeanWrapperImpl(beanInstance);
      initBeanWrapper(bw);
      return bw;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
   }
}


public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {

   // If there is no method override, use java reflection to instantiate, otherwise use CGLIB.
   if (bd.getMethodOverrides().isEmpty()) {
      Constructor<?> constructorToUse;
      synchronized (bd.constructorArgumentLock) {
         constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
         if (constructorToUse == null) {
            final Class<?> clazz = bd.getBeanClass();
            if (clazz.isInterface()) {
               throw new BeanInstantiationException(clazz, "Specified class is an interface");
            }
            try {
               if (System.getSecurityManager() != null) {
                  constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
                     @Override
                     public Constructor<?> run() throws Exception {
                        return clazz.getDeclaredConstructor((Class[]) null);
                     }
                  });
               }
               else {
                  constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
               }
               bd.resolvedConstructorOrFactoryMethod = constructorToUse;
            }
            catch (Throwable ex) {
               throw new BeanInstantiationException(clazz, "No default constructor found", ex);
            }
         }
      }
      // Instance by Constructing Method
      return BeanUtils.instantiateClass(constructorToUse);
   }
   else {
      // Existence method override, the use of CGLIB to complete instantiation, need to rely on CGLIB to generate subclasses, here does not expand
      return instantiateWithMethodInjection(bd, beanName, owner);
   }
}
bean attribute injection populateBean ()
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
   // All properties of bean s
   PropertyValues pvs = mbd.getPropertyValues();

   if (bw == null) {
      if (!pvs.isEmpty()) {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      else {
         return;
      }
   }


   boolean continueWithPropertyPopulation = true;
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // If false is returned, the representative does not need to do any subsequent attribute settings or go through other BeanPostProcessor processing.
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
               continueWithPropertyPopulation = false;
               break;
            }
         }
      }
   }

   if (!continueWithPropertyPopulation) {
      return;
   }

   if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

      // Find all attribute values by name, and initialize the dependent bean if it is a bean dependency. Record dependencies
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
         autowireByName(beanName, mbd, bw, newPvs);
      }

      // Assemble by type. Complicated
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
         autowireByType(beanName, mbd, bw, newPvs);
      }

      pvs = newPvs;
   }

   boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
   boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

   if (hasInstAwareBpps || needsDepCheck) {
      PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      if (hasInstAwareBpps) {
         for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
               InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
               // Here's a BeanPostProcessor I mentioned above that handles @Autowire correctly
               // It sets values for all attributes marked with @Autowired and @Value annotations
               pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
               if (pvs == null) {
                  return;
               }
            }
         }
      }
      if (needsDepCheck) {
         checkDependencies(beanName, mbd, filteredPds, pvs);
      }
   }
   // Setting the property value of the bean instance
   applyPropertyValues(beanName, mbd, bw, pvs);
}

getBean is done.

13. finishRefresh()
protected void finishRefresh() {
        //As you can see by name, clean up the resource cache used in the previous series of operations
        clearResourceCaches();

        // Initialize Lifecycle Processor
        initLifecycleProcessor();

        // The internal implementation of this method is to start all bean s that implement the Lifecycle interface.
        getLifecycleProcessor().onRefresh();

        //Publish ContextRefreshedEvent events
        publishEvent(new ContextRefreshedEvent(this));

        // Check whether spring.liveBeansView.mbeanDomain exists, and if so, create an MBeanServer
        LiveBeansView.registerApplicationContext(this);
    }
14. resetCommonCaches()

The last step is to clear the cache

15. refresh() summary

It takes so long to sort out the details of the whole refresh() method, and here's a paste of the muddy refresh() method you just saw.


public void refresh() throws BeansException, IllegalStateException {
 
   synchronized (this.startupShutdownMonitor) {

      // Record container startup time, mark "startup" status, and check environment variables
      prepareRefresh();

      // Initialize BeanFactory container, register BeanDefinition
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Setting up the class loader for BeanFactory, adding several BeanPostProcessor s, and manually registering several special bean s
      prepareBeanFactory(beanFactory);

      try {
         // Extension Point
         postProcessBeanFactory(beanFactory);
         // Call the postProcessBeanFactory method of BeanFactoryPostProcessor implementation classes
         invokeBeanFactoryPostProcessors(beanFactory);

         // Implementing Class for Registering BeanPostProcessor
         registerBeanPostProcessors(beanFactory);

         // Initialize MessageSource
         initMessageSource();

         // Initialize Event Broadcaster
         initApplicationEventMulticaster();

         // Extension Point
         onRefresh();

         // Registered Event Listener
         registerListeners();


         // Initialize all singleton beans
         finishBeanFactoryInitialization(beanFactory);

         // Broadcasting events
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }

         // Destroy initialized beans
         destroyBeans();

         // Setting the'active'state
         cancelRefresh(ex);

         throw ex;
      }

      finally {
         // Clear Cache
         resetCommonCaches();
      }
   }
}

summary

This is the end of this article. In view of the simplicity and understandability of XML, this paper introduces the start-up process of Spring IOC based on XML, explains the creation of Bean container and the initialization process of Bean in a slightly deeper way. This is the first time that the author has read the source code of the open source framework. If there are any mistakes in the article, please take the trouble to point out.

Given the current popularity of Spring Boot and Spring Cloud, the next article will analyze Spring IOC from the annotation-based Perspective

<h4 style="color:red">recommended reading </h4>

  1. Summary of Spring Cloud Learning Series
  2. Why do we have to ask redis in front-line interviews?
  3. Summary of Essential Knowledge for Multithread Interview
  4. Java Collection Source Analysis Summary - JDK 1.8
  5. Quick Search of Common Commands in Linux-Summary
  6. Summary of JVM Series Articles
  7. Summary of MySQL Series Articles
  8. Summary of RabbitMQ Series Articles

<h4 style="color:red"> All blog articles are published in the public number "Java Learning Record". Please keep them.
You can get 2000G Java Learning Resources </h4> by scanning the code and paying attention to the public number.

Keywords: Java Spring Attribute xml

Added by g00bster on Fri, 16 Aug 2019 12:24:17 +0300