preface

This article is aimed at the Srping ClassPathXMLApplicationContext for source code analysis, in this blog will not tell the spring Xml parsing registration code. I have compiled a spring interview question to share with you.

Because ApplicationContext is an extended version of BeanFactory, the GetBean of ApplicationContext and the XML parse register BeanDefinition are all done with one set of code, If this is your first look, take a look at the XMLBeanFactory parsing and beanFactory.getBean source parsing:

Source:

package lantao; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.lantao.UserBean; public class ApplicationContextTest { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-bean.xml"); UserBean userBean = (UserBean) applicationContext.getBean("userBean"); System.out.println(userBean.getName()); }}Copy the code

Here directly using the ClassPathXmlApplicationContext XML parsing, XML parsing code and GetBean code here but more description, ApplicationContext is the BeanFactory extension, So want to see the source of these two parts of the author’s last two blog Sprin source parsing;

Next we see ClassPathXmlApplicationContext source code:

/** * Create a new ClassPathXmlApplicationContext with the given parent, * loading the definitions from the given XML files. * @param configLocations array of resource locations * @param refresh whether to automatically refresh the context, * loading all bean definitions and creating all singletons. * Alternatively, call refresh manually after further configuring the context. * @param parent the parent context * @throws BeansException  if context creation failed * @see #refresh() */ public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super(parent); SetConfigLocations (configLocations); if (refresh) { refresh(); }}Copy the code

In the setConfigLocations method, resource files are placed in the configLocations global variable, and multiple file parsing is supported.

Refresh method:

@Override public void refresh() throws BeansException, An IllegalStateException {synchronized (enclosing startupShutdownMonitor) {/ / Prepare this context for refreshing. / / to refresh the context prepareRefresh(); // Refresh the internal bean factory. // Refresh the internal bean factory. Through this method applicationContext has all the functions the BeanFactory ConfigurableListableBeanFactory the BeanFactory = obtainFreshBeanFactory (); PrepareBeanFactory (beanFactory); // Prepare the bean factory for use in this context. try { // Allows post-processing of the bean factory in context subclasses. // Allows post-processing of BeanFactory in context subclasses. / / to allow subclasses to the context of the Bean plant for reprocessing / / can be hard coded form of spring BeanFactoryPostProcessor here call addBeanFactoryPostProcessor postProcessBeanFactory(beanFactory); // Invoke Factory processors registered as beans in the context BeanFactoryPostProcessors is instantiated before execution invokeBeanFactoryPostProcessors (the beanFactory); // Register bean processors that intercept bean creation. To actually call BeanPostProcessor while getBean is executed in instantiation of doCreateBean before and after init DoCreateBean - > initializeBean - > applyBeanPostProcessorsBeforeInitialization and applyBeanPostProcessorsAfterInitialization registerBeanPostProcessors(beanFactory); // Initialize message source for this context. // Initialize the message source for the context (such as internationalization) without going too far into initMessageSource(); // Initialize event multicaster for this context. And in the applicationEventMulticaster bean initApplicationEventMulticaster (); // Initialize other special beans in specific context subclasses. // Leave it to subclasses to Initialize other beans. // Check for listener beans and register them. // Check for listeners beans and register them. / / Instantiate all remaining (non - lazy - init) singletons. / / initializes the rest of the single instance finishBeanFactoryInitialization (the beanFactory); // Last step: Publish corresponding Event. // Complete the refresh process, notifying the lifecycleProcessor of the refresh process, Also issue ContextRefreshEvent to notify others (LifecycleProcessor uses to do status updates with all declared bean cycles) 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

The Refresh method covers almost all of the basic and extended functionality for the ApplicationContext, so let’s look at what this method does;

Refresh context, preparation before initialization; Load the beanFactory. With this method, the applicationContext has all the functionality of the beanFactory. Populate the beanFactory with various functions that allow reprocessing of the beanFactory here, for example: Here you can hardcode BeanFactory to BeanFactoryPostProcessor or BeanPostProcessor; BeanFactoryPostProcessor is executed before the bean is instantiated, BeanPostProcessor is executed before and after the initialization method, Spring BeanFactoryPostProcessor is BeanFactoryBeanPostProcessor operation is Bean, Second here also involves an extension BeanDefinitionRegistryPostProcessor it is inherited spring BeanFactoryPostProcessor, And also have their own postProcessBeanDefinitionRegistry definition method, this method can BeanDefinitionRegistry operation, BeanDefinitionRegistry has one of the most important methods: registerBeanDefinition. You can register BeanDefinitions and use this method to handle beans that are not governed by Spring; Handle all the spring BeanFactoryPostProcessor, also can saying is to activate the BeanFactory processors, in this way can handle BeanDefinitionRegistryPostProcessor first, In dealing with spring BeanFactoryPostProcessor because BeanDefinitionRegistryPostProcessor has its own definition, so the first execution; BeanPostProcessors are executed before and after the init method: DoCreateBean – > initializeBean – > applyBeanPostProcessorsBeforeInitialization and ApplyBeanPostProcessorsAfterInitialization method; Initialize the Message source for the context (such as internationalization processing) without going too far here; Initializes the application of news broadcast, initialization applicationEventMulticaster, using custom or default; Leave it to subclasses to initialize other beans; Look for ApplicationListener beans among all registered beans and register them with the message broadcaster; Initialize the remaining single instance (not lazy loading), which involves conversionService, LoadTimeWeaverAware, freezing BeanFactory, initializing Bean, etc. Complete the refresh process, including cleaning sub-level resources (such as scanned metadata), notifying lifecycleProcessor and STRat, and publish Event notifying others with ContextRefreshEvent;

Start with the prepareRefresh method:

/** * Prepare this context for refreshing, setting its startup date and * active flag as well as performing any initialization of property sources. */ protected void prepareRefresh() { // Switch to active. this.startupDate = System.currentTimeMillis(); // flag indicating whether this context is closed this.closed. Set (false); // Flag indicating whether this context is currently active this.active.set(true); if (logger.isDebugEnabled()) { if (logger.isTraceEnabled()) { logger.trace("Refreshing " + this); } else { logger.debug("Refreshing " + getDisplayName()); }} // Initialize any placeholder property sources in the context. initPropertySources(); // Validate that all properties marked as required are resolvable: / / see ConfigurablePropertyResolver# setRequiredProperties, / / verification labeled mandatory attribute information whether there were ConfigurablePropertyResolver# setRequiredProperties method getEnvironment().validateRequiredProperties(); // Store pre-refresh ApplicationListeners... if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); } else { // Reset local application listeners to pre-refresh state. this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... this.earlyApplicationEvents = new LinkedHashSet<>(); }Copy the code

, we may think that this method does not do, in fact this method besides the Closed and Active, the most important thing is initPropertySources and getEnvironment () validateRequiredProperties () method;

1. InitPropertySources certificate conforms to the open structure design of Spring and provides users with the maximum ability to extend Spring. Users can rewrite the initPropertySourece method according to their own needs, and carry out personalized property processing and setting in the method.

2. ValidateRequiredProperties is to verify this attribute, so how to validate? Take a small example of merging two lines of code. For example, there is a requirement that a certain setting (such as VAR) used by the project during operation is taken from the system environment variable, and the project will not work if the user does not configure this parameter in the system environment variable. This requirement is also a variety of solutions, can do that in the Spring, the Spring can be changed directly source, such as modified ClassPathXmlApplicationContext

Of course, the best way is to extend the source code and customize the class:

public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext{ public MyClassPathXmlApplicationContext(String.. configLocations){ super(configLocations); } protected void initPropertySources(){// Add validation requirements getEnvironment().setrequiredProterties ("VAR"); }}Copy the code

Custom inherited from the ClassPathXmlApplicationContext MyClassPathXmlApplicationContext, and rewrite the initPropertySources method, the method to add a personalized needs, So at the time of validation is the program go getEnvironment () validateRequiredProperties () code, if the system does not detect the corresponding VAR environment variables, will throw an exception. Of course, we also need when used to replace the original ClassPathXmlApplicationContext:

Public static void main (Stirng [] args) {ApplicationContext bf = new MyClassPathXmlApplicationContext (" myTest. XML "); User user = (User)bf.getBean("testBean"); }Copy the code

Look at the next obtainFreshBeanFactory method, initialize DefaultListAbleBeanFactory here and parse the XML:


 /**
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
  refreshBeanFactory();
  return getBeanFactory();
}
Copy the code
/** * This implementation performs an actual refresh of this context's underlying * bean factory, shutting down the previous bean factory (if any) and * initializing a fresh bean factory for the next phase of the context's lifecycle. */ @Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } the try {/ / createBeanFactory method directly to create a new DefaultListableBeanFactory, Internal use is DefaultListableBeanFactory instance DefaultListableBeanFactory the beanFactory = createBeanFactory (); / / set the serialization id the beanFactory. SetSerializationId (getId ()); // customizeBeanFactory customizeBeanFactory(beanFactory); // Load BeanDefinition loadBeanDefinitions(beanFactory); Synchronized (this.beanFactoryMonitor) {// Use a global variable to record BeanFactory this. BeanFactory = BeanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); }}Copy the code

Take a look at what the above methods do:

1. Check whether the BeanFactory exists, if so, destroy all beans, and then close the BeanFactory;

2. CreateBeanFactory method is used to create a new DefaultListableBeanFactory directly, internal use DefaultListableBeanFactory instance;

3. Set the serialization ID of the BeanFactory

4. Customize the beanFactory factory, that is, to allowBeanDefinitionOverriding (whether to allow coverage with the name of the Bean) and allowCircularReferences (whether to allow the Bean circular dependencies), By setAllowBeanDefinitionOverriding and setAllowCircularReferences assignment, this can be through the dealer make initialization method of initPropertySources approach to the assignment;

package lantao; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyApplicationContext extends ClassPathXmlApplicationContext { public MyApplicationContext(String... configLocations){ super(configLocations); } protected void initPropertySources(){// Add validation requirements getEnvironment().setrequiredProperties ("VAR"); / / add here set super. SetAllowBeanDefinitionOverriding (true); super.setAllowCircularReferences(true); }}Copy the code

Let’s look at the prepareBeanFactory method source:

/** * Configure the factory's standard context characteristics, * such as the context's ClassLoader and post-processors. * @param beanFactory the BeanFactory to configure */ protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // Tell the internal bean factory to use the Context's classloader etc. // Sets BeanFactory's classLoader to the current context's classLoader beanFactory.setBeanClassLoader(getClassLoader()); // By default, we can use #{bean.xxx} to call the related attribute values // call back when the bean is instantiated Attributes filling method (doCreateBean populateBean method of method of applyPropertyValues evaluateBeanDefinitionString) in the Will determine whether beanExpressionResolver null operation. The beanFactory setBeanExpressionResolver (new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); // Add a default PropertyEditor to BeanFactory. // beanFactory calls the ResourceEditorRegistrar at the initialization of BeanWrapper (initBeanWrapper) The beanFactory registerCustomEditors method. AddPropertyEditorRegistrar (new ResourceEditorRegistrar (this, getEnvironment ())); // Configure the bean factory with context callbacks. // ApplicationContextAwareProcessor --> PostProcessBeforeInitialization / / registered BeanPostProcessor BeanPostProcessor performed before and after is instantiated beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); The addBeanPostProcessor method already handles the following classes, which are not normal beans. In this case, spring ignores the autowireByName and autowireByType of populateBean in // doCreateBean In the unsatisfiedNonSimpleProperties! Judging isExcludedFromDependencyCheck (pd), / / when fill back to rely on, If there are a few don't do the processing Implements the operation for the following class can do the 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. // Set several registration dependencies. Refer to spring source for deep parsing. When the bean's properties are injected, Once detected properties for the type of the BeanFactory change back to the BeanFactory instance injected the BeanFactory. RegisterResolvableDependency (the BeanFactory. Class, the 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. Use to detect the internal bean as ApplicationListener. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // Detect a LoadTimeWeaver and prepare for weaving, If found. // Added support for AxpectJ 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. 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

Without further ado, let’s look at what this method does:

Set BeanFactory’s classLoader to the current context’s classLoader.

Spel expression language support has been added in Spring3 to set the BeanFactory. By default, you can use the form #{bean.xxx} to call related attribute values.

Call back when the Bean is instantiated attribute of filling method in applyPropertyValues method (doCreateBean method of populateBean evaluateBeanDefinitionString) Determines whether beanExpressionResolver is a NULL operation, and if not, Spel expression rules are used for parsing

<? The XML version = "1.0" encoding = "utf-8"? > <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd "> < bean id =" testOneBean" class="lantao.bean.TestOneBean"> <property name="testTwoBean" value="#{testTWoBean}"/> </bean> <bean id="testTWoBean" class="lantao.bean.TestTwoBean"/> <! Class =" lanto.bean.testoneBean "> <property name="testTwoBean" ref="testTWoBean1"/> </bean> <bean id="testTWoBean1" class="lantao.bean.TestTwoBean"/> </beans>Copy the code

3. Add a default PropertyEditor for BeanFactory. Add a property registry editor for BeanFactory. In the User class, the type of startDate is date, but the value of XML property is 2019-10-10, so an error will be reported when it is started, and the type conversion is not successful. Here, we can use the class model of inheritance PropertyEditorSupport to rewrite it and inject it. The beanFactory will use the ResourceEditorRegistrar registerCustomEditors method at the initialization of BeanWrapper (initBeanWrapper).

3. Configure BeanPostProcessor, configuration is ApplicationContextAwareProcessor here, we said the above, BeanPostProcessor in initialization method before and after the Init, Have a look at ApplicationContextAwareProcessor Before and After methods:

@Override @Nullable public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException { AccessControlContext acc = null; / / this method will be the BeanFactory instantiation bean invokes the doCreateBean - > initializeBean - > applyBeanPostProcessorsBeforeInitialization - > PostProcessBeforeInitialization / / if the instantiation of the class implements the invokeAwareInterfaces method in the class Will call method of the initial assignment if (System. GetSecurityManager ()! = null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) { acc = this.applicationContext.getBeanFactory().getAccessControlContext(); } if (acc ! = null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareInterfaces(bean); return null; }, acc); } else { invokeAwareInterfaces(bean); } return bean; } 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); } } } @Override public Object postProcessAfterInitialization(Object bean, String beanName) { return bean; }Copy the code

The invokeAwareInterfaces method is called in the Before method, and the instanceof type is checked in the invokeAwareInterfaces method. This means that if the Bean implements the above Aware, the resource is initialized. For example, if you implement ApplicationContextAware, you’ll setApplicationContext, which I’m sure you’ve all used before.

The addBeanPostProcessor method already handles the following classes, which are not normal beans, so spring ignores them when it comes to bean dependencies. In doCreateBean method of populateBean autowireByName or in unsatisfiedNonSimpleProperties autowireByType! Judging isExcludedFromDependencyCheck (pd), if there is not do dependency injection;

When a BeanFactory dependency is registered, the BeanFactory instance will be injected when the BeanFactory attribute is detected. The BeanFactory instance will be injected when the BeanFactory attribute is detected.

Add BeanPostProcessor, in this case add ApplicationListener, register early processor; You can see the author’s source code tests here, under the Spring-context test class;

Added support for AxpectJ

Register the default systemEnvironment bean, environment, systemProperties, systemEnvironment;

That’s how you populate the BeanFactory function, postProcessBeanFactory:

The postProcessBeanFactory method is an empty method that allows post-processing of the Bean factory in context subclasses, such as: Can be hard coded form of spring BeanFactoryPostProcessor here call addBeanFactoryPostProcessor, For addBeanFactoryPostProcessor or BeanPostProcessor;

Look at the next invokeBeanFactoryPostProcessors method:

public static void invokeBeanFactoryPostProcessors(
		ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

	// Invoke BeanDefinitionRegistryPostProcessors first, if any.
	Set<String> processedBeans = new HashSet<>();

	// 对 BeanDefinitionRegistry  类型处理
	if (beanFactory instanceof BeanDefinitionRegistry) {
		// 强转
		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;

		// 普通的处理器
		List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();

		//注册处理器
		List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();


		// 这里就是硬编码处理 因为这里是从 getBeanFactoryPostProcessors()方法获取的 可以硬编码从addBeanFactoryPostProcessor()方法添加
		for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {

			if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {

				// 对于 BeanDefinitionRegistryPostProcessor 类型 在 BeanFactoryPostProcessor 的基础上还有自己的定义,需要先调用
				BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;

				// 执行 继承 BeanDefinitionRegistryPostProcessor 类的  postProcessBeanDefinitionRegistry 方法
				registryProcessor.postProcessBeanDefinitionRegistry(registry);

				registryProcessors.add(registryProcessor);
			}
			else {
				regularPostProcessors.add(postProcessor);
			}
		}
		//上边的For循环只是调用了硬编码的 BeanDefinitionRegistryPostProcessor 中的 postProcessBeanDefinitionRegistry 方法,
		// 但是 BeanFactoryPostProcessor 中的 postProcessBeanFactory 方法还没有调用,是在方法的最后一行
		// invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
		// invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); 这两个方法中执行的,


		// 下面是自动处理器 获取类型是BeanDefinitionRegistryPostProcessor  beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); 获取的


		// 当前注册处理器
		List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

		// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
		// 首先调用实现了 PriorityOrdered 的 BeanDefinitionRegistryPostProcessors
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		registryProcessors.addAll(currentRegistryProcessors);
		// 执行 BeanDefinitionRegistryPostProcessor类的postProcessBeanDefinitionRegistry方法
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		currentRegistryProcessors.clear();

		// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
		// 下一个 ,调用实现 Ordered 的 BeanDefinitionRegistryPostProcessors
		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);
		// 执行 BeanDefinitionRegistryPostProcessor类的postProcessBeanDefinitionRegistry方法
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		currentRegistryProcessors.clear();

		// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
		// 最后,调用所有其他BeanDefinitionRegistryPostProcessors,直到不再显示其他BeanDefinitionRegistryPostProcessors 无序的
		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);
			// 执行 BeanDefinitionRegistryPostProcessor类的postProcessBeanDefinitionRegistry方法
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
				currentRegistryProcessors.clear();
		}

		// 现在,调用到目前为止处理的所有处理器的  执行BeanFactoryPostProcessor 类的 postProcessBeanFactory 方法
		// 这里执行的是 硬编码 和 非硬编码(自动)的 BeanFactoryPostProcessor 类的 postProcessBeanFactory 方法 分为硬编码处理器 和 普通处理器
		invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
	}

	else {
		// 调用在上下文实例中注册的工厂处理器的postProcessBeanFactory方法。 就是硬编码 通过 addBeanFactoryPostProcessor 方法添加的BeanFactoryPostProcessor
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
	}




	// 自动处理 非硬编码 获取类型为是BeanFactoryPostProcessor    beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

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

	// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
	// Ordered, and the rest.

	//  实现 priorityOrdered 的
	List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();

	// 实现 Ordered 的
	List<String> orderedPostProcessorNames = new ArrayList<>();

	// 无序的
	List<String> nonOrderedPostProcessorNames = new ArrayList<>();

	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<>();
	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<>();
	for (String postProcessorName : nonOrderedPostProcessorNames) {
		nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}
	invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

	// Clear cached merged bean definitions since the post-processors might have
	// modified the original metadata, e.g. replacing placeholders in values...
	beanFactory.clearMetadataCache();
        }
        
Copy the code

The above code may seem like a lot, but it adds up to three things:

Perform hard coded and active injection BeanDefinitionRegistryPostProcessor, call postProcessBeanDefinitionRegistry method; Executes the hardcoded and actively injected BeanFactoryPostProcessor, calling the postProcessBeanFactory method; Autoinjected inheritable Ordered, priorityOrdered, or unordered; The above tests are provided in the Lantao package of the author’s Spring source code.

RegisterBeanPostProcessors method source code:

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. / / using priorityOrdered that order List < BeanPostProcessor > priorityOrderedPostProcessors = new ArrayList < > (); // MergedBeanDefinitionPostProcessor List<BeanPostProcessor> internalPostProcessors = new ArrayList<>(); / / using the order that order List < String > orderedPostProcessorNames = new ArrayList < > (); / / unordered List < String > nonOrderedPostProcessorNames = new ArrayList < > (); // add for (String ppName: postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); priorityOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, // First register the BeanPostProcessors that implement PriorityOrdered First sort PostProcessors sortPostProcessors (priorityOrderedPostProcessors, the beanFactory); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // Next, register the BeanPostProcessors that implement. Order BeanPostProcessors 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. Unordered 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. All registered MergedBeanDefinitionPostProcessor types BeanPostProcessor, not repeat registration. sortPostProcessors(internalPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, internalPostProcessors); // Re-register post-processor for detecting inner beans as ApplicationListeners, // Move it to the end of the processor chain (for picking up Proxies etc). // Add ApplicationListener detector beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); }Copy the code

RegisterBeanPostProcessors method code or longer, it and the main difference is the registerBeanPostProcessors invokeBeanFactoryPostProcessors method only registered here, But do not call here, doing and invokeBeanFactoryPostProcessors about:

1. Use priorityOrdered, Ordered, or disordered to ensure order;

2. Through the beanFactory. AddBeanPostProcessor (postProcessor) for registration; It’s very simple, it’s a long code, but it’s very easy to understand, and you can look at it briefly;

InitApplicationEventMulticaster source code:

/** * Initialize the ApplicationEventMulticaster. * Uses SimpleApplicationEventMulticaster if none defined in the context. * @see org.springframework.context.event.SimpleApplicationEventMulticaster */ protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); / / using the custom radio if (the beanFactory. ContainsLocalBean (APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isTraceEnabled()) { logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "] "); }} else {/ / use the spring to the default radio enclosing applicationEventMulticaster = new SimpleApplicationEventMulticaster (the beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isTraceEnabled()) { logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " + "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]"); }}}Copy the code

InitApplicationEventMulticaster method is mainly to judge is to use a custom ApplicationEventMulticaster (radio) or using Spring default SimpleApplicationEventMulti Caster;

The onRefresh method is left empty for a subclass to override;

RegisterListeners method:

/** * Add beans that implement ApplicationListener as listeners. * Doesn't affect other listeners, which can be added without being beans. */ protected void registerListeners() { // Register statically specified The for (ApplicationListener<? > listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let post-processors apply to them! / / register add ApplicationListener here is automatically registered add String [] listenerBeanNames = getBeanNamesForType (ApplicationListener. Class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } // Publish early application events now that we finally have a multicaster... / / release early event Set < ApplicationEvent > earlyEventsToProcess = this. EarlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess ! = null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); }}}Copy the code

RegisterListeners do three things:

1. AddApplicationListener. This is added by hard-coding the addApplicationListener method.

2. Adding ApplicationListener is added through automatic registration

3. Post early morning events

/** * Finish the initialization of this context's bean factory, * initializing all remaining singleton beans. */ protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this Context. // conversionService is used for type conversion, For example, String goes to Date // to determine whether the BeanFactory contains a Bean whose name is conversionService and type is conversionService. If it exists, it is injected into the beanFactory // to determine if there is a custom attribute transformation service interface, and it is initialized. We used this service interface in analyzing the bean's attribute population. In the convertIfNecessary method of the TypeConverterDelegate class, 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)); } // Register a default embedded value resolver if no bean post-processor // (such as a PropertyPlaceholderConfigurer bean) registered any before: // at this point, primarily for resolution in annotation attribute values. if (! beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. // // If there are beans of type LoadTimeWeaverAware, initialize them to load Spring beans into third-party modules such as AspectJ, We'll talk more about that later. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // Stop using the temporary ClassLoader for type matching beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes. Show that you registered bean will not be modified or make any further processing Changed BeanDefinition is to not let the beanFactory. FreezeConfiguration (); // Instantiate all Remaining (non-lazy-init) singletons // Instantiate all remaining (non-lazy-init) singletons by calling your getBean method beanFactory.preInstantiateSingletons(); }Copy the code

FinishBeanFactoryInitialization method do five things:

1. Set the conversionService of the BeanFactory, which is used for type conversion, for example: In the User class, the type of startDate is date, but the value of the XML property is 2019-10-10, so an error will be reported when it is started, and the type conversion is not successful. ConversionService can be used. There are 170 pages of code in the book;

2. Add the BeanFactory addEmbeddedValueResolver, reading configuration information on here, could be obtained by EmbeddedValueResolverAware, refer to: www.cnblogs.com/winkey4986/…

3. Get all the subclass names that implement the LoadTimeWeaverAware interface and initialize them for loading Spring beans into third-party modules such as AspectJ, which we’ll cover later.

4. Stop using temporary classloaders at this point

5. Freeze all bean definitions to indicate that your registered bean will not be modified or any further processing will not be allowed to change the BeanDefinition

Call your getBean method, loop through all the beans and instantiate them under the conditions: singleton, non-abstract non-lazy-loaded

The final method finishRefresh:

/** * Finish the refresh of this context, invoking the LifecycleProcessor's * onRefresh() method and publishing the * {@link org.springframework.context.event.ContextRefreshedEvent}. */ protected void finishRefresh() { // Clear context-level Resource caches (such as ASM metadata from scanning). // Clears lower-level resources (such as scanned metadata). clearResourceCaches(); Lifecycle has its own start/ stop method. Lifecycle has its own start/ stop method. Implementing this interface ensures that spring calls the start method on startup to start the lifecycle and the stop method on shutdown to end the lifecycle initLifecycleProcessor(); // Propagate refresh to lifecycle processor first getLifecycleProcessor().onRefresh(); PublishEvent (new ContextRefreshedEvent(this)); // Publish the final event. // Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this); }Copy the code

The finishRefresh method is the last method to initialize the ApplicationContext, and it does some closing things:

1. Clear lower-level resources (such as scanned metadata).

Lifecycle will be initialized in the current context. Lifecycle will have its own start/ stop methods and spring will guarantee that lifecycle will be called when lifecycle is started and stop will be called when lifecycle is closed.

OnRefresh starts all methods that implement Lifecycle and calls the start method.

4. Handle the publishing event when ApplicationContext initialization is complete.

The last

I have arranged a: Spring related information documents, Spring bucket series, Java systematic information, (including Java core knowledge, interview topics and the latest Internet real questions in 20 years, e-books, etc.) friends who need to pay attention to the public number [procedure Yuan Small wan] can be obtained.