preface

The author retypesets the previous Spring format and explains it one line at a time. I hope you like it. Spring Boot is an easy way to start a startup. How does Spring scan for a class that uses @Component and put it in the BeanFactory? How does it start? Now let’s take a look. This series will cover the process of starting the Spring Boot in several chapters. Since I wrote this article in many environments, the code may vary depending on the Spring Boot version, but the idea is the same.

1. Create a SpringApplication object

/ / 1. The main method
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class DemoApplication {

    public static void main(String[] args) {
        // To start the entry, click the run methodSpringApplication.run(DemoApplication.class, args); }}// 2. Create an instance of new SpringApplication
/** * Create a new Instance of SpringApplication, i.e. new SpringApplication(), and define the main class as the loading source of the Bean */
/**
 * Create a new {@link SpringApplication} instance. The application context will load
 * beans from the specified primary sources (see {@link SpringApplication class-level}
 * documentation for details. The instance can be customized before calling
 * {@link#run(String...) *}.@param resourceLoader the resource loader to use
 * @param primarySources the primary bean sources
 * @see #run(Class, String[])
 * @see #setSources(Set)
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class
       ... primarySources) {
	this.resourceLoader = resourceLoader;
	Assert.notNull(primarySources, "PrimarySources must not be null");
	// The setup class entry is the startup class
	this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
	// Set the application type to SERVLET, NONE, and REACTIVE. See the WebApplicationType enumeration class for details
	this.webApplicationType = WebApplicationType.deduceFromClasspath();
	/ / set the initializer, the getSpringFactoriesInstances () method from the spring. Read in the factories
	setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
	// Set up the listener, as long as you see this method, just read the desired class from spring.factories and load it
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	this.mainApplicationClass = deduceMainApplicationClass();
}
Copy the code

2. Call Run () on the SpringApplication object

/** * 1. Run */
public ConfigurableApplicationContext run(String... args) {
	StopWatch stopWatch = new StopWatch();
	// Start the timer
	stopWatch.start();
	ConfigurableApplicationContext context = null;
	Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
	// Configure some peripherals
	configureHeadlessProperty();
	// Get listeners. GetRunlisteners also get listeners
	SpringApplicationRunListeners listeners = getRunListeners(args);
	// The listener starts executing
	listeners.starting();
	try {
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
		ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
		configureIgnoreBeanInfo(environment);
		/ / print the banner
		Banner printedBanner = printBanner(environment);
		// To create the application context, see 2
		context = createApplicationContext();
		// Load the exception reporting period
		exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
				new Class[] { ConfigurableApplicationContext.class }, context);
		// To prepare context, see 3
		prepareContext(context, environment, listeners, applicationArguments, printedBanner);
		// Refresh the context
		refreshContext(context);
		afterRefresh(context, applicationArguments);
		stopWatch.stop();
		if (this.logStartupInfo) {
			new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
		}
		listeners.started(context);
		callRunners(context, applicationArguments);
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, exceptionReporters, listeners);
		throw new IllegalStateException(ex);
	}

	try {
		listeners.running(context);
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, exceptionReporters, null);
		throw new IllegalStateException(ex);
	}
	return context;
}
/** * 2. This method creates a different context instance from the application type that the SpringApplication instance is loaded with. In this case, */ is created because it is a SERVLET type
protected ConfigurableApplicationContext createApplicationContext(a) { Class<? > contextClass =this.applicationContextClass;
	if (contextClass == null) {
		try {
		switch (this.webApplicationType) {
			case SERVLET:
				// org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
				// Called annotation configuration context instance
				contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
				break;
			case REACTIVE:
				contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
				break;
			default: contextClass = Class.forName(DEFAULT_CONTEXT_CLASS); }}catch (ClassNotFoundException ex) {
			throw new IllegalStateException(
					"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex); }}return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
/** * 3. This is an important part of how to load the bootstrap class to the BeanFactory
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
	context.setEnvironment(environment);
	postProcessApplicationContext(context);
	applyInitializers(context);
	listeners.contextPrepared(context);
	if (this.logStartupInfo) {
		logStartupInfo(context.getParent() == null);
		logStartupProfileInfo(context);
	}
	// Add boot specific singleton beans
	Because the context is AnnotationConfigServletWebServerApplicationContext / / here
	/ / so he inherited from ServletWebServerApplicationContext
	/ / ServletWebServerApplicationContext GenericWebApplicationContext inheritance
	/ / GenericWebApplicationContext GenericApplicationContext inheritance
	/ / so he is the beanFactory default private final DefaultListableBeanFactory the beanFactory;
	ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
	beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
	if(printedBanner ! =null) {
		beanFactory.registerSingleton("springBootBanner", printedBanner);
	}
	if (beanFactory instanceof DefaultListableBeanFactory) {
		((DefaultListableBeanFactory) beanFactory)
				.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
	}
	if (this.lazyInitialization) {
		context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
	}
	// Load the sources
	Set<Object> sources = getAllSources();
	Assert.notEmpty(sources, "Sources must not be empty");
	// This method describes how to register the boot class with the beanFactory, paving the way for the following refreshContext
	// The load method also has the bootstrap class registered into BeanDefinition
	load(context, sources.toArray(new Object[0]));
	listeners.contextLoaded(context);
}
/** * BeanDefinition: BeanDefinition: BeanDefinition: BeanDefinition: BeanDefinition: BeanDefinition: BeanDefinition * class metadata and AnnotatedGenericBeanDefinition is to open the class metadata interface * when the adb and beanName in BeanDefinitionHolder initialization together * /
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
		@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
		@Nullable BeanDefinitionCustomizer[] customizers) {
	// Define the metadata object of the bean, the following is to get the bean name and so on
	AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
	if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
		return;
	}
	abd.setInstanceSupplier(supplier);
	ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name ! =null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
	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)); }}}if(customizers ! =null) {
		for(BeanDefinitionCustomizer customizer : customizers) { customizer.customize(abd); }}// BeanDefinitionHolder is created when the metadata object is beanName
	// He saves some aliases and beanName altogether
	BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
	// This will formally register the bean with the this.beanDefinitionMap and this.beanDefinitionNames properties
	/ / which two attributes are just the default the beanFactory is DefaultListableBeanFactory. Class
	BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
Copy the code

3. Core method refreshContext

/** * 1. This method is actually the core process of the whole Spring startup process or ioc etc. * this method is explained in several steps */
public void refresh(a) throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		// Prepare the context
		prepareRefresh();
		// Tell the subclass to refresh the internal bean factory.
		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.
			// This method scans all beans and loads all beans
			invokeBeanFactoryPostProcessors(beanFactory);
			

			// Instantiate all remaining (non-lazy-init) singletons.
			// The first step is to scan and load, which is the actual creation of the Bean instance
			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(); }}}/** * 2
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	/ / getBeanFactoryPostProcessors () this method is to get the current all the beanFactory enhancer in can see, at present there are three default
	// 1. SharedMetadataReaderFactoryContextInitializer $CachingMetadataReaderFactoryPostProcessor applyInitializ in prepareContext Ers to insert
	// 2. ConfigurationWarningsApplicationContextInitializer $ConfigurationWarningsPostProcessor applyInitializer in prepareContext S insert
	// 3. ConfigFileApplicationListener $PropertySourceOrderingPostProcessor listeners. The last line in prepareContext contextLoaded insert (context)
	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())); }}/ * * * 3. This method, which includes a large number of operations we come together to see * /
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List
       
         beanFactoryPostProcessors)
        {
	// Invoke BeanDefinitionRegistryPostProcessors first, if any.
	Set<String> processedBeans = new HashSet<>();
	/ / this context is AnnotationConfigServletWebServerApplicationContext instance he inherited class has BeanDefinitionRegistry interface
	// So this must come in
	if (beanFactory instanceof BeanDefinitionRegistry) {
		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
		List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
		List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
		// This loop classifies the three enhancers
		/ / BeanDefinitionRegistryPostProcessor CachingMetadataReaderFactoryPostProcessor implementation
		/ / BeanDefinitionRegistryPostProcessor ConfigurationWarningsPostProcesso implementation
		/ / spring BeanFactoryPostProcessor PropertySourceOrderingPostProcessor implementation
		for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
			if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
				BeanDefinitionRegistryPostProcessor registryProcessor =
						(BeanDefinitionRegistryPostProcessor) postProcessor;
				// Register BeanDefinition here
				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.
		List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

		// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
		/ / here get beanName not just enhancer but constant org. Springframework. Context. The annotation. InternalConfigurationAnnotationProcessor
		/ / and this cycle will ConfigurationClassPostProcessor loading up.
		/ / then we will ask ConfigurationClassPostProcessor when loaded?
		// createApplicationContext This is where the configuration is loaded when Spring selects Servlet mode
		// CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME is put into the beanFactory as beanname.configuration_annotation_processor_bean_name
		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);
		/ / when ConfigurationClassPostProcessor back run processConfigBeanDefinitions method, jump to 4
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		currentRegistryProcessors.clear();

		// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
		postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
		for (String ppName : postProcessorNames) {
			if(! processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear();// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
		boolean reiterate = true;
		while (reiterate) {
			reiterate = false;
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
			for (String ppName : postProcessorNames) {
				if(! processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate =true;
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();
		}

		// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
		invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
		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!
	String[] postProcessorNames =
			beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true.false);

	// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
	// Ordered, and the rest.
	List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
	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<>(orderedPostProcessorNames.size());
	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<>(nonOrderedPostProcessorNames.size());
	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();
}
/** * 4. This is where the bootstrap class is selected and ComponentScan is started. This is where auto-assembly is done@Import* /
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
	List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
	String[] candidateNames = registry.getBeanDefinitionNames();
	//configCandidates will add the boot class
	for (String beanName : candidateNames) {
		BeanDefinition beanDef = registry.getBeanDefinition(beanName);
		if(beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) ! =null) {
			if (logger.isDebugEnabled()) {
				logger.debug("Bean definition has already been processed as a configuration class: "+ beanDef); }}else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
			configCandidates.add(newBeanDefinitionHolder(beanDef, beanName)); }}/** * omit code */
	// Parse each @Configuration class
	// This is the implementation class to find Component
	ConfigurationClassParser parser = new ConfigurationClassParser(
			this.metadataReaderFactory, this.problemReporter, this.environment,
			this.resourceLoader, this.componentScanBeanNameGenerator, registry);
	Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
	Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
	do {
		Parse has a number of Component classes to use here
		parser.parse(candidates);
		/** * omit code */
	}
	while(! candidates.isEmpty());/** * omit code */
}
/** * 5. Scan Component and autowage, this is also important, and the code has several complex recursions
protected final SourceClass doProcessConfigurationClass( ConfigurationClass configClass, SourceClass sourceClass, Predicate
       
         filter)
       
			throws IOException {

		/** * omit code */
		// Process any @ComponentScan annotations
		// Why is this an array? When you use @ComponentScans(value = {@componentScan ("com.example.test"), @ComponentScan("com.example.test1")})
		// The length here will become 3
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if(! componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			This is why the start class is always at the outermost layer of all packages. If you want to scan other modules or start packages outside the class, you need the @scanComponent annotation
			for (AnnotationAttributes componentScan : componentScans) {
				// The config class is annotated with @ComponentScan -> perform the scan immediately
				// The Definition of each class with the @Component annotation will be placed inside scannedBeanDefinitions
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				// Check the set of scanned definitions for any further config classes and parse recursively if needed
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						Parse is the same as the previous parser. Parse is an array and a single Bean
						/ / and he will recursively doProcessConfigurationClass () method, and to perform a access to see if this class is @ ComponentScan, and continues to scan until the endparse(bdCand.getBeanClassName(), holder.getBeanName()); }}}}// Process any @Import annotations
		// In fact, every parse method goes to this point and loops through the annotation of each class until there is no annotation place to load the @import annotation class. This is how auto-assembly works
		@import is a key point. Import this class into the BeanFactory
		processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

		/** * omit code */
		return null;
	}
Copy the code

Creating a Bean instance

/** * create an instance of the bean. ** * create an instance of the bean. ** * create an instance of the bean. Each interface * 3 of the bean's life cycle is triggered when doCreateBean is created. In fact, I found that ApplicationContextAware is not part of the bean lifecycle, but part of the input context * 4. Because the ApplicationContextAware is actually caused by adding the AnnotationConfigServletWebServerApplicationContext class * 5. I will have the following UML diagram to give you a better understanding of how beans are created */
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.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		// Get all BeanName
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if(! bd.isAbstract() && bd.isSingleton() && ! bd.isLazyInit()) {if (isFactoryBean(beanName)) {
					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{ getBean(beanName); }}}// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if(System.getSecurityManager() ! =null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else{ smartSingleton.afterSingletonsInstantiated(); }}}}Copy the code

About the ApplicationContext

Achieve ApplicationContextAware interface will call setApplicationContext method and ApplicationContextAwareProcessor BeanPostProcessor and implementation, And ApplicationContextAwareProcessor registered by Spring force, so if a Bean implementation ApplicationContextAware and BeanPostProcessor, So when you initialize the Bean that has BeanPostProcessor, you create that Bean and then you call the setApplicationContext method and then you call the method that BeanPostProcessor implements, which is a little tricky, So finally I want to Debug myself

Bean life cycle flowchart

summary

When I reconstructed this article, it was actually because I didn’t understand the previous article, so I hope you can understand this chapter. If you can’t read it, it must mean that my literary talent is not good enough. I hope you can point out my mistakes. Speaking of Spring, in fact, all of you are Spring engineers, but you must be too busy to study the whole Spring process. Here I help you all ready.