Spring IoC container design principles

For the Spring IoC container, you will always hear several similar descriptions: “How Spring IoC works”, “how Spring IoC loads”, and so on. Both descriptions are correct, and how the container loads, that’s how it works. About Spring IoC, let’s first comb through the container system. There are two main lines, one is BeanFactory inheritance system, the other is ApplicationContext inheritance system.

BeanFactory, as the basic container interface, provides the most basic functions, and the function of each method can be seen from the method name

ApplicationContext is a high-level container interface. LifeCycle is inherited by LifeCycle. It will trigger a start/stop call when the container is started or closed. In AbstractApplicationContext, will trigger a variety of implements the LifeCycle of the start/stop method call. MessageSource associated with internationalization, ApplicationEventPublisher in the IoC container system, is an event publishing, publishing ApplicationEvent events.

Above, the whole system about the impression, then, we start with a simple test cases, step by step to understand how the IoC container, here or in the most commonly used ClassPathXmlApplicationContextTests.

The container loading process

2. Parse the Bean from the resource file and convert it to Spring BeanDefinition, and put it into the container. 3

ClassPathXmlApplicationContextTests

@Test
public void testSingleConfigLocation(a) {
    ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(FQ_SIMPLE_CONTEXT);
    assertTrue(ctx.containsBean("someMessageSource"));
    ctx.close();
}
Copy the code

Here to create a ClassPathXmlApplicationContext object, the constructor is ultimately calls

ClassPathXmlApplicationContext

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)throws BeansException {
	super(parent);
	setConfigLocations(configLocations);
	if(refresh) { refresh(); }}Copy the code

Refresh is the core method for starting the IoC container

AbstractApplicationContext


public void refresh(a) throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare the container environment, such as setting the startup time and activating flag status
		prepareRefresh();

		// By subclass refresh container
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			postProcessBeanFactory(beanFactory);

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

			// Register bean processors that intercept bean creation.
			registerBeanPostProcessors(beanFactory);

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

			// Initialize event multicaster for this context.
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			onRefresh();

			// Check for listener beans and register them.
			registerListeners();

			// Instantiate all remaining (non-lazy-init) singletons.
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding 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

ObtainFreshBeanFactory method

AbstractApplicationContext

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

RefreshBeanFactory () and getBeanFactory() are abstract methods and are left to subclasses to implement

AbstractRefreshableApplicationContext

protected final void refreshBeanFactory(a) throws BeansException {
	// If the container already exists, destroy it
        if (hasBeanFactory()) {
		destroyBeans();
		closeBeanFactory();
	}
	try {
		DefaultListableBeanFactory beanFactory = createBeanFactory();
		beanFactory.setSerializationId(getId());
		customizeBeanFactory(beanFactory);
                // The entry of the loading Bean, which has a deep call stack, is easy to lose itself
		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

RefreshBeanFactory () the first is whether the container, is destroyed, and create a DefaultListableBeanFactory again, next is the core of loadBeanDefinitions (the beanFactory)

LoadBeanDefinitions () method

AbstractRefreshableApplicationContext

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
	// Create a new XmlBeanDefinitionReader for the given BeanFactory.
	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));

	// If you want to define a Bean with XmlBeanDefinitionReader, you can subclass it. If you want to define a Bean with XmlBeanDefinitionReader, you can use XmlBeanDefinitionReader
	initBeanDefinitionReader(beanDefinitionReader);
	loadBeanDefinitions(beanDefinitionReader);
}
Copy the code

For example, if you want to load the definition of the Bean, you can delegate to the XmlBeanDefinitionReader. For example, if you want to load the definition of the Bean, you can delegate to the XmlBeanDefinitionReader

XmlBeanDefinitionReader

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
	try {
		Document doc = doLoadDocument(inputSource, resource);
		returnregisterBeanDefinitions(doc, resource); }... }Copy the code

The actual parsing of XML into BeanDefinition is done in the registerBeanDefinition method

XmlBeanDefinitionReader

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
	BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
	int countBefore = getRegistry().getBeanDefinitionCount();
	documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
	return getRegistry().getBeanDefinitionCount() - countBefore;
}
Copy the code

In this method, the documentReader. RegisterBeanDefinitions (doc, createReaderContext (resource) parsing, concrete analytical work, Is entrusted to BeanDefinitionParserDelegate class

Optionally, if XmlBeanDefinitionReader holds a BeanFactory object, then if you want to use the createReaderContext(resource) method, If you pass this to the XmlBeanDefinitionReader, then XmlReaderContext(the return object for createReaderContext) is passed; otherwise, XmlReaderContext indirectly holds the BeanFactory object

DefaultBeanDefinitionDocumentReader

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
	this.readerContext = readerContext;
	logger.debug("Loading bean definitions");
	Element root = doc.getDocumentElement();
	doRegisterBeanDefinitions(root);
}
Copy the code

DefaultBeanDefinitionDocumentReader

protected void doRegisterBeanDefinitions(Element root) {
	// Any nested <beans> elements will cause recursion in this method. In
	// order to propagate and preserve <beans> default-* attributes correctly,
	// keep track of the current (parent) delegate, which may be null. Create
	// the new (child) delegate with a reference to the parent for fallback purposes,
	// then ultimately reset this.delegate back to its original (parent) reference.
	// this behavior emulates a stack of delegates without actually necessitating one.
	BeanDefinitionParserDelegate parent = this.delegate;
	this.delegate = createDelegate(getReaderContext(), root, parent);

	if (this.delegate.isDefaultNamespace(root)) {
		String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
		if (StringUtils.hasText(profileSpec)) {
			String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
					profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			if(! getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {if (logger.isInfoEnabled()) {
					logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
							"] not matching: " + getReaderContext().getResource());
				}
				return;
			}
		}
	}

	preProcessXml(root);
        / / entrust BeanDefinitionParserDelegate parsing
	parseBeanDefinitions(root, this.delegate);
	postProcessXml(root);

	this.delegate = parent;
}
Copy the code

Can know from this method, the real is indeed BeanDefinitionParserDelegate parsing, and BeanDefinitionParserDelegate is also indirectly holds the BeanFactory object. Proceed to parseBeanDefinitions(root, this.delegate), and you will enter

AbstractBeanDefinitionParser

public final BeanDefinition parse(Element element, ParserContext parserContext) {
	AbstractBeanDefinition definition = parseInternal(element, parserContext);
	if(definition ! =null && !parserContext.isNested()) {
		try {
			String id = resolveId(element, definition, parserContext);
			if(! StringUtils.hasText(id)) { parserContext.getReaderContext().error("Id is required for element '" + parserContext.getDelegate().getLocalName(element)
								+ "' when used as a top-level tag", element);
			}
			String[] aliases = null;
			if (shouldParseNameAsAliases()) {
				String name = element.getAttribute(NAME_ATTRIBUTE);
				if(StringUtils.hasLength(name)) { aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name)); }}// Wrap BeanDefinition with BeanDefinitionHolder
			BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
                        / / register BeanDefinitionHolder
			registerBeanDefinition(holder, parserContext.getRegistry());
			if (shouldFireEvents()) {
				BeanComponentDefinition componentDefinition = newBeanComponentDefinition(holder); postProcessComponentDefinition(componentDefinition); parserContext.registerComponent(componentDefinition); }}catch(BeanDefinitionStoreException ex) { String msg = ex.getMessage(); parserContext.getReaderContext().error((msg ! =null ? msg : ex.toString()), element);
			return null; }}return definition;
}
Copy the code

To be clear, ParserContext also indirectly holds a BeanFactory object, and directly holds an XmlReaderContext object. Definitionholder (DefinitionHolder, definitionHolder, definitionHolder, definitionHolder); Logic in registerBeanDefinition (holder, parserContext getRegistry ()); After go in, will enter the BeanDefinitionReaderUtils

BeanDefinitionReaderUtils

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

	// Register bean definition under primary name.
	String beanName = definitionHolder.getBeanName();
	registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

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

Again into the registry. RegisterBeanDefinition (beanName, definitionHolder getBeanDefinition ()), this method is a little long, saves the front part

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

	/ / to omit...
        
	if (beanDefinition instanceof AbstractBeanDefinition) {
		try {
			((AbstractBeanDefinition) beanDefinition).validate();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
					"Validation of bean definition failed", ex);
		}
	}

	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
	if(existingDefinition ! =null) {
		
		// ...
		// If it already exists, override it directly
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}
	else {
		if (hasBeanCreationStarted()) {
			// Cannot modify startup-time collection elements anymore (for stable iteration)
			synchronized (this.beanDefinitionMap) {
				this.beanDefinitionMap.put(beanName, beanDefinition);
				List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
				updatedDefinitions.addAll(this.beanDefinitionNames);
				updatedDefinitions.add(beanName);
				this.beanDefinitionNames = updatedDefinitions;
				if (this.manualSingletonNames.contains(beanName)) {
					Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
					updatedSingletons.remove(beanName);
					this.manualSingletonNames = updatedSingletons; }}}else {
			// Still in startup registration phase
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			this.manualSingletonNames.remove(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

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

Results the be clear at a glance, this. BeanDefinitionMap. Put (beanDefinition beanName); So the Spring IoC container is essentially a HashMap. The parsing is working here, so it’s pretty much ok, but does putting in the beanDefinition of the container solve the dependency problem? No.

Here, we have been into the deep level, so to go back, back to AbstractApplicationContext obtainFreshBeanFactory (), basic is over, actually this method also returns the beanFactory directly, So we have to go back to Refresh () and post the code again

PrepareBeanFactory method

AbstractApplicationContext

public void refresh(a) throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare the container environment, such as setting the startup time and activating flag status
		prepareRefresh();

		// By subclass refresh container
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare some features of the container, such as ClassLoader, post-processors
		prepareBeanFactory(beanFactory);

		try {
			// Empty implementation, callback registered by subclass
			postProcessBeanFactory(beanFactory);

			/ / execution eBeanFactoryPostProcessor method
			invokeBeanFactoryPostProcessors(beanFactory);

			/ / register BeanPostProcessors
			registerBeanPostProcessors(beanFactory);

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

			// Initialize event multicaster for this context.
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			onRefresh();

			// Check for listener beans and register them.
			registerListeners();

			// Instantiate all remaining (non-lazy-init) singletons.
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding 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

PrepareBeanFactory method, so let’s look at the code first

AbstractApplicationContext

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

		// 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);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// 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 default environment beans.
		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

Of interest here is the registered Aware class. The Aware class is a callback mechanism provided by Spring, more commonly used as ApplicationContextAware, which is essentially placed in a HashSet. Aware itself is an interface with no defined methods. ApplicationContextAware has only one setApplicationContext method. Only one ApplicationEventPublisherAware setApplicationEventPublisher method, the Aware method, is where to call?

Check out the test demo: Org. Springframework. Context. Support. StaticApplicationContextTests# count, Another class is org. Springframework. Context. ACATester# setApplicationContext, breakpoint setApplicationContext, starting the count

The invocation chain that is called when instantiation of the Bean instantiation, behind will continue to speak, from the point of the chain, interesting is ApplicationContextAwareProcessor class, it’s a BeanPostProcessor, is made extended when the Bean is instantiated, Is useful to many scene, BeanPostProcessor provides two methods postProcessBeforeInitialization and postProcessAfterInitialization, so that Aware of those methods, The call is triggered by the BeanPostProcessor

private void invokeAwareInterfaces(Object bean) {
	if (bean instanceof Aware) {
		if (bean instanceof EnvironmentAware) {
			((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
		}
		if (bean instanceof EmbeddedValueResolverAware) {
			((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
		}
		if (bean instanceof ResourceLoaderAware) {
			((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
		}
		if (bean instanceof ApplicationEventPublisherAware) {
			((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
		}
		if (bean instanceof MessageSourceAware) {
			((MessageSourceAware) bean).setMessageSource(this.applicationContext);
		}
		if (bean instanceof ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); }}}Copy the code

PostProcessBeanFactory method is an abstract method, by a subclass implementation, such as AbstractRefreshableWebApplicationContext, Package the servletContext and servletConfig as BeanPostProcessor and register them in the container

InvokeBeanFactoryPostProcessors method

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

	// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
	// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
	if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
		beanFactory.setTempClassLoader(newContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); }}Copy the code

InvokeBeanFactoryPostProcessors mainly perform registration before spring BeanFactoryPostProcessor, spring BeanFactoryPostProcessor like BeanPostProcessor, BeanFactoryPostProcessor provides a method, postProcessBeanFactory, After the BeanFactory of the container has been initialized (meaning that the BeanDefinition has been loaded into the container, but has not yet been instantiated), you can use this method to override or add some configuration to the previously exposed Bean

public interface BeanFactoryPostProcessor {

	/**
	 * 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 overriding or adding
	 * properties even to eager-initializing beans.
	 * @param beanFactory the bean factory used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}
Copy the code

A typical example is ConfigurationClassPostProcessor, the interface inheritance spring BeanFactoryPostProcessor, used to Configure the configuration for enhanced

/** * Prepare the Configuration classes for servicing bean requests at runtime * by replacing them with CGLIB-enhanced subclasses. */
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	int factoryId = System.identityHashCode(beanFactory);
	if (this.factoriesPostProcessed.contains(factoryId)) {
		throw new IllegalStateException(
				"postProcessBeanFactory already called on this post-processor against " + beanFactory);
	}
	this.factoriesPostProcessed.add(factoryId);
	if (!this.registriesPostProcessed.contains(factoryId)) {
		// BeanDefinitionRegistryPostProcessor hook apparently not supported...
		// Simply call processConfigurationClasses lazily at this point then.
		processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
	}

	enhanceConfigurationClasses(beanFactory);
	beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
Copy the code

RegisterBeanPostProcessors method

Registered BeanPostProcessor registerBeanPostProcessors method in the Bean instantiation is to call the method, The method of the entrusted PostProcessorRegistrationDelegate registerBeanPostProcessors instantiation and registered BeanPostProcessor,

public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true.false);

	// Register BeanPostProcessorChecker that logs an info message when
	// a bean is created during BeanPostProcessor instantiation, i.e. when
	// a bean is not eligible for getting processed by all BeanPostProcessors.
	int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
	beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

	// Separate between BeanPostProcessors that implement PriorityOrdered,
	// Ordered, and the rest.
	List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
	List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
	List<String> orderedPostProcessorNames = new ArrayList<>();
	List<String> nonOrderedPostProcessorNames = new ArrayList<>();
	for (String ppName : postProcessorNames) {
		if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			priorityOrderedPostProcessors.add(pp);
			if (pp instanceofMergedBeanDefinitionPostProcessor) { internalPostProcessors.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<>();
	for (String ppName : orderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		orderedPostProcessors.add(pp);
		if (pp instanceof MergedBeanDefinitionPostProcessor) {
			internalPostProcessors.add(pp);
		}
	}
	sortPostProcessors(orderedPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, orderedPostProcessors);

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

	// Finally, re-register all internal BeanPostProcessors.
	sortPostProcessors(internalPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, internalPostProcessors);

	// Re-register post-processor for detecting inner beans as ApplicationListeners,
	// moving it to the end of the processor chain (for picking up proxies etc).
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
Copy the code

The logic of this method is quite simple, mainly the BeanPostProcessor according to PriorityOrdered and Ordered sequence, and add to the BeanFactory, finally is to put the no sorting is added to the BeanFactory

At this point, it should be noted that BeanDefinition is registered with the container, but it hasn’t been instantiated or injected, and BeanPostProcessor is registered with the container.

See this, can discover AbstractApplicationContext inheritance system, the use of template method is a typical case