preface

Springmvc, SpringBoot, SpringCloud and many of their supporting frameworks, such as various Staters, SpringSecurity, etc., are all based on Spring, as the most fundamental part of the Spring family of source code analysis, This article will give you spring as simple as possible to explain the main process. It lays a foundation for subsequent analysis of Springboot, SpringCloud, and other relevant frameworks.

Simple example of the Spring framework

Introducing dependencies:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>4.3.11. RELEASE</version>
</dependency>
Copy the code

Define an interface:

public interface DemoService {    
  String getData();
}
Copy the code

Define the interface implementation class:

public class DemoServiceImpl implements DemoService {     
  public String getData() {        
    return "hello world"; }}Copy the code

Next, we’ll create a new configuration file in the Resources directory, which we’ll call application.xml:

<? xml version="1.0" encoding="UTF-8"? ><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       
  xmlns="http://www.springframework.org/schema/beans"       
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" 
  default-autowire="byName">     
  <bean id="demoService" class="com.wang.example.DemoServiceImpl"/>
</beans>
Copy the code

In this way, we can run:

public class App {    
  public static void main(String[] args) {  
    // Start an ApplicationContext with our configuration file
    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");         
    System.out.println("Context started successfully");         
    // Fetch our Bean from the context, which is spring's way, without going to new DemoServiceImpl
    DemoService demoService = context.getBean(demoService.class);        
    // This will output: hello worldSystem.out.println(demoService.getData()); }}Copy the code

This is one of the simplest examples of using Spring. Many people who develop directly with SpringBoot don’t know this anymore, but if you want to analyze Spring source code, you need to know how to use it. If you don’t know how to use spring source code, source analysis is out of the question.

Using this example as an entry point, let’s take a look at the Spring process.

Before the analysis, I will briefly say the process, and then verify the overall process of Spring source code is not like this:

Scans the specified “classpath: application. XML configuration files, and then scan to parse the XML document, according to the inside of the node information such as” “, instantiate the corresponding objects, object information is the information node is defined, and finally into the map collection, called “container”. The subsequent “context.getBean(Demoservice.class)” method is the instance fetched from the container (the previous map collection). The map collection is actually the Spring container, corresponding to the Spring FactoryBean class, which by its name is a class that manages beans.

Take a look at some of the FactoryBean source code:

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";

    Object getBean(String var1) throws BeansException;

    <T> T getBean(String var1, Class<T> var2) throws BeansException;

    Object getBean(String var1, Object. var2) throws BeansException; <T> T getBean(Class<T> var1) throws BeansException; <T> T getBean(Class<T> var1,Object. var2) throws BeansException; . } Follow the public account: Kylin bug change, share a copy170Multi-page Spring core learning notes.Copy the code

You can see that it is an interface that defines the various methods to get beans, which are actually retrieved from the Map collection. What is the relationship between ApplicationContext and FactoryBean in the example above?

Answer: FactoryBean is the parent of ApplicationContext, so ApplicationContext belongs to the container

The diagram above shows the BeanFactory and ApplicationContext class inheritance, as well as the main BeanFactory subclasses. This diagram will be covered in a subsequent analysis, but come back here when we talk about class diagrams.

FileSystemXmlApplicationContext constructor requires an XML configuration file path in the system and the ClassPathXmlApplicationContext function is similar, are scanning XML files are generated instances of container.

AnnotationConfigApplicationContext is used for scanning generated annotation instance container, the present springboot is done with this, wait for subsequent analysis springboot can see the source code.

Now that we know the general inheritance of the class, let’s look at the code:

ClassPathXmlApplicationContext:

public ClassPathXmlApplicationContext(
      String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
      throws BeansException {
   super(parent);
   // Set the path of the configuration file to ApplicationContext for subsequent call parsing
   setConfigLocations(configLocations);
   if (refresh) {
      // The core method of Spring parsingrefresh(); }}Copy the code

AbstractApplicationContext:

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // To prepare, record the startup time of the container, mark the "started" status, and process placeholders in the configuration file. not
      // Core logic
      prepareRefresh();

      // This is the first step of the core logic,
      / / 1. New DefaultListableBeanFactory () is the core of this container, the BeanFactory is through it
      // Get the corresponding instance object
      // 2. LoadBeanDefinitions defines the instance object in the configuration file application. XML and generates it
      // Place each BeanDefinition in a Map
      
       ,
      ,>
      // Where string is the name of the bean and BeanDefinition describes a bean class.
      // There is no instantiation yet, just the class information being parsed into the BeanDefinition.
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Do some preparatory work for the Beanfactory, which is actually a series of configuration work for the Beanfactory
      // Prepare for subsequent operations. Examples include ClassLoader and post-processors
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         // Add BeanPostProcessor for subclasses to use
         / / subsequent finishBeanFactoryInitialization method will be called after complete instantiation
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         // Register the BeanPostProcessor implementation class. Note the difference between BeanPostProcessor and BeanFactoryPostProcessor
         / / the interface of two methods: postProcessBeforeInitialization and postProcessAfterInitialization
         / / follow-up will trigger in finishBeanFactoryInitialization
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         initMessageSource();

         // Initializes the ApplicationContext event announcer, which is the core spring publicEvent method.
         // It is used to send event notifications. Listeners can listen for emitted events, which is useful in practice.
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         // The hook function for subclass extension.
         // --------------------------------------------------------
         // In SpringBoot, there are subclasses that implement this method, and then create
         / / out of embedded tomcat container, created WebServerStartStopLifecycle, for tomcat startup
         // This will be explained in my next article
         onRefresh();

         // Check for listener beans and register them.
         / / of all the Listeners registered, the above initApplicationEventMulticaster method to register the broadcast
         // The last broadcast event is listened for by the listener here.
         // --------------------------------------------------------
         // When SpringBoot starts, it does various initialization operations. Keep an eye on my later articles
         registerListeners();

         // This is the most important, the core logical instance and initializes all Singleton beans
         finishBeanFactoryInitialization(beanFactory);

         // Call the onRefresh() method of LifecycleProcessor and send the ContextRefreshedEvent event.
         // The final work belongs to.
         // --------------------------------------------------------
         / / for springboot created WebServerStartStopLifecycle in the onRefresh method above,
         / / in this step will call WebServerStartStopLifecycle onRefresh method, complete springboot inline
         // Start the Tomcat container.
         // Later I will open a separate article about springBoot source code will mention this, please follow me.finishRefresh(); }... }}Copy the code

This is the main process, and I’ve commented all of it, and I’ve commented all of the code related to SpringBoot. To prepare for the subsequent analysis of Springboot source code, I hope you pay more attention to my follow-up article.

Only the core spring-related code is analyzed here:

obtainFreshBeanFactory

finishBeanFactoryInitialization

ObtainFreshBeanFactory process analysis

This is done by creating the bean container and registering the corresponding BeanDefinition into the container

AbstractApplicationContext:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   // Create a new BeanFactory, load the Bean definition, and register the Bean
   refreshBeanFactory();
   return getBeanFactory();
}
Copy the code

AbstractRefreshableApplicationContext:

protected final void refreshBeanFactory() throws BeansException {
   // If BeanFactory is already loaded and all beans in BeanFactory are destroyed, close the BeanFactory
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      / / create the BeanFactory, create a subclass is DefaultListableBeanFactory, why use this subclass?
      / / the following said
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      // Set two configuration properties of BeanFactory: whether Bean overrides are allowed and whether circular references are allowed
      customizeBeanFactory(beanFactory);
      // Load the Bean into the BeanFactory
      loadBeanDefinitions(beanFactory);
      // Set the container to the current ApplicationContext
      this.beanFactory = beanFactory;
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for "+ getDisplayName(), ex); }}Copy the code

Why use DefaultListableBeanFactory subclass? Take a look at this class diagram

DefaultListableBeanFactory inherited almost all the BeanFactory related classes, traditionally the function of the inherited, it it a newbest, so it was created.

Also mentioned in the previous code BeanDefinition, it is very important to a class in the spring, save the definition of XML bean class information, English translation is also one of the mean “bean definitions”, look at its code is as follows:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
   // The way classes are created in Spring
   // A singleton has only one instance, i.e., a singleton.
   // prototype creates one instance at a time, equivalent to new.
   String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
   StringSCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE; .// Set the parent BeanName
   void setParentName(String parentName);
 
   // Get the parent BeanName
   String getParentName();
 
   // Set the class name of the Bean
   void setBeanClassName(String beanClassName);
 
   // Get the class name of the Bean
   String getBeanClassName();
 
 
   // Set the scope of the bean
   void setScope(String scope);
 
   String getScope();
 
   // Set lazy loading
   void setLazyInit(boolean lazyInit);
 
   boolean isLazyInit();
 
   // Set all the beans that the Bean depends on. Note that the dependencies here are not property dependencies (as in the @autowire tag).
   // Is the value set by the depends-on="" attribute.
   void setDependsOn(String. dependsOn);// Returns all dependencies for the Bean
   String[] getDependsOn();
 
   // Set whether this Bean can be injected into other beans, only for injection by type,
   // If you inject by name, this works even if false is set here
   void setAutowireCandidate(boolean autowireCandidate);
 
   // Whether this Bean can be injected into other beans
   boolean isAutowireCandidate();
 
   // Main. Multiple implementations of the same interface. If no name is specified, Spring will preferentially select beans with primary set to true
   void setPrimary(boolean primary);
 
   // Is primary
   boolean isPrimary();
 
   // Specify the factory name if the Bean is generated using the factory method. For readers unfamiliar with the factory, please enter the appendix
   void setFactoryBeanName(String factoryBeanName);
   // Get the factory name
   String getFactoryBeanName();
   // Specify the name of the factory method in the factory class
   void setFactoryMethodName(String factoryMethodName);
   // Get the factory method name in the factory class
   String getFactoryMethodName();
 
   // Constructor arguments
   ConstructorArgumentValues getConstructorArgumentValues();
 
   // The property value in the Bean, which will be described later when injecting the property value into the Bean
   MutablePropertyValues getPropertyValues();
 
   / / if the singleton
   boolean isSingleton();
 
   / / whether the prototype
   boolean isPrototype();
 
   // If the Bean is an abstract class natively, it cannot be instantiated
   boolean isAbstract();
 
   int getRole();
   String getDescription();
   String getResourceDescription();
   BeanDefinition getOriginatingBeanDefinition();
}
Copy the code

As you can see, the BeanDefinition defines all of the bean’s information, which allows you to instantiate a bean.

Then analyze the code above:

There are two main methods as follows

customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory)
Copy the code
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
   if (this.allowBeanDefinitionOverriding ! =null) {
      // Sets whether the bean class definition is allowed to be overridden with a bean name, replacing the previous one.
      // If it is allowed, it will be replaced; if it is not allowed, an exception will be thrown.
      // Spring defaults to true, which is allowed.
      beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
   if (this.allowCircularReferences ! =null) {
      // Set whether circular dependencies are allowed and resolve the problem automatically. The default is true.
      // A cyclic dependency is A class A dependent on B, which is A cyclic dependency.
      // Spring solves this problem by using singletons (many tutorials are called caching, so it doesn't matter)
      // when A is instantiated, it will be placed in the map container
      // if B is dependent on A, then A already exists in the map.
      // So just return, so that the loop does not continue.
      beanFactory.setAllowCircularReferences(this.allowCircularReferences); }}Copy the code

Moving on to loadBeanDefinitions, which is the main one, parses the XML and registers the BeanDefinition into the container.

@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // Instantiate an XmlBeanDefinitionReader for BeanFactory
   // Is used to parse XML
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

   // Configure the bean definition reader with this context's
   // resource loading environment.
   beanDefinitionReader.setEnvironment(this.getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   // Not important, skip
   initBeanDefinitionReader(beanDefinitionReader);
   // Follow up on it, mainline logic
   loadBeanDefinitions(beanDefinitionReader);
}
Copy the code

The loadBeanDefinitions call will eventually register the beanDefinition with the container

It’s a lot of calls, and I’m going to draw this in sequence.

Finally, this method is called to register the BeanDefinition with the container. The core methods are listed below.

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
      throws BeanDefinitionStoreException {

      ...
      
   BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
   // If the BeanDefinition already exists
   if(existingDefinition ! =null) {
      // Check whether overwriting is allowed
      if(! isAllowBeanDefinitionOverriding()) {// Throw an exception if overwriting is not allowed. We examined this property previously
         throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
      }
      // Register with the container, overwriting the original bean.
      this.beanDefinitionMap.put(beanName, beanDefinition);
   }
   else {
      // The bean does not exist
      if (hasBeanCreationStarted()) {
         // The process has been created. Lock it to avoid conflicts
         // Cannot modify startup-time collection elements anymore (for stable iteration)
         synchronized (this.beanDefinitionMap) {
            // Put it in the container
            this.beanDefinitionMap.put(beanName, beanDefinition);
            List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
            updatedDefinitions.addAll(this.beanDefinitionNames);
            updatedDefinitions.add(beanName);
            this.beanDefinitionNames = updatedDefinitions; removeManualSingletonName(beanName); }}else {
         // Register beanDefinition in the container
         this.beanDefinitionMap.put(beanName, beanDefinition);
         this.beanDefinitionNames.add(beanName);
         removeManualSingletonName(beanName);
      }
      this.frozenBeanDefinitionNames = null; }... }Copy the code

At this point, the obtainFreshBeanFactory process is finally finished.

Then continue to finishBeanFactoryInitialization core processes, the class instantiation, the code is as follows:

AbstractApplicationContext

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   // instantiate the Bean named conversionService.
   The beanFactory.getBean method triggers the instantiation operation.
   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)); }...// Stop using the temporary ClassLoader for type matching.
   beanFactory.setTempClassLoader(null);
 
   // Freeze the beanDefinition information, at this point the instantiation will begin, and the information is not expected to be modified.
   // Set a freeze flag
   beanFactory.freezeConfiguration();
 
   // Instantiate the bean process
   beanFactory.preInstantiateSingletons();
}
Copy the code

DefaultListableBeanFactory:

@Override
public void preInstantiateSingletons() throws BeansException {
   if (this.logger.isDebugEnabled()) {
      this.logger.debug("Pre-instantiating singletons in " + this);
   }
 
   List<String> beanNames = new ArrayList<String> (this.beanDefinitionNames);
 
   Trigger the initialization of all non-lazy-loaded Singleton beans
   for (String beanName : beanNames) {
 
      < Bean id="" class="" "parent="" />
      // There will be an article on this later
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
 
      // Non-abstract, non-lazy-loaded singletons.
      if(! bd.isAbstract() && bd.isSingleton() && ! bd.isLazyInit()) {// Handle FactoryBean. Note the difference between FactoryBean and BeanFactory
         // Write an article to explain it
         if (isFactoryBean(beanName)) {
            // For a FactoryBean, prefix beanName with an am& and call getBean,
            // The core method of the getBean method instantiates the bean because it is preceded by the ampersand, so
            // Get an object of type FactoryBean.
            // --------------------------------------------------
            // This is a brief introduction to defining a class that implements the getObject method in FactoryBean, getBean
            // If the name is preceded by a '&' to get the object itself, for example, the Demo class implements a FactoryBean, and then you
            // getBean("&demo") to get the demo itself.
            // --------------------------------------------------
            // So the getBean in the source code will implement you as a FactoryBean
            // instantiate the class and place it in the Spring container.
            // Later when you call getBean(' demo ') in the program without the ampersand, and so on
            // You will find that your instance object already exists in the container (such as Demo in the above example),
            // Because you didn't add the ampersand this time, the process will be different and it will call the getObject method of the demo instance.
            // Of course, this is just instantiating the class that implements The FactoryBean and putting it into the container
            final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
            ...
         }
         else {
            For normal beans, just call getBean(beanName) to initialize themgetBean(beanName); }}}// All non-lazy-loaded Singleton Beans have been initialized
   / / if we define the bean is realized SmartInitializingSingleton interface, so get back here, ignored
   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(); }}}}Copy the code

Next parse the getBean, which calls the doGetBean method to parse it:

protected <T> T doGetBean(
      String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
      throws BeansException {

   String beanName = transformedBeanName(name);
   Object bean;

   // Check whether the object has been instantiated, if so, directly from cache.
   // If not registered, null is returned. It involves level 3 caching (as many articles call it).
   Object sharedInstance = getSingleton(beanName);
   if(sharedInstance ! =null && args == null) {
      if (logger.isTraceEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
            logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); }}// This method checks if the bean implements a FactoryBean and calls its getObject method.
      // If not, return the instance directly.
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

   else{...try {
         RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // Check whether the current bean has a depends-on configuration and instantiate the dependencies first.
         // Corresponding annotation @dependson
         String[] dependsOn = mbd.getDependsOn();
         if(dependsOn ! =null) {
            for (String dep : dependsOn) {
               if (isDependent(beanName, dep)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
               }
               registerDependentBean(dep, beanName);
               try {
                  getBean(dep);
               }
               catch (NoSuchBeanDefinitionException ex) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex); }}}// Create singleton object, main logic.
         if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
               try {
                  // Perform specific instantiation operations
                  return createBean(beanName, mbd, args);
               }
               catch (BeansException ex) {
                  // Explicitly remove instance from singleton cache: It might have been put there
                  // eagerly by the creation process, to allow for circular reference resolution.
                  // Also remove any beans that received a temporary reference to the bean.
                  destroySingleton(beanName);
                  throwex; }}); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }// Create a non-singleton object if it is not a singleton
         else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }

         else{... Leave out unimportant code}}catch (BeansException ex) {
         cleanupAfterBeanCreationFailure(beanName);
         throwex; }}// If a requiredType is passed in, it checks whether the requiredType matches the bean type and attempts to convert it,
   / / conversionService finishBeanFactoryInitialization method initially has mentioned, it is
   // I will try to convert the date format
   // Convert.
   if(requiredType ! =null && !requiredType.isInstance(bean)) {
      try {
         T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
         if (convertedBean == null) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
         }
         return convertedBean;
      }
      catch (TypeMismatchException ex) {
         if (logger.isTraceEnabled()) {
            logger.trace("Failed to convert bean '" + name + "' to required type '" +
                  ClassUtils.getQualifiedName(requiredType) + "'", ex);
         }
         throw newBeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); }}return(T) bean; } Follow the public account: Kylin bug change, share a copy170Multi-page Spring core learning notes.Copy the code

Next, look at the createBean method, which performs the specific instantiation and puts the instantiated object into the container.

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

   // Make sure the Class in BeanDefinition is loadedClass<? > resolvedClass = resolveBeanClass(mbd, beanName);if(resolvedClass ! =null&&! mbd.hasBeanClass() && mbd.getBeanClassName() ! =null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }
  // Prepare method override, not important
   try {
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }

   try {
      // Provide BeanPostProcessors with an opportunity to replace the current bean and return your own proxy
      / / bean.
      / / postProcessBeforeInstantiation and postProcessAfterInstantiation corresponding method.
      // The method entry is a bean, and the return is a bean, giving you the opportunity to replace it in the method.
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if(bean ! =null) {
         returnbean; }}catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }

   try {
      // The core method for creating the instance
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isTraceEnabled()) {
         logger.trace("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   }
   catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      // A previously detected exception with proper bean creation context already,
      // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
      throw ex;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); }}Copy the code

AbstractAutowireCapableBeanFactory:

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

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      // instantiate the object
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   Objectbean = instanceWrapper.getWrappedInstance(); Class<? > beanType = instanceWrapper.getWrappedClass();if(beanType ! = NullBean.class) { mbd.resolvedTargetType = beanType; }...// To solve the loop dependency problem
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {
      if (logger.isTraceEnabled()) {
         logger.trace("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
      // Handle dependency injection operations such as @autowaried, @resource, and attribute assignment of instance objects.
      populateBean(beanName, mbd, instanceWrapper);
      // Call various callback functions. Like the callback of the BeanPostProcessor interface,
      // InitializingBean interface afterPropertiesSet callback interface, and various
      // Aware interface.exposedObject = initializeBean(beanName, exposedObject, mbd); }...return exposedObject;
}
Copy the code

This saves unnecessary code.

So far the general situation has been relatively clear, if you are interested in further analysis.

The initializeBean method is analyzed here, because it is used more in work.

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
   if(System.getSecurityManager() ! =null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         invokeAwareMethods(beanName, bean);
         return null;
      }, getAccessControlContext());
   }
   else {
      // Invoke the interfaces of each Aware subclass
      invokeAwareMethods(beanName, bean);
   }

   Object wrappedBean = bean;
   if (mbd == null| |! mbd.isSynthetic()) {/ / call interface BeanPostProcessors postProcessBeforeInitialization method
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }

   try {
      // Call the afterPropertiesSet method of the InitializingBean interface
      // it is used to do some initialization after startup.
      invokeInitMethods(beanName, wrappedBean, mbd);
   }
   catch (Throwable ex) {
      throw newBeanCreationException( (mbd ! =null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
   }
   if (mbd == null| |! mbd.isSynthetic()) {/ / call interface BeanPostProcessors postProcessAfterInitialization method
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

   return wrappedBean;
}
Copy the code

conclusion

The whole process of the string again, there are more detailed notes. There are a lot of options that Spring leaves open for developers to use for extension callbacks. These extension ports are also very useful, limited by space, I will write a later article to explain these important extension points with the source code.

Next will be with you to analyze Springboot, SpringCloud, Mybatis, springAOP and other source analysis, Spring is the foundation must first understand this article, you can compare the code, with their own again, this understand, the subsequent analysis is simple.

If you like the article, remember to pay attention to me and give a thumbs-up. Thank you for your support! Important things say three times, forward + forward + forward, must remember to forward oh!!