package com.example.demo.springcontext;

import com.example.demo.beanfactory.Car;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author <a href="mailto:[email protected]">linxiaohui</a> * @version 1.0 18/10/11 * @since 1.0 */ public Class ApplicationContextTest {public static void main(String[] args) { AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        Car car = ctx.getBean("car", Car.class); car.introduce(); }}Copy the code

ClassPathXmlApplicationContext constructor

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
   this(new String[] {configLocation}, true.null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
      throws BeansException {

   super(parent);
   // Parse incoming configuration file names, such as placeholders in file names, and replace them with real values
   setConfigLocations(configLocations);
   if (refresh) {
      // Call the container's start methodrefresh(); }}Copy the code

Let’s take a look at the steps to start the Spring container as a whole, and then take a step-by-step look at what each step does.

public void refresh(a) throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // 1. Preparation before container startup
      prepareRefresh();

      // Initialize the beanFactory, load the configuration file, convert to BeanDefinitions, and register these BeanDefinitions
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Set some attributes of beanFactory to enhance the function
      prepareBeanFactory(beanFactory);

      try {
         // After step 3, you can do some post-processing for the beanFactory. Implemented by subclass extension
         postProcessBeanFactory(beanFactory);

         // Call the beanFactory postprocessing method registered in the container
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register the bean's backend handler. Tips: Trigger time is after the bean is instantiated, around the time the bean is initialized.
         registerBeanPostProcessors(beanFactory);

         // Initialize the resources used for internationalization
         initMessageSource();

         // 8. Initialize the event broadcaster
         initApplicationEventMulticaster();

         Initialize other special beans to be implemented by specific subclasses
         onRefresh();

         // 10. Register event listener to publish events that need to be broadcast in advance
         registerListeners();

         // instantiate the remaining non-lazy-loaded singletons
         finishBeanFactoryInitialization(beanFactory);

         // 12. Finish the container startup, process the post-event and publish the notification event
         finishRefresh();
      }

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

         // Destroy already created singletons to avoid dangling resources.
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // Propagate exception to caller.
         throw ex;
      }

      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...resetCommonCaches(); }}}Copy the code


Step1. Preparation work before container startup

/** * Prepare this context for refreshing, setting its startup date and * active flag as well as performing any initialization of property sources. */
protected void prepareRefresh(a) {
   // Set the boot time
   this.startupDate = System.currentTimeMillis();
   // Set the container state
   this.closed.set(false);
   this.active.set(true);

   if (logger.isInfoEnabled()) {
      logger.info("Refreshing " + this);
   }

   // Initializes the file, implemented by subclasses
   initPropertySources();

   // Verify that the required attribute already exists
   // see ConfigurablePropertyResolver#setRequiredProperties
   getEnvironment().validateRequiredProperties();

   // Save events that the container needs to broadcast in advance
   // Tips: These early events are broadcast directly to registerListeners when they are registered
   this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}Copy the code

The first step is mainly to do some state Settings before container startup, as well as the verification of necessary properties.


Step2 initialize the beanFactory and load the configuration file

protected ConfigurableListableBeanFactory obtainFreshBeanFactory(a) {
   // Look at the method code
   refreshBeanFactory();
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (logger.isDebugEnabled()) {
      logger.debug("Bean factory for " + getDisplayName() + ":" + beanFactory);
   }
   return beanFactory;
}

protected final void refreshBeanFactory(a) throws BeansException {
   // The beanFactory already exists
   if (hasBeanFactory()) {
      // Clear all singleton caches
      destroyBeans();
      // Set beanFactory to null
      closeBeanFactory();
   }
   try {
      / / create the beanFactory DefaultListableBeanFactory instance
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      // Set the serialization ID
      beanFactory.setSerializationId(getId());
      // Custom property Settings: 1, whether to allow the same bean(the latter overrides the former), 2, whether to allow cyclic dependencies
      customizeBeanFactory(beanFactory);
      // Load the parsed XML file configuration, convert it to the in-memory beanDefinition format, and register it in the corresponding collection list
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory; }}catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for "+ getDisplayName(), ex); }}Copy the code

Step 2 basically creates a new beanFactory, sets the serialization ID, and custom attributes, and then parses the XML configured bean information for use.

Step3. Set some attributes of beanFactory to extend functions

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   // Set AppClassLoader as the class loader
   beanFactory.setBeanClassLoader(getClassLoader());
   // Set up the Spring EL expression parser
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
   // Set the property editor
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

   // Set up the bean post-handler so that we can fetch the entire container and inject resources. (EnvironmentAware, EmbeddedValueResolverAware
   / /, ResourceLoaderAware, ApplicationEventPublisherAware MessageSourceAware, ApplicationContextAware)
   // used when the bean is instantiated. PreInstantiateSingletons ()->getBean() ->
   / / doGetBean () - > createBean () - > doCreateBean () - > initializeBean () - > invokeAwareMethods ())
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
   // Ignore the resources automatically injected by the processor after the previous registration
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

   // Register Spring's own system beans, distinguished from business beans
   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
   beanFactory.registerResolvableDependency(ResourceLoader.class, this);
   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
   beanFactory.registerResolvableDependency(ApplicationContext.class, this);

   / / registered ApplicationListenerDarecror post processor, to implement the interface ApplicationListener singleton
   // Register to the container's event collection
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

   // AOP support. This is not extended and will be analyzed in the AOP module later
   if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      // Set a temporary ClassLoader for type matching.
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }

   // Register the default system environment bean. (The details can be viewed at the interrupt point, such as placeholder prefix '${', suffix '}', value delimiter ':', etc.)
   if(! beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); }if(! beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME,  getEnvironment().getSystemProperties()); }if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
   }
}Copy the code


Step4. After completing step 3, do some post-processing for beanFactory. Extend by subclasses

/**
 * Modify the application context's internal bean factory after its standard
 * initialization. All bean definitions will have been loaded, but no beans
 * will have been instantiated yet. This allows for registering special
 * BeanPostProcessors etc in certain ApplicationContext implementations.
 * @param beanFactory the bean factory used by the application context
 */
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // After beanFactory loads the parsed XML configuration file and before the bean is instantiated, subclasses can do some special processing at this time, yes
    //beanFactory implements attribute enhancement (see the implementation of different container subclasses)
}Copy the code


Step5. Call the beanFactory post-processor method registered in the container

Let’s start with the spring container extension point. Let’s briefly talk about BeanPostProcessor and BeanFactoryPostProcessor.

BeanPostProcessor is executed after the Spring container loads the bean definition file and instantiates the bean, respectively, before and after the bean calls to initialize init-method. (Operation target object is bean object)

BeanFactoryPostProcessor is executed after the Spring container loads the bean definition file (XML file) and before the bean is instantiated. (Operation target object is beanFactory object)

Now that we know the timing and purpose of both, we can move on. The detailed use of both will not be expanded here.

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   // Core code, see comments below
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

   // AOP support. This is not extended and will be analyzed in the AOP module later
   if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      beanFactory.setTempClassLoader(newContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); }}Copy the code

/ / code before you see here, first of all need to know, BeanDefinitionRegistryPostProcessor spring BeanFactoryPostProcessor as part of the interface, the interface
// Extends the parent interface, so the following is done separately for both processors
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List
       
         beanFactoryPostProcessors)
        {

   // Invoke BeanDefinitionRegistryPostProcessors first, if any.
   Set<String> processedBeans = new HashSet<String>();
   // Whether BeanDefinitionRegistry is of type
   if (beanFactory instanceof BeanDefinitionRegistry) {
      BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
      // Save the BeanFactoryPostProcessor processor
      List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
      / / save BeanDefinitionRegistryPostProcessor post processor
      List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();
      / / traverse manual coding registered BeanFactoryProcessor (view into the cords getBeanFactoryPostProcessors ())
      for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
         / / if BeanDefinitionRegistryPostProcessor
         if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
            BeanDefinitionRegistryPostProcessor registryProcessor =
                  (BeanDefinitionRegistryPostProcessor) postProcessor;
            / / call BeanDefinitionRegistryPostProcessor extended method first
            registryProcessor.postProcessBeanDefinitionRegistry(registry);
            // Put it into the collection of registryProcessors, then call the method inherited from the parent interface
            registryProcessors.add(registryProcessor);
         }
         else {
            // Add regularPostProcessors to the collectionregularPostProcessors.add(postProcessor); }}// Do not initialize FactoryBeans here: We need to leave all regular beans
      // uninitialized to let the bean factory post-processors apply to them!
      // Separate between BeanDefinitionRegistryPostProcessors that implement
      // PriorityOrdered, Ordered, and the rest.
      // temporary set
      List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();

      / / get all realized BeanDefinitionRegistryPostProcessor bean in the configuration file name
      String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
      // Walk through the beans in the configuration file
      for (String ppName : postProcessorNames) {
         // If the PriorityOrdered interface is implemented
         if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // Put it into the temporary collection
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            // Add to the set that has already been executed to prevent repeated execution.processedBeans.add(ppName); }}// Sort the processor beans that implement the PriorityOrer interface
      sortPostProcessors(currentRegistryProcessors, beanFactory);
      / / the BeanDefinitionRegistryPostProcessor into registryProcessors list in the configuration file
      registryProcessors.addAll(currentRegistryProcessors);
      / / implementation in BeanDefinitionRegistryPostProcessor extension method
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
      // Clear the temporary collection
      currentRegistryProcessors.clear();

      / / this special processing to realize the interface Ordered BeanDefinitionRegistryPostProcessor processor, as well as the above steps,
      // This editor is not easy to use, so I will not repeat typing.
      postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
      for (String ppName : postProcessorNames) {
         if(! processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));  processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear();/ / to the execution of the remaining BeanDefinitionRegistryPostProcessors the above steps.
      boolean reiterate = true;
      while (reiterate) {
         reiterate = false;
         postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
         for (String ppName : postProcessorNames) {
            if(! processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate =true;
            }
         }
         sortPostProcessors(currentRegistryProcessors, beanFactory);
         registryProcessors.addAll(currentRegistryProcessors);
         invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
         currentRegistryProcessors.clear();
      }

      / / perform all BeanDrfinitionRegistryPostProcessor (including manual coding registered and configured in the configuration file)
      // Inherits methods from BeanFactoryPostProcessor
      invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
      // Executes the post-processing of all manually encoded BeanFactoryPostProcessor registrations
      invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
   }

   else {
      // Directly execute the manual encoding registration of the post-processor method
      invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
   }

   // Do not initialize FactoryBeans here: We need to leave all regular beans
   // uninitialized to let the bean factory post-processors apply to them!
   // Get the BeanFactoryPostProcessor configured in all the configuration files.
   String[] postProcessorNames =
         beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true.false);

   // The following steps are to implement the PriortyOrdered,Ordered, and unimplemented interfaces for the BeanFactory postprocessor configured in the configuration file
   // Sort, sort, sort, sort, sort
   List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
   List<String> orderedPostProcessorNames = new ArrayList<String>();
   List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
   for (String ppName : postProcessorNames) {
      if (processedBeans.contains(ppName)) {
         // skip - already processed in first phase above
      }
      else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
         priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
      }
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
         orderedPostProcessorNames.add(ppName);
      }
      else{ nonOrderedPostProcessorNames.add(ppName); }}// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
   sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
   invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

   // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
   List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
   for (String postProcessorName : orderedPostProcessorNames) {
      orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
   }
   sortPostProcessors(orderedPostProcessors, beanFactory);
   invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

   // Finally, invoke all other BeanFactoryPostProcessors.
   List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
   for (String postProcessorName : nonOrderedPostProcessorNames) {
      nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
   }
   invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

   / / as the method of rear spring BeanFactoryPostProcessor processor may modify the metadata, such as replacing attribute value is accomplished
   // placeholder, so the relevant cache needs to be cleaned
   beanFactory.clearMetadataCache();
}Copy the code


Step6: register the bean’s post-processor.

/** * Instantiate and invoke all registered BeanPostProcessor beans, * respecting explicit order if given. * 

Must be called before any instantiation of application beans. */

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); }Copy the code

public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
   // Get the BeanPostProcessor configured in all configuration files
   String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true.false);

   / / beanProcessorTargetCount = manually register BeanPostProcessor number + 1 + the BeanPostProcessor quantity is configured in the configuration file
   // Add 1 because you need to register BeanPostProcessorChecker for logging.
   int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
   // Register BeanPostProcessorChecker to log the instantiation of other beans before the post-processor is registered
   beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

   // BeanPostProcessors are implemented in PriorityOrdered,Ordered, and unimplemented order. (and the BeanFactory postposition above
   // The processor handles it the same way.
   List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
   List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
   List<String> orderedPostProcessorNames = new ArrayList<String>();
   List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
   for (String ppName : postProcessorNames) {
      if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
         BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
         priorityOrderedPostProcessors.add(pp);
         if (pp instanceof MergedBeanDefinitionPostProcessor) {
            / / the MergedBeanDefinitionPostProcessor types of carrying outinternalPostProcessors.add(pp); }}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
         orderedPostProcessorNames.add(ppName);
      }
      else{ nonOrderedPostProcessorNames.add(ppName); }}// First, register the BeanPostProcessors that implement PriorityOrdered.
   sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

   // Next, register the BeanPostProcessors that implement Ordered.
   List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
   for (String ppName : orderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      orderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         / / the MergedBeanDefinitionPostProcessor types of carrying out
         internalPostProcessors.add(pp);
      }
   }
   sortPostProcessors(orderedPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, orderedPostProcessors);

   // Now, register all regular BeanPostProcessors.
   List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
   for (String ppName : nonOrderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      nonOrderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         / / the MergedBeanDefinitionPostProcessor types of carrying out
         internalPostProcessors.add(pp);
      }
   }
   registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

   / / sorting, registration again MergedBeanDefinitionPostProcessor types of beans (registered will is cleared to register again)
   sortPostProcessors(internalPostProcessors, beanFactory);
   // In effect, these types of processors are registered last
   registerBeanPostProcessors(beanFactory, internalPostProcessors);

   / / register ApplicationListenerDetector
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}Copy the code


Step7 initialize the resources used for internationalization

public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";/** * Initialize the MessageSource. * Use parent's if none defined in this context. */
protected void initMessageSource(a) {
   / / get the BeanFactory
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   // If there is a bean named messageSource (here hardcoded by Spring)
   if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
      // Initialize the bean
      this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
      // Establish a connection between MessageSource and parent MessageSource.
      if (this.parent ! =null && this.messageSource instanceof HierarchicalMessageSource) {
         HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
         if (hms.getParentMessageSource() == null) {
            // Only set parent context as parent MessageSource if no parent MessageSource
            // registered already.hms.setParentMessageSource(getInternalParentMessageSource()); }}if (logger.isDebugEnabled()) {
         logger.debug("Using MessageSource [" + this.messageSource + "]"); }}else {
      // It does not exist. This creates an empty MessageSource to process the resource request and names it MessageSource
      DelegatingMessageSource dms = new DelegatingMessageSource();
      dms.setParentMessageSource(getInternalParentMessageSource());
      this.messageSource = dms;
      beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
      if (logger.isDebugEnabled()) {
         logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
               "': using default [" + this.messageSource + "]"); }}}Copy the code


Step8 initialize the event broadcaster (observer mode)

For those who are not familiar with the Observer pattern, the implementation of this pattern is relatively simple, but it is very helpful to understand Spring event broadcasting and listening.

public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";

/**
 * Initialize the ApplicationEventMulticaster.
 * Uses SimpleApplicationEventMulticaster if none defined in the context.
 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
 */
protected void initApplicationEventMulticaster(a) {
   / / get the BeanFactory
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   / / contains named applicationEventMulticaster bean (hard-coded multicast)
   if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
      this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
      if (logger.isDebugEnabled()) {
         logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); }}else {
      / / does not contain, then create a SimpleApplicationEventMulticaster and named applicationEventMulticaster
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
      if (logger.isDebugEnabled()) {
         logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
               APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
               "': using default [" + this.applicationEventMulticaster + "]"); }}}Copy the code


Step9 initialize other special beans and have specific subclass containers to implement them

/**
 * Template method which can be overridden to add context-specific refresh work.
 * Called on initialization of special beans, before instantiation of singletons.
 * <p>This implementation is empty.
 * @throws BeansException in case of errors
 * @see #refresh()
 */
protected void onRefresh() throws BeansException {
   // For subclasses: do nothing by default.
}Copy the code


Step10 register event listeners and publish events that need to be broadcast in advance

/** * Add beans that implement ApplicationListener as listeners. * Doesn't affect other listeners, which can be added without being beans. */
protected void registerListeners(a) {
   // Register all manually encoded event listeners
   for(ApplicationListener<? > listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); }// Register event listeners configured for all configuration files
   String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true.false);
   for (String listenerBeanName : listenerBeanNames) {
      getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
   }

   // Publish events that need to be broadcast in advance
   Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
   this.earlyApplicationEvents = null;
   if(earlyEventsToProcess ! =null) {
      for(ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); }}}Copy the code

Let’s look at the use of the observer mode through the specific event broadcast method

@Override
public void multicastEvent(ApplicationEvent event) {
   multicastEvent(event, resolveDefaultEventType(event));
}

@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
   ResolvableType type= (eventType ! = null ? eventType : resolveDefaultEventType(event)); // Iterate over all listeners listening for the eventfor(final ApplicationListener<? > listener : getApplicationListeners(event,type)) {
      Executor executor = getTaskExecutor();
      if(executor ! = null) { executor.execute(newRunnable() {
            @Override
            public void run() {invokeListener(listener, event); }}); }else{ invokeListener(listener, event); }}}Copy the code


Step11. Instantiate the remaining singletons without lazy loading

String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
/**
 * Finish the initialization of this context's bean factory, * initializing all remaining singleton beans. */ protected void FinishBeanFactoryInitialization (ConfigurableListableBeanFactory the beanFactory) {/ / type converter, 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 there is no default embedded value resolver, register an if (! beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(new StringValueResolver() { @Override public String resolveStringValue(String strVal) { return getEnvironment().resolvePlaceholders(strVal); }}); } // AOP functions, Subsequent analysis in AOP module String [] weaverAwareNames. = the beanFactory getBeanNamesForType (LoadTimeWeaverAware. Class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } / / deactivate type to match class loaders have been created. The beanFactory setTempClassLoader (null); Freezing / / modification, all the bean metadata caching. The beanFactory freezeConfiguration (); / / instantiate all the lazy loading of bean. The beanFactory preInstantiateSingletons (); }Copy the code

Let’s take a quick look at the instantiation steps

@Override
public void preInstantiateSingletons() throws BeansException {
   if (this.logger.isDebugEnabled()) {
      this.logger.debug("Pre-instantiating singletons in " + this);
   }

   // Iterate over a copy to allow for init methods which inturn register new bean definitions. // While this may not be part of the regular factory bootstrap, List<String> beanNames = new ArrayList<String>(this.beandefinitionNames); / / traversefor(String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // non-abstract && singleton && non-lazy loadingif(! bd.isAbstract() && bd.isSingleton() && ! Bd.islazyinit ()) {// If it is a FactoryBeanif(isFactoryBean(beanName)) {// '&' + beanName Gets the FactoryBean itself. Final FactoryBean<? > factory = (FactoryBean<? >) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; // Determine if the bean needs to be loaded immediatelyif(System.getSecurityManager() ! = null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { @Override public Booleanrun() {
                     return((SmartFactoryBean<? >) factory).isEagerInit(); } }, getAccessControlContext()); }else{ isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<? >) factory).isEagerInit()); }if(isEagerInit) { getBean(beanName); }}else{// Load the normal bean getBean(beanName); }}} / / implements SmartInitializingSingleton singleton, can trigger afterSingletonsInstantiated callback methodsfor (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 Objectrun() {
                  smartSingleton.afterSingletonsInstantiated();
                  return null;
               }
            }, getAccessControlContext());
         }
         else{ smartSingleton.afterSingletonsInstantiated(); }}}}Copy the code


Step12. Container refresh is completed, and container startup post-event and release completion notification event are processed

protected void finishRefresh() {// Initialize lifecycleProcessor initLifecycleProcessor(); // Get all beans that implement Lifecycle and execute start() getLifecycleProcessor().onRefresh(); // publishEvent(new ContextRefreshedEvent(this)); / / the current vessel registration to the collection of LiveBeansView LiveBeansView. RegisterApplicationContext (this); }Copy the code

      

Well, this is the end of the Spring container startup process. There are many points in the middle that can be extended. In view of my limited level, some points may not be detailed. I will try to supplement some analysis articles later, which is better than nothing. 😄