Previous posts:

1. Deep understanding of Spring IOC(I), unified resource loading

2. Deep understanding of Spring IOC(ii), from XML to BeanDefinition

1. BeanDefinition registration

In our previous article, we have parsed the XML information into BeanDefiniton. Then we need to register it, which means putting the parsed BeanDefiniton into a container for unified instantiation during later instantiation. Let’s look at the following code:

The code block1
        @Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		XmlBeanDefinitionReader (XmlBeanDefinitionReader
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
		
		/ / 2. It is in AbstractXmlApplicationContext, its parent class inherited DefaultResourceLoader already, also
		// Implements ResourcePatternResolver
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
	
		// 3. Set the validation model
		initBeanDefinitionReader(beanDefinitionReader);
		// 4. Load Resource
		loadBeanDefinitions(beanDefinitionReader);
	}
Copy the code

The fault code believe everybody already very familiar with it, we can see the code block 1 new a XmlBeanDefinitionReader, we note that the new preach a DefaultListableBeanFactory, at the same time The DefaultListableBeanFactory it implements BeanDefinitionRegistry interface, in other words, it is also a BeanDefinitionRegistry instance, this thing had what effect? Let’s look at the argument to the method called by the code at 2 in the following:

The code block2
        protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if(bdHolder ! =null) {
			// 1. Parse the custom label under the default label
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// 2. Register beanDefiniton instance.
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(newBeanComponentDefinition(bdHolder)); }}Copy the code

This is before the code in the article, the second parameter of the method called the second place getReaderContext () getRegistry () method returns, is DefaultListableBeanFactory examples above, We point directly into the two BeanDefinitionReaderUtils registerBeanDefinition method to see:

The code block3
        public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// 1. Register beanDefinition
		String beanName = definitionHolder.getBeanName();
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// 2. Register an alias
		String[] aliases = definitionHolder.getAliases();
		if(aliases ! =null) {
			for (Stringaliase : aliases) { registry.registerAlias(beanName, aliase); }}}Copy the code

We focus on the 1, before also said that the registry is actually a DefaultListableBeanFactory instance, So we follow in this class to find DefaultListableBeanFactory registerBeanDefinition method:

The code block4
        @Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				// 1. Check method-override and factory-method.
				((AbstractBeanDefinition) beanDefinition).validate();
			}catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition oldBeanDefinition;

		// Synchronized, because ConcurrentHashMap is not absolutely thread-safe
		synchronized (this.beanDefinitionMap) {
			oldBeanDefinition = this.beanDefinitionMap.get(beanName);
			if(oldBeanDefinition ! =null) {
				/ / 2. AllowBeanDefinitionOverriding default is true
				if (!this.allowBeanDefinitionOverriding) {
					throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
							"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
							"': There is already [" + oldBeanDefinition + "] bound.");
				// 3. The role of the bean represents the type of beanDefiniton, which is a variable of type int. You can understand that the larger the number, the lower the beanDefinition it represents
				For example, 1 is user-defined, 2 and 3 are configuration dependent, but at different levels
				} else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
					if (this.logger.isWarnEnabled()) {
						this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
								" with a framework-generated bean definition ': replacing [" +
								oldBeanDefinition + "] with [" + beanDefinition + "]"); }}else {
					if (this.logger.isInfoEnabled()) {
						this.logger.info("Overriding bean definition for bean '" + beanName +
								"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); }}}else {
			    // Place the beanName in a collection dedicated to bean names for subsequent object creation
				this.beanDefinitionNames.add(beanName);
				this.frozenBeanDefinitionNames = null;
			}
			// 4. Register the beanDefinition in a map
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}

		if(oldBeanDefinition ! =null|| containsSingleton(beanName)) { resetBeanDefinition(beanName); }}Copy the code

As you can see, at 4, all the parsed BeanDefinitions are put into a Map, and at this point, the BeanDefinitions are registered.

2. AbstractApplicationContext refresh

That’s it, though, because this is where many of you start reading Spring source code, and many of you probably know this method as well. Anyway, we’ll let you know more today, so let’s go straight to the Refresh method here:

Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 1. Preparation before loading prepareRefresh(); / / 2. Get a new instances of the beanFactory ConfigurableListableBeanFactory the beanFactory = obtainFreshBeanFactory (); PrepareBeanFactory (beanFactory); prepareBeanFactory(beanFactory); Try {/ / (empty methods, let subclasses override) allows for the beanFactory do some stuff in the front of the change, can be add a BeanFactoryPostProcessors / / this, also can give increase a BeanDefinition, You can also add interfaces that are ignored by the beanFactory during autowiring. You can also add beans that are used in specific scenarios. For example, some descendants add new Scope beans, etc. But the point is that everything I've just said is based on a concrete scenario, so in this abstract class, // this method is empty (not abstract because it doesn't force subclasses to implement it) postProcessBeanFactory(beanFactory); / / 4. Trigger call all BeanFactoryPostProcessors (a what) can speak behind invokeBeanFactoryPostProcessors (the beanFactory); / / 5. All registered BeanPostProcessor behind (speak) registerBeanPostProcessors (the beanFactory); // 6. Initialize initMessageSource(); / / 7. Initialization event broadcasters initApplicationEventMulticaster (); // 8. Initialize other special beans onRefresh(); // Listeners(); / / 10. Instantiate bean (key) finishBeanFactoryInitialization (the beanFactory); finishRefresh(); } catch (BeansException ex) { 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; }}}Copy the code

Despite comments above every step, but are you sure is meng force, also don’t know what did the method of the inside, in order to easier to let you understand, in this article, a large part will be split into many small parts, and then we according to the above code block each annotation, say, every detail.

Before that there is a need of attention, is based on the article before I start code debug, we are still in use ClassPathXmlApplicationContext at this time, that is to say the ApplicationContext implementation class, A lot of the source code articles talk about the refresh method directly, and to be honest, it really feels like a bit of a rascal to talk about it not based on usage scenarios. All right, enough teasing, let’s get started

5.1

The prepareRefresh call at 1 in Block 5 is mostly preparation before loading, so let’s get straight to what the prepareRefresh method does

The code block6
        protected void prepareRefresh() {
		// 1. Record the time when the container starts flushing
		this.startupDate = System.currentTimeMillis();
		// 2. Mark the container as active
		synchronized (this.activeMonitor) {
			this.active = true;
		}

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

		/ / 3. ClassPathXmlApplicationContext tuning method is empty, when skip ~
		initPropertySources();

		/ / 4. Call the validateRequiredProperties StandardEnvironment method
		getEnvironment().validateRequiredProperties();
	}
Copy the code

The above 1, 2, 3, it is easy to understand, we see four validateRequiredProperties method directly, this piece of the code is in AbstractEnvironment:

The code block7
        @Override
	public void validateRequiredProperties() throws MissingRequiredPropertiesException {
		this.propertyResolver.validateRequiredProperties();
	}
Copy the code

Here the propertyResolver is a PropertySourcesPropertyResolver instance, This is used to parse and store environment variables and configurations (springBoot properties and YML properties are eventually stored in the propertySources). We see PropertySourcesPropertyResolver validateRequiredProperties method directly, but in fact it is directly inherited AbstractPropertyResolver this method:

The code block8
        @Override
	public void validateRequiredProperties() {
		// Create an exception
		MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
		// If the desired attribute is empty then throw the exception from the previous new line
		for (String key : this.requiredProperties) {
			if (this.getProperty(key) == null) { ex.addMissingRequiredProperty(key); }}if(! ex.getMissingRequiredProperties().isEmpty()) {throwex; }}Copy the code

This. RequiredProperties is empty when the StandardEnvironment is created because setRequiredProperties was not called to add requiredProperties. So we speak of this method is in this context p did not do, but we still need to pay attention to PropertySourcesPropertyResolver (at least you know what it is), because this thing is very important in the SpringBoot.

5.2

Code block in 2 of 5 main purpose here is to get a new DefaultListableBeanFactory, and the corresponding information in the XML loaded into BeanDefinition into it. The loading process is exactly what we’ve been talking about in previous articles, so we won’t repeat it here.

5.3

This is mostly initialization

The code block9
    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
        // Set the class loader: if it exists, set it directly. If it does not exist, create a default class loader
		beanFactory.setBeanClassLoader(getClassLoader());
		// Set the EL expression parser (used when filling properties after Bean initialization)
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
		// Set the property registry parser PropertyEditor
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
	    / / the object of the current ApplicationContext to ApplicationContextAwareProcessor class to deal with,
		// Inject applicationContext into the Aware interface implementation class
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		
		// Set the interface to ignore autowiring
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

		// Register parsed autowiring
		// BeanFactory interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// If the current BeanFactory contains a loadTimeWeaver Bean, there is a classloading period woven into AspectJ,
		/ / is the BeanFactory to class loading in the current period BeanPostProcessor implementation class LoadTimeWeaverAwareProcessor to deal with,
		// The class loading phase is woven into AspectJ.
		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		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 current container environment component Bean
		// Register default environment beans.
		if(! beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); }// Register the system configuration systemProperties component Bean
		if(! beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME,  getEnvironment().getSystemProperties()); }// Register the systemEnvironment component Bean
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
	}
Copy the code

Although can give the note I gave, but I estimate you see this or a face meng force, do not know what these things are used, really do not understand, can first mix a face familiar, and so on the back of the finished and then return to see here.

5.4

This is where all of the BeanFactoryPostProcessors are triggered, and there will be an extension to BeanFactoryPostProcessor for that. We’re here, and we can look at the code here, because it’s actually pretty easy to understand.

The code block10
        protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
	}
Copy the code

We can see that, again, it’s a delegate, so let’s go straight to the delegate:

The code block11
        public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
		// A collection of processors that have been instantiated
		Set<String> processedBeans = new HashSet<String> ();/ / first call BeanDefinitionRegistryPostProcessors
		/ / because the parameters of the beanFactory is DefaultListableBeanFactory instance, and DefaultListableBeanFactory has been realized
		// BeanDefinitionRegistry, therefore, if conditional is true
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			RegularPostProcessors is a BeanFactoryPostProcessor
			List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
			/ / and it is the registryPostProcessors put BeanDefinitionRegistryPostProcessor
			/ / note: inherited spring BeanFactoryPostProcessor BeanDefinitionRegistryPostProcessor interface
			List<BeanDefinitionRegistryPostProcessor> registryPostProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();

			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				/ / if the spring BeanFactoryPostProcessor BeanDefinitionRegistryPostProcessor,
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryPostProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					/ / execution BeanDefinitionRegistryPostProcessor and join registryPostProcessors collection
					registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
					registryPostProcessors.add(registryPostProcessor);
				// Otherwise, just join regularPostProcessors
				} else{ regularPostProcessors.add(postProcessor); }}String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
			/ / first call for PriorityOrdered BeanDefinitionRegistryPostProcessors
			List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					/ / note that instantiate the BeanDefinitionRegistryPostProcessor herepriorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); }}/ / this sort, it is to adjust the realized PriorityOrdered already, and Ordered BeanDefinitionRegistryPostProcessor
			// Because it implements PriorityOrdered, it is possible to implement both interfaces simultaneously (although PriorityOrdered inherited from Ordered)
			/ /, if you don't sort, but your BeanDefinitionRegistryPostProcessor and need the execution order, there will be a problem when I invoke below
			// The same goes for sorting
			OrderComparator.sort(priorityOrderedPostProcessors);
			// Add the implemented PriorityOrdered to the previous registryPostProcessors
			registryPostProcessors.addAll(priorityOrderedPostProcessors);
			/ / realized PriorityOrdered BeanDefinitionRegistryPostProcessor execution
			invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);

			/ / and then call the Ordered BeanDefinitionRegistryPostProcessors
			// Why redo the array? Because realize the PriorityOrdered BeanDefinitionRegistryPostProcessor can give you to register the implementation
			/ / Ordered what sort interface and no BeanDefinitionRegistryPostProcessor
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
			List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
			for (String ppName : postProcessorNames) {
				// The executed items are skipped and not executed
				if(! processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } OrderComparator.sort(orderedPostProcessors); registryPostProcessors.addAll(orderedPostProcessors); invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);/ / the last call other BeanDefinitionRegistryPostProcessors is realized
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
				/ / outer layer is a while loop, because BeanDefinitionRegistryPostProcessor can give you
				/ / registered a BeanDefinitionRegistryPostProcessor come in, so cycle, as long as you a for loop can come in
				Iterate; // Reiterate the flag for whether or not to iterate is true
				for (String ppName : postProcessorNames) {
					if(! processedBeans.contains(ppName)) { BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class); registryPostProcessors.add(pp); processedBeans.add(ppName); pp.postProcessBeanDefinitionRegistry(registry); reiterate =true; }}}// both call the BeanFactoryPostProcessor method postProcessBeanFactory
			invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}else {
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}

		/ / there's a lot of attention: the above logic is in the call into the spring BeanFactoryPostProcessor and BeanDefinitionRegistryPostProcessor refs
		// The next thing to do is call the BeanFactoryPostProcessor in the beanFactory container, Ordered by its PriorityOrdered, Ordered
		// and the normal call. As for why to call first BeanDefinitionRegistryPostProcessors then call spring BeanFactoryPostProcessor? This is because
		/ / BeanDefinitionRegistryPostProcessors can register new spring BeanFactoryPostProcessor come in
		
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true.false);
		
		// A set of three priority BeanFactoryPostProcessors
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
		List<String> orderedPostProcessorNames = new ArrayList<String> (); List<String> nonOrderedPostProcessorNames = new ArrayList<String> ();for (String ppName : postProcessorNames) {
			// Skip if it has already been parsed
			if (processedBeans.contains(ppName)) {
				
			// PriorityOrdered adds a high-priority set, and initiates first
			} else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			// Ordered adds the general priority set
			} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			// Add the normal collection
			} else{ nonOrderedPostProcessorNames.add(ppName); }}// Sort and call the high-priority BeanFactoryPostProcessor
		OrderComparator.sort(priorityOrderedPostProcessors);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Initialize the generic priority BeanFactoryPostProcessor and sort the calls
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		OrderComparator.sort(orderedPostProcessors);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Initialize the ordinary BeanFactoryPostProcessor and sort the calls
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
	}
Copy the code

Code is long, but the thinking is very clear, overall, that is, in order to invoke BeanDefinitionRegistryPostProcessor first, and then call spring BeanFactoryPostProcessor in the same order.

5.5

This is where all the BeanPostProcessors are registered. Note that this will not be called because the BeanPostProcessor cannot be called until the Bean is initialized. I’ll talk about this BeanPostProcessor in the same article as BeanFactoryPostProcessor. We can also directly look at the source code for registering BeanPostProcessor (because it is simple 😊), in the same class as the above code block, but with another method:

The code block12
        public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
		// Get all the BeanPostProcessor names
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true.false);
		
		// Preferentially register an instance of BeanPostProcessorChecker, which is used to initialize the process in BeanPostProcessor
		// See the extension for the check content
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// Again familiar, separate the three priority levels of BeanPostProcessor
		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) {
			// instantiate the code that implements PriorityOrdered and join the collection
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				/ / if MergedBeanDefinitionPostProcessor, join internalPostProcessors
				if (pp instanceofMergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); }}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			} else{ nonOrderedPostProcessorNames.add(ppName); }}// Sort and register
		OrderComparator.sort(priorityOrderedPostProcessors);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Then the Ordered implementation is registered
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		OrderComparator.sort(orderedPostProcessors);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// re-register normal
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		/ / register all realized MergedBeanDefinitionPostProcessor (last) in order to move to the processing link
		// Do not understand what is the processing link
		OrderComparator.sort(internalPostProcessors);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		/ / register ApplicationListenerDetector (and last) to move to the processing link
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}
Copy the code

In fact, it’s similar to how BeanFactoryPostProcessor was registered before. I won’t explain it too much here, just read the comments.

The code 6, 7, 8, and 9 of code block 5 are not part of the core flow, so we won’t focus on those for now. At this point, the preparatory work for instantiating the bean is complete. So to summarize, in this case with XML, there are a couple of things that we do before we instantiate the bean in the Refresh method. First we need to load all of the BeanDefinitions into the BeanFactory container and that’s done in the second step of refresh, The next step is to initialize some basic beans in prepareBeanFactory first, and then call all the BeanFactoryPostProcessors to postprocess the BeanDefinition. This is followed by the deregistration of all Beanpostprocessors, followed by internationalization, event announcer, and listener initialization. Of these, the most important step is to load the BeanDefinition and call the BeanFactoryPostProcessor, because both of these steps are extensible.