Have feelings, have dry goods, wechat search [three prince Ao Bing] pay attention to this different programmer.

This article has been included in GitHub github.com/JavaFamily, there are a line of large factory interview complete test sites, information and my series of articles.

preface

Spring Framework is one of the most far-reaching frameworks in the Java language. The two classical ideas of IOC and AOP are always talked about by programmers. The Spring Boot and Spring Cloud series launched later are also developed on the basis of them. To understand the Spring bucket series, you must learn from the Spring Framework.

This article is the first in a series of source code analysis of the Spring Framework, mainly from the code level to start the Spring Framework to do a complete analysis, the ideas here are based on my own experience with the use of Spring and the understanding of Spring synthesis, the following content represents my personal views, Please feel free to comment if you have any questions.

As an added reminder, this article is based on 5.1.6.RELEASE code, and the entry code is the official recommended Java-Config technology, not XML.

The source code parsing

Considering that it is a very boring process to read the source code directly, and Spring code design is very good specification, which will lead to a very frequent jump between classes when opening the source code, and students who are not familiar with it may be confused directly, so I will prepare a flow chart before each important process. It is recommended that you take a look at the whole process through the flow chart first, and then go through the code hard, this can reduce a lot of difficulty.

I believe that every student who has used Spring technology knows that there is a very important step in the initialization process of Spring, namely the refresh of the Spring container. This step is important, but the initialization process before the refresh is also very important. This article breaks down the entire startup process into two parts, initialization and refresh of the container.

Initialization Process

Process analysis

Because it is based on Java – config technical analysis of the source code, so the entrance here is AnnotationConfigApplicationContext, if is to use XML analysis, The entrance is the ClassPathXmlApplicationContext, both of them is the common features of inherited AbstractApplicationContext classes, and the well-known refresh method is defined in this class, now didn’t reveal the plot, We then analyze AnnotationConfigApplicationContext class, can draw into a flow chart of the following:

After looking at the flow chart, we should consider: if you were to design an IOC container, what would you do? First of all, I will certainly provide an entry (AnnotationConfigApplicationContext) to the user use, then need to initialize a series of tool components:

(1) : if I want to generate bean object, it needs to be a the beanFactory factory (DefaultListableBeanFactory);

(2) : If I want to read a class with a specific annotation (@service, @repository) and convert it into a BeanDefinition object (BeanDefinition is a very important Spring concept that stores all the characteristics of a bean object), Whether such as whether the singleton, lazy loading, factoryBeanName, etc.), then you need an annotation configuration reader (AnnotatedBeanDefinitionReader);

(3) : if I want to scan for the user to specify package directory bean object, so you need a path to the scanner (ClassPathBeanDefinitionScanner).

Is the above diagram easy to understand by thinking about it above?

Ps: The yellow notes in the figure can be omitted, but they clearly show where and when some of Spring’s built-in components are added to the container. The role of components will be discussed in more detail in a later series of articles.

Core code profiling

Considering that if all the code are analyzed, then the length of the article will be too long, so here only on the core content of the source level analysis, all the steps marked ①, ②, ③ and other words in the figure can be understood as a more important step, the following start to carry out a detailed analysis.

org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors

By the time the code runs at this point, the Spring container has been constructed, so it is time to add some built-in components to the container. One of the main component is ConfigurationClassPostProcessor and AutowiredAnnotationBeanPostProcessor, the former is a rear the beanFactory processor, It is used to scan and inject beans, which is a bean post-processor used to perform @AutoWired automatic injection.

org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean

This step resolves the Spring configuration class passed in by the user into a BeanDefinition and registers it in the container. Nothing to say.

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
		@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
	// Parse the incoming configuration class. In fact, this method can parse both the configuration class and the Spring bean object
	AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
	// Determine whether to skip based on @Conditional annotations on this class
	if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
		return;
	}

	abd.setInstanceSupplier(instanceSupplier);
	ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name ! =null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
	// Handle generic annotations on classes
	AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
	if(qualifiers ! =null) {
		for (Class<? extends Annotation> qualifier : qualifiers) {
			if (Primary.class == qualifier) {
				abd.setPrimary(true);
			}
			else if (Lazy.class == qualifier) {
				abd.setLazyInit(true);
			}
			else {
				abd.addQualifier(newAutowireCandidateQualifier(qualifier)); }}}// Encapsulate a BeanDefinitionHolder
	for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
		customizer.customize(abd);
	}
	BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
	/ / scopedProxyMode processing
	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

	// Register BeanDefinitionHolder with Registry
	BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
Copy the code

The refresh process

Process analysis

The following code is the most important step in Spring: container refresh, again look at the diagram and then analyze.

Now that we know how to initialize an IOC container in 3.1, it’s time to make the IOC container work: The simplest functionality of an IOC container is to scan the bean to put in the container, wrap it as a BeanDefinition object, then create the bean through reflection and complete the assignment. But looking at the figure above, it’s clear that Spring has a lot more initialization than this, so let’s break down the intent:

If the user wants to do something custom after scanning the bean: If a container contains both A and B, you can dynamically inject C into the container, or d if not. Spring supports this, too, thanks to its BeanFactoryPostProcessor. The corresponding is pictured above invokeBeanFactoryPostProcessors operation.

What if the user also wants to do something before and after the bean’s initialization? Spring provides a BeanPostProcessor for generating proxy objects, modifying object properties, etc. In fact, most of the functions in the Spring container are done through Bean postprocessor. Spring also provides an entry point for adding objects. The corresponding is pictured above registerBeanPostProcessors operation.

During container creation, what if the user wants to listen for container startup, refresh, etc., and do some custom actions based on those events? Spring has already taken this into account by providing an interface for adding listeners and container event notifications, corresponding to the registerListeners shown above.

Now, if you look at the figure above, it’s a lot easier. Here’s a look at some of the important code.

Core code profiling

org.springframework.context.support.AbstractApplicationContext#refresh

This approach is based on the specific code shown above and can be divided into 12 steps, the more important ones described below.

Here, we need to remember that every container in Spring calls the refresh method to refresh, whether it’s Spring’s parent container or the Feign isolation container in Spring Cloud Feign, and every container calls this method to initialize.

public void refresh(a) throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		// 1. Preprocessing before refreshing
		prepareRefresh();

		// Tell the subclass to refresh the internal bean factory.
		/ / 2. Get the beanFactory, namely created earlier DefaultListableBeanFactory 】 【
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		// 3. Preprocess the beanFactory to add some components to the container
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			// 4. Subclasses can override this method to make further Settings after BeanFactory is created and ready
			postProcessBeanFactory(beanFactory);

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

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

			// Initialize message source for this context.
			// 7. Initialize MessageSource component (internationalization function; Message binding, message parsing)
			initMessageSource();

			// Initialize event multicaster for this context.
			// 8. Initialize the event dispatcher, which is used when registering listeners
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			// 9. Leave this method to subcontainers (subclasses). Subclasses override this method to customize the logic when the container is refreshed, which is used in web scenarios
			onRefresh();

			// Check for listener beans and register them.
			// 10. Register listener and dispatch some events generated by previous steps (maybe not)
			registerListeners();

			// Instantiate all remaining (non-lazy-init) singletons.
			// 11. Initialize all non-singleton beans
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding event.
			Publish the container refresh completion eventfinishRefresh(); }... }}Copy the code

org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory

As the name implies, this interface is to add some built-in components to the beanFactory factory, preprocessing processes.

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

	// Configure the bean factory with context callbacks.
	/ / add a BeanPostProcessor ApplicationContextAwareProcessor 】 【
	beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

	// Set the interface to ignore auto-assembly, that is, not auto-injection through annotations
	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.
	// Register parsed autowiring classes that can be annotated automatically in any component
	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.
	/ / add a BeanPostProcessor ApplicationListenerDetector 】 【
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

	// Detect a LoadTimeWeaver and prepare for weaving, if found.
	// Add compile-time AspectJ
	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.
	// Register an environment component of type [ConfigurableEnvironment]
	if(! beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); }// Register the systemProperties component (Map
      
       ).
      ,>
	if(! beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME,  getEnvironment().getSystemProperties()); }// Register systemEnvironment component (Map
      
       )
      ,>
	if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
		beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
	}
}
Copy the code

org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors

As mentioned earlier, Spring can do some customization after it has scanned all beans to become BeanDefinitions, thanks to Spring’s BeanFactoryPostProcessor interface.

The spring BeanFactoryPostProcessor another subinterface BeanDefinitionRegistryPostProcessor, the former will expose ConfigurableListableBeanFactory use to us, The latter exposes the BeanDefinitionRegistry registry for us to use. Once we have the registry, we can inject as needed, for example, if we assume that the container contains A and B, then inject C dynamically into the container, or d if not.

Those of you familiar with Spring know that the same type of component in Spring allows you to control the Order. For example, the @Order annotation is often used in AOP, and the BeanFactoryPostProcessor interface provides the Order. It starts with an implementation class that implements the PriorityOrdered interface, followed by an implementation class that implements the Ordered interface, and finally the remaining regular BeanFactoryPostProcessor class.

At this point to see above, is found and water generally simple, will first callback postProcessBeanDefinitionRegistry () method, then the callback postProcessBeanFactory () method, finally, pay attention to the order, Let’s take a look at the specific code implementation.

public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List
       
         beanFactoryPostProcessors)
        {
	/ / beanFactoryPostProcessors. This parameter is refers to the user by AnnotationConfigApplicationContext addBeanFactoryPostProcessor () method of the incoming manually BeanFactoryPostProcessor is not managed by Spring
	// Invoke BeanDefinitionRegistryPostProcessors first, if any.
	/ / BeanDefinitionRegistryPostProcessor represent the execution
	Set<String> processedBeans = new HashSet<>();

	if (beanFactory instanceof BeanDefinitionRegistry) {
		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
		// A collection of generic post-processors that implement the BeanFactoryPostProcessor interface
		List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
		/ / registered post processor set, namely BeanDefinitionRegistryPostProcessor interface is realized
		List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
		/ / processing custom beanFactoryPostProcessors (refers to the calling context. AddBeanFactoryPostProcessor () method), and generally are not here
		for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
			if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
				BeanDefinitionRegistryPostProcessor registryProcessor =
						(BeanDefinitionRegistryPostProcessor) postProcessor;
				/ / call postProcessBeanDefinitionRegistry method
				registryProcessor.postProcessBeanDefinitionRegistry(registry);
				registryProcessors.add(registryProcessor);
			}
			else{ regularPostProcessors.add(postProcessor); }}// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let the bean factory post-processors apply to them!
		// Separate between BeanDefinitionRegistryPostProcessors that implement
		// PriorityOrdered, Ordered, and the rest.
		/ / define a variable currentRegistryProcessors, said the current BeanFactoryPostProcessors to be processed
		List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

		// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
		/ / first of all, from the container to find implements the interface PriorityOrdered BeanDefinitionRegistryPostProcessor types, it will only find out a 【 ConfigurationClassPostProcessor 】
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
		for (String ppName : postProcessorNames) {
			// Check whether the PriorityOrdered interface is implemented
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				/ / added to currentRegistryProcessors
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				// Add to processedBeans to indicate that the class has already been processedprocessedBeans.add(ppName); }}// Set the order
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		// Add to registry
		registryProcessors.addAll(currentRegistryProcessors);
		/ / perform [postProcessBeanDefinitionRegistry] callback methods
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		/ / will empty currentRegistryProcessors variables, the following will continue to use
		currentRegistryProcessors.clear();

		// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
		/ / search for implementation in the container, then Ordered interface BeanDefinitionRegistryPostProcessors types, here may find out more
		/ / because have completed postProcessBeanDefinitionRegistry ConfigurationClassPostProcessor 】 【 () method, which has complete scanning to the container, so there will be a lot of a component container
		postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
		for (String ppName : postProcessorNames) {
			// Determine if processedBeans handles this class and implements the Ordered interface
			if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		// Set the order
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		// Add to registry
		registryProcessors.addAll(currentRegistryProcessors);
		/ / perform [postProcessBeanDefinitionRegistry] callback methods
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		/ / will empty currentRegistryProcessors variables, the following will continue to use
		currentRegistryProcessors.clear();

		// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
		/ / in the end, from the container to find all remaining regular BeanDefinitionRegistryPostProcessors types
		boolean reiterate = true;
		while (reiterate) {
			reiterate = false;
			// Search from the container by type
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
			for (String ppName : postProcessorNames) {
				// Determine if processedBeans handles this class
				if(! processedBeans.contains(ppName)) {/ / added to currentRegistryProcessors
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					// Add to processedBeans to indicate that the class has already been processed
					processedBeans.add(ppName);
					/ / will mark is set to true, continue to loop through, may at any time for preventing the call invokeBeanDefinitionRegistryPostProcessors rear () method is introduced into the new processor
					reiterate = true; }}// Set the order
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			// Add to registry
			registryProcessors.addAll(currentRegistryProcessors);
			/ / perform [postProcessBeanDefinitionRegistry] callback methods
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			/ / will currentRegistryProcessors variables to empty, because the next cycle may be used
			currentRegistryProcessors.clear();
		}

		// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
		// Now execute the [postProcessBeanFactory] callback of registryProcessors
		invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
		// Implement the [postProcessBeanFactory] callback for regularPostProcessors. Also contains the user manual call addBeanFactoryPostProcessor () method to add spring BeanFactoryPostProcessor
		invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
	}

	else {
		// Invoke factory processors registered with the context instance.
		invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
	}

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

	// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
	// Ordered, and the rest.
	// Represents a BeanFactoryPostProcessor that implements the PriorityOrdered interface
	List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
	// Represents a BeanFactoryPostProcessor that implements the Ordered interface
	List<String> orderedPostProcessorNames = new ArrayList<>();
	/ / left over conventional BeanFactoryPostProcessors said
	List<String> nonOrderedPostProcessorNames = new ArrayList<>();
	for (String ppName : postProcessorNames) {
		// Determine if it has been handled, because postProcessorNames actually contains the BeanDefinitionRegistry type that was handled in the previous step
		if (processedBeans.contains(ppName)) {
			// skip - already processed in first phase above
		}
		// Check whether the PriorityOrdered interface is implemented
		else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
		}
		// Determine whether the Ordered interface is implemented
		else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
			orderedPostProcessorNames.add(ppName);
		}
		// All the conventional ones
		else{ nonOrderedPostProcessorNames.add(ppName); }}// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
	/ / will be ordered priorityOrderedPostProcessors set first
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	/ / perform priorityOrderedPostProcessors postProcessBeanFactory callback methods
	invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

	// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
	/ / then, convert orderedPostProcessorNames to orderedPostProcessors collection
	List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
	for (String postProcessorName : orderedPostProcessorNames) {
		orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}
	// Order the collection orderedPostProcessors
	sortPostProcessors(orderedPostProcessors, beanFactory);
	// Execute the [postProcessBeanFactory] callback of orderedPostProcessors
	invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

	// Finally, invoke all other BeanFactoryPostProcessors.
	/ / the last turns nonOrderedPostProcessorNames into nonOrderedPostProcessors collection, there is only one, myBeanFactoryPostProcessor
	List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
	for (String postProcessorName : nonOrderedPostProcessorNames) {
		nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}
	// Execute the [postProcessBeanFactory] callback of nonOrderedPostProcessors
	invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

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

org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors

This step is to inject the BeanPostProcessor into the container, but note that it is only injected into the container, not used. Refer to the above steps and the code below, the reader can analyze, should not be very difficult.

The role of BeanPostProcessor will be discussed in more detail in a future Article on the Spring bean creation process. Of course, it is not possible to analyze all of the BeanPostProcessor components, which would require several sequels. It’s just a matter of understanding that this component interferes with Spring’s process of initializing beans for proxying, automatic injection, loop dependency, and more.

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

	// Get the BeanPostProcessor type from the container
	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;
	// Add BeanPostProcessorChecker to the container to check whether any beans have been initialized.
	// If not all beanpostProcessors (measured by number) are executed, an INFO log will be printed if so
	beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

	// Separate between BeanPostProcessors that implement PriorityOrdered,
	// Ordered, and the rest.
	// Store the BeanPostProcessor that implements the PriorityOrdered interface
	List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
	/ / store BeanPostProcessor MergedBeanDefinitionPostProcessor type
	List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
	// Store the name of the BeanPostProcessor that implemented the Ordered interface
	List<String> orderedPostProcessorNames = new ArrayList<>();
	// Store the name of the remaining normal BeanPostProcessor
	List<String> nonOrderedPostProcessorNames = new ArrayList<>();
	// Look for beans in postProcessorNames from beanFactory and put them in the corresponding collection
	for (String ppName : postProcessorNames) {
		// Check whether the PriorityOrdered interface is implemented
		if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			priorityOrderedPostProcessors.add(pp);
			/ / if realized PriorityOrdered interface, and belongs to the MergedBeanDefinitionPostProcessor
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				/ / add MergedBeanDefinitionPostProcessor type to internalPostProcessors collectioninternalPostProcessors.add(pp); }}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
			orderedPostProcessorNames.add(ppName);
		}
		else{ nonOrderedPostProcessorNames.add(ppName); }}// First, register the BeanPostProcessors that implement PriorityOrdered.
	/ / to priorityOrderedPostProcessors sort
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	// Register the beanPostProcessor that implements the PriorityOrdered interface
	registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

	// Next, register the BeanPostProcessors that implement Ordered.
	From / / the beanFactory orderedPostProcessorNames bean, then put in the corresponding collection
	List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
	for (String ppName : orderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		orderedPostProcessors.add(pp);
		if (pp instanceofMergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); }}// Order orderedPostProcessors
	sortPostProcessors(orderedPostProcessors, beanFactory);
	// Re-register the beanPostProcessor that implements the Ordered interface
	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 instanceofMergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); }}// Re-register the regular beanPostProcessor
	registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

	// Finally, re-register all internal BeanPostProcessors.
	/ / sorting MergedBeanDefinitionPostProcessor beanPostProcessor of this type
	sortPostProcessors(internalPostProcessors, beanFactory);
	/ / the last registered MergedBeanDefinitionPostProcessor beanPostProcessor type
	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).
	/ / to add beanPostProcessor ApplicationListenerDetector 】 【 container, distinguish the listener, if is put bean in the container to save up
	By default, there are six built-in BeanPostProcessors in the container
		// 0 = {ApplicationContextAwareProcessor@1632}
		//	1 = {ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@1633}
		//	2 = {PostProcessorRegistrationDelegate$BeanPostProcessorChecker@1634}
		//	3 = {CommonAnnotationBeanPostProcessor@1635}
		//	4 = {AutowiredAnnotationBeanPostProcessor@1636}
		//	5 = {ApplicationListenerDetector@1637}
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
Copy the code

org.springframework.context.support.AbstractApplicationContext#initApplicationEventMulticaster

As we said, in the process of the whole container to create, Spring will release a lot of container events, such as container startup, refresh, shut down, the realization of the function of the benefit from the ApplicationEventMulticaster radio components, distributed event notification by it.

Here, Spring also provides us with extension, SimpleApplicationEventMulticaster default is synchronous, asynchronous, if we want to change to Only need to define a name in containers for applicationEventMulticaster container, similar ideas in the subsequent Spring there will be more reflected in the Boot, go here.

protected void initApplicationEventMulticaster(a) {
	/ / get the beanFactory
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	/ / see if there are custom applicationEventMulticaster container
	if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
		// Get the assignment from the container
		this.applicationEventMulticaster =
				beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
		if (logger.isTraceEnabled()) {
			logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); }}else {
		/ / no, they create a SimpleApplicationEventMulticaster
		this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
		/ / will create ApplicationEventMulticaster added to the BeanFactory, other components can be injected automatically
		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

org.springframework.context.support.AbstractApplicationContext#registerListeners

If the user wants to monitor container events, then it must be in accordance with the standard implementation ApplicationListener interface and placed into the container, here is the Spring scanning to, added to the ApplicationEventMulticaster radio apparatus, the later can launch event notification, The corresponding Listener receives the message and processes it.

protected void registerListeners(a) {
	// Register statically specified listeners first.
	// Get the ApplicationListener saved in the previous step
	for(ApplicationListener<? > listener : getApplicationListeners()) {/ / getApplicationEventMulticaster () is applicationEventMulticaster get steps before initialization
		getApplicationEventMulticaster().addApplicationListener(listener);
	}

	// Do not initialize FactoryBeans here: We need to leave all regular beans
	// uninitialized to let post-processors apply to them!
	// Get all applicationListeners from the container
	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...
	// Distribute the Application Events generated in the previous step
	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
	this.earlyApplicationEvents = null;
	if(earlyEventsToProcess ! =null) {
		for(ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); }}}Copy the code

org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

In the previous step, most of the Spring components have been initialized. The remaining step is to initialize all the remaining singleton beans. Initializing a bean object in Spring is very complicated, such as loop dependencies, bean post-processor application, AOP proxy, etc. All of this will be covered in a future series of articles, but we need to understand that Spring uses this method to initialize all the beans in the container.

public void preInstantiateSingletons(a) throws BeansException {
	if (logger.isTraceEnabled()) {
		logger.trace("Pre-instantiating singletons in " + this);
	}

	// Iterate over a copy to allow for init methods which in turn register new bean definitions.
	// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
	// Get all beandefinitionNames in the container
	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

	// Trigger initialization of all non-lazy singleton beans...
	// Loop through initialization and object creation
	for (String beanName : beanNames) {
		// Get RootBeanDefinition, which represents the merged object of its own BeanDefinition and a BeanDefinition that may have a parent class
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		// If non-abstract and singleton, non-lazy loading
		if(! bd.isAbstract() && bd.isSingleton() && ! bd.isLazyInit()) {// If it is a factoryBean, create the object using the following method
			if (isFactoryBean(beanName)) {
				// if it is a factoryBean, add & to create the factoryBean
				Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
				if (bean instanceof FactoryBean) {
					finalFactoryBean<? > factory = (FactoryBean<? >) bean;boolean isEagerInit;
					if(System.getSecurityManager() ! =null && factory instanceofSmartFactoryBean) { isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<? >) factory)::isEagerInit, getAccessControlContext()); }else {
						isEagerInit = (factory instanceofSmartFactoryBean && ((SmartFactoryBean<? >) factory).isEagerInit()); }if(isEagerInit) { getBean(beanName); }}}else {
				// Instead of a factory bean, use this method to create objectsgetBean(beanName); }}}// Trigger post-initialization callback for all applicable beans...
	for (String beanName : beanNames) {
		Object singletonInstance = getSingleton(beanName);
		/ / check whether all the bean SmartInitializingSingleton interface
		if (singletonInstance instanceof SmartInitializingSingleton) {
			final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
			if(System.getSecurityManager() ! =null) {
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					smartSingleton.afterSingletonsInstantiated();
					return null;
				}, getAccessControlContext());
			}
			else {
				/ / callback afterSingletonsInstantiated () method, we can do something in the callbacksmartSingleton.afterSingletonsInstantiated(); }}}}Copy the code

org.springframework.context.support.AbstractApplicationContext#finishRefresh

Once the entire container is initialized, some cleanup is done here, such as clearing the cache, initializing the lifecycle handler, publishing container refresh events, and so on.

protected void finishRefresh(a) {
	// Clear context-level resource caches (such as ASM metadata from scanning).
	// Clear the cache
	clearResourceCaches();

	// Initialize lifecycle processor for this context.
	// Initialize the post-processor associated with the life cycle
	initLifecycleProcessor();

	// Propagate refresh to lifecycle processor first.
	// Retrieve the previously defined LifecycleProcessor callback onRefresh() method
	getLifecycleProcessor().onRefresh();

	// Publish the final event.
	Publish the container refresh completion event
	publishEvent(new ContextRefreshedEvent(this));

	// Participate in LiveBeansView MBean, if active.
	LiveBeansView.registerApplicationContext(this);
}
Copy the code

I’m Aobing, the more you know, the more you don’t know, thank you for your talent: likes, favorites and comments, we’ll see you next time!


This article is constantly updated. You can search “Santaizi Aobing” on wechat and read it for the first time. Reply [Information] There are the interview materials and resume templates for first-line big factories prepared by me.