Spring Startup Process


1. The Demo

  • DemoThe code is very simple, the whole project structure is as follows:
  • pomRely on
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.8. RELEASE</version>
</dependency>
Copy the code
  • Two classes under the service packageOrderService,UserServiceOnly added@ServiceAnnotation, two classes under the DAO packageOrderDao,UserDaoOnly added@RepositoryAnnotation.MainApplicationOnly in the classmain()Methods. The code is as follows:
public static void main(String[] args) {
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

    UserService userService = applicationContext.getBean(UserService.class);
    System.out.println(userService);

    OrderService orderService = applicationContext.getBean(OrderService.class);
    System.out.println(orderService);

    UserDao userDao = applicationContext.getBean(UserDao.class);
    System.out.println(userDao);

    OrderDao orderDao = applicationContext.getBean(OrderDao.class);
    System.out.println(orderDao);

    applicationContext.close();
}
Copy the code
  • AppConfigClass is a configuration class with two annotations, plus@ConfigurationShow thatAppConfigIs a configuration class, plus@ComponentScanIs to tellSpringThe code for which packages to scan is as follows:
@Configuration
@ComponentScan("com.tiantang.study")
public class AppConfig {}Copy the code

2. Start

  • runMainApplicationIn themain()Method, this oneSpringThe container is up and running. The console printed them out separatelyUserService,OrderService,UserDao,OrderDaothehashCode.
  • So the question is, compared to the pastxmlThe way you configure it, now it’s just a few lines of code, oneSpringThe container will be up and running, and we’ll be able to get it from the containerBean.SpringHow does it work internally? Let’s analyze it step by stepSpringStart the source code.

3. Entrance

  • The entry of the program ismain()Method, as you can see from the code, the core code is only one line,new AnnotationConfigApplicationContext(AppConfig.class), with this line of code, willSpringThe container is created, and then we can go throughgetBean()The object is retrieved from the container. Therefore, the analysisSpringSource code, fromAnnotationConfigApplicationContextThe argument constructor of the.
  • AnnotationConfigApplicationContextwithClassPathXmlApplicationContextThe effect is the same, the former corresponding is adoptedJavaConfigThe latter corresponds to the application of technologyXMLApplication of configuration

4. Basic concepts

  • In theSpringBefore reading the source code, you need to understand a few concepts.
    1. SpringWill give everything toSpringManage the class and scan itclassFile, parse it intoBeanDefinitionIn theBeanDefinitionFor example, whether the class is a singleton,BeanType, whether lazy loading, which classes to rely on, autoassemble model.SpringWhen you create an object, that’s the basisBeanDefinitionTo createBean.
    1. SpringContainers in this article can be simply understood asDefaultListableBeanFactory, it isBeanFactoryClass, which has several very important properties:beanDefinitionMapIs amapFor storagebeanThe correspondingBeanDefinition;beanDefinitionNamesIs aListCollection, used to store allbeanthename;singletonObjectsIs aMapIs used to store all created singletonsBean.
    1. SpringThere are a lot of rear processors, but ultimately they can be divided into two types, one isBeanFactoryPostProcessor, one isBeanPostProcessor. The former is used for interventionBeanFactoryThe latter is used for interventionBeanThe creation process of. The post processor is very important,beanAnd the creation ofAOPThe implementation of the backend processor is entirely dependent.

5. AnnotationConfigApplicationContext constructor

  • AnnotationConfigApplicationContextThe constructor argument is a mutable array that can be passed to multiple configuration classes at this timeDemoIn, only passedAppConfigA class.
  • In the constructor, it is called firstthis()In thethis()Class is initialized by calling the parent class constructorBeanFactory, and registered seven post-processors to the container. And then callregister(), and puts the constructor parameters intoBeanDefinitionMapIn the. The last executionrefresh()Method, this is the wholeSpringThe core of container startup will also be analyzed in this articlerefresh()The process and role of methods.
public AnnotationConfigApplicationContext(Class
       ... annotatedClasses) {
	/ / initialize a the BeanFactory, DefaultListableBeanFactory as default
	// Initializes a beanDefinition reader and registers seven Spring postprocessors (including BeanPostProcessor and BeanFactoryPostProcessor) with the container.
	Refresh () initializes a scanner that appears not to be used later, but a new scanner is used in refresh().
	this(a);// Register configuration classes in BeanDefinitionMap
	register(annotatedClasses);
	refresh();
}
Copy the code
5.1 this () call
  • this()Will be calledAnnotationConfigApplicationContextNo parameter constructor, while inJavaThe constructor of the parent class is called first. So it’s called firstAnnotationConfigApplicationContextThe parent classGeniricApplicationContextClass, initialized in the parent classbeanFactory, that is, directnewaDefaultListableBeanFactory.
public GenericApplicationContext(a) {
	this.beanFactory = new DefaultListableBeanFactory();
}
Copy the code
  • inthis()Through thenew AnnotatedBeanDefinitionReader(this)Instantiated oneBeanReader, and toBeanDefinitionMapAdd the7An element. throughnew ClassPathBeanDefinitionScanner(this)A scanner is instantiated (this scanner is not used later).
public AnnotationConfigApplicationContext(a) {
    / / here will call the superclass constructor, namely first execution super (), initialize DefaultListableBeanFactory
    // Initializes the bean reader and registers 7 spring native classes with Spring. Registration means placing beanDefinitionDefinitions for these 7 classes into a BeanDefinitionMap
    this.reader = new AnnotatedBeanDefinitionReader(this);
    // Initialize the scanner
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}
Copy the code
  • performthis.reader = new AnnotatesBeanDefinitionReader(this)Is finally called toAnnotationConfigUtils.registerAnnotationConfigProcessors(BeanDefinitionRegistry registry,Object source)Method, this method is directed toBeanDefinitionMapAdd the7A class, this7A class ofBeanDefinition(onBeanDefinitionCan refer to the previous explanation) areRootBeanDefinition, these classes are respectivelyConfigurationClassPostProcessor,AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor,PersistenceBeanPostProcessor,EventListenerMethodProcessor,DefaultEventListenerFactory.
  • Of these seven classes,ConfigurationClassPostProcessor,AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessorThese three classes are so important that they are briefly introduced in the following code and analyzed in separate articles. The focus of this article is to finish the introductionSpringStart the process.
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) {
	DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
	// omit some code...
	Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
	/ / registered ConfigurationClassPostProcessor, this kind of super important, it completed the added Configuration to annotate class parsing, @ ComponentScan, @ the parsing of the Import.
	if(! registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(ConfigurationClassPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
	}
	/ / register AutowiredAnnotationBeanPostProcessor, the rear of the bean processors for processing the @autowired injection
	if(! registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
	}
	/ / register RequiredAnnotationBeanPostProcessor
	if(! registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
	}
	/ / registered CommonAnnotationBeanPostProcessor, used to handle such as @ Resource, @ PostConstruct annotations in conformity with the JSR - 250 standard, etc
	// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
	if(jsr250Present && ! registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
	}
	/ / register PersistenceAnnotationBeanPostProcessor, with support for JPA
	// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
	if(jpaPresent && ! registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition();
		try {
			def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
					AnnotationConfigUtils.class.getClassLoader()));
		}
		catch (ClassNotFoundException ex) {
			throw new IllegalStateException(
					"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
		}
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	/ / registered EventListenerMethodProcessor to treatment upon the @ EventListener annotation methods
	if(! registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(EventListenerMethodProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
	}

	/ / register DefaultEventListenerFactory, don't know what to use for the time being, from the name of the class, is an event listener's factory
	if(! registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(DefaultEventListenerFactory.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
	}
	return beanDefs;
}
Copy the code
  • callthis.scanner = new ClassPathBeanDefinitionScanner(this)To initialize a scanner that is not used when scanning packets laterSpringInitialized to satisfy other scenarios, such as developer manual passregister(configClass)Is used when scanning packets.
5.2 register (annotatedClasses)

Configure the incoming class annotatedClasses parsed into BeanDefinition (actual type AnnotatedGenericBeanDefinition), and then into the BeanDefinitionMap, Behind this can parse in ConfigurationClassPostProcessor annotatedClasses, AppConfig class in the demo, for example, only the parsing AppConfig class, You can only know which packages Spring is scanning (because of the @ComponentScan annotation in the AppConfig class), and you can only know which packages Spring is scanning for beans that you need to hand over to Spring to manage so that you can use Spring to create beans.

5.3 Running the refresh() method

The Refresh () method is the heart of the entire Spring container, where beans are instantiated, initialized, autowiring, AOP, and so on. Let’s take a look at the refresh() method code with some personal understanding and a brief introduction to what each line of code does, followed by a detailed analysis of several important methods

public void refresh(a) throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		// Initializes the properties profile, validates required properties, and listeners
		prepareRefresh();
		// Tell the subclass to refresh the internal bean factory.
		// Set the serialization ID for beanFactory
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
		// Register two BeanPostProcessors and three environment-specific beans with the beanFactory
		/ / the two rear processor for ApplicationContextAwareProcessor and ApplicationListenerDetector
		// The previous postprocessing is a callback to the setApplicationContext() method for classes that implement the ApplicationContextAware interface,
		The latter handler is used to detect the ApplicationListener class. When a Bean that implements the ApplicationListener interface is created, it is added to the listener list
		prepareBeanFactory(beanFactory);
		try {
			// Allows post-processing of the bean factory in context subclasses.
			// Empty method, implemented by subclasses
			postProcessBeanFactory(beanFactory);
			// Implements all BeanFactoryPostProcessors, both custom and spring built-in. By default, the container is only a Spring BeanFactoryPostProcessor, namely: Spring built-in, ConfigurationClassPostProcessor (this class is very important)
			/ / will perform first realized BeanDefinitionRegistryPostProcessor interface classes, then execute the spring BeanFactoryPostProcessor class
			/ / postProcessorBeanFactory ConfigurationClassPostProcessor class () method for the @ the parsing of the Configuration class, @ ComponentScan scanning, and the processing of @ Import annotations
			// After this step, the beanDefinitionMap of all spring-managed beans is placed in the beanFactory beanDefinitionMap
			/ / at the same time ConfigurationClassPostProcessor class postProcessorBeanFactory () method after the execution, to add a container rear processor -- -- ImportAwareBeanPostProcessor
			invokeBeanFactoryPostProcessors(beanFactory);
			// Register all beanPostProcessors. At this step, all beanPostProcessors are instantiated because the getBean() method is called inside the method
            // Why instantiate BeanPostProcessor at this stage? Because the bean is instantiated later, and the BeanPostProcessor is used to interfere with bean creation, all BeanPostProcessors (including those defined by the developer) must be instantiated prior to bean instantiation
			/ / and then register the ApplicationListenerDetector, the aim is to put ApplicationListenerDetector in the end to rear the processor
			registerBeanPostProcessors(beanFactory);
			// Initialize message source for this context.
           // Initialize MessageSource for message internationalization. Message internationalization is not used in a typical project
			initMessageSource();
			// Initialize event multicaster for this context.
			/ / initialize event broadcast, if the container is the name for applicationEventMulticaster radio apparatus, using the radio device
			/ / if not, then a SimpleApplicationEventMulticaster initialization
            // The purpose of an event broadcaster is to publish events and find event listeners for the published times.
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			// Performing other initialization operations, such as integrating with SpringMVC, requires initializing some other beans, but for pure Spring projects, the onFresh method is an empty method
			onRefresh();

			// Check for listener beans and register them.
			// This step puts the bean name of the custom listener into the event broadcaster
			// Early ApplicationEvents will also be published (for individual Spring projects, no ApplicationEvents will be published at this point, but when integrated with springMVC, springMVC will execute the onRefresh() method, Events will be posted here)
			registerListeners();
			// Instantiate the remaining non-lazy-loaded singleton bean(note: residual, non-lazy-loaded, singleton)
            // Why is it surplus? If the developer customized the BeanPosrProcessor, and the BeanPostProcessor was instantiated earlier, it will not be instantiated here, so the remaining term is used here
			finishBeanFactoryInitialization(beanFactory);
			// The main thing to do is to publish a ContextRefreshEvent notifying everyone that the Spring container refresh has finished.
			finishRefresh();
		}
		catch (BeansException ex) {
			// Destroy the bean after an exception
			destroyBeans();
			// Reset 'active' flag.
			cancelRefresh(ex);
			// Propagate exception to caller.
			throw ex;
		}
		finally {
           // During bean instantiation, a lot of information is cached, such as bean annotation information, but when the singleton bean is instantiated, the cached information is no longer used, so the memory resources can be freedresetCommonCaches(); }}}Copy the code

6. The refresh () method

  • inrefresh()Among the methods, the most important one isinvokeBeanFactoryPostProcessors(beanFactory)finishBeanFactoryInitialization(beanFactory). Other methods are relatively simple, the following main analysis of these two methods, the role of other methods, you can refer to the above source notes.
6.1 invokeBeanFactoryPostProcessors ()
  • The purpose of this method is to perform allBeanFactoryPostProcessorBecause ofSpringThere will be a built-inBeanFactoryPostProcessor, i.e.,ConfigurationClassPostProcessor(This is the only default if the developer does not customize itBeanFactoryPostProcessor), the post-processor will parse out all the deliverables as they are processedSpringcontainer-managedBeanAnd parse them intoBeanDefinitionAnd then put it inBeanFactorytheBeanDefinitionMapIn the.
  • The method will eventually be calledPostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()Method, whose main function is to perform allBeanFactoryPostProcessorthepostProcessorBeanFactory()Methods.BeanFactoryPostProcessorAnd divided into two cases, one is direct realizationBeanFactoryPostProcessorInterface class, another case is implementedBeanDefinitionRegistryPostProcessorInterface (BeanDefinitionRegistryPostProcessorinheritedBeanFactoryPostProcessorInterface).
  • Execute all of them first during executionBeanDefinitionRegistryPostProcessorthepostProcessorBeanDefinitionRegistry()Method, and then executeBeanFacotryPostProcessorthepostProcessorBeanFactory()Methods.
public interface BeanFactoryPostProcessor {
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
Copy the code
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
Copy the code
  • By default,SpringThere’s a built-in oneBeanFactoryPostProcessor, that is:ConfigurationClassPostProcessorClass, which implementsBeanDefinitionRegistryPostProcessorClass, so it executesConfigurationClassPostProcessor.postProcessorBeanDefinitionRegistry.ConfigurationClassPostProcessortheUMLThe picture is as above (some non-important inheritance relationship has been deleted)
6.2 registerBeanPostProcessors ()
  • The purpose of this method is to find all of themBeanPostProcessorAnd then put theseBeanPostProcessorInstantiate (will callgetBean()Method,getBean()The main logic of the method is ifbeanExists in theBeanFactoryIs returnedbean; If not, it will be created. It will be analyzed in detail latergetBean()Execution logic). Will thesePostProcessorAfter instantiation, finally put intoBeanFactorythebeanPostProcessorsAttribute.
  • Question: How do I find all of themBeanPostProcessor? includingSpringBuilt-in and developer custom.
  • Due to therefresh()Method is executed firstinvokeBeanFactoryPostProcessor()Method, so all customBeanPostProcessorClasses have been scanned and resolved intoBeanDefinition(Who does the scanning and parsing?ConfigurationClassPostProcessorMade), deposited toBeanFactorytheBeanDefinitionMap, so here you can find all of them by using the following line of codeBeanPostProcessorAnd then throughgetBean()Instantiate everything, and finally add the instantiated object toBeanFactorythebeanPostProcessorsProperty, the property is aListCollection.
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true.false);
Copy the code
  • And then finally re-registeredApplicationListenerDetectorThe purpose of doing this is to changeApplicationListenerDetectorPut it at the very end of the rear processor
  • registerBeanPostProcessor()The final call is going to bePostProcessorRegistrationDelegate.registerBeanPostProcessors(), the following isPostProcessorRegistrationDelegate.registerBeanPostProcessors()Method code
public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

	Find all BeanpostProcessors from BeanDefinitionMap
	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true.false);
	/ /... Omit some code...

	// Find the PriorityOrdered, Ordered, and normal BeanPostProcessor implemented separately
	for (String ppName : postProcessorNames) {
		if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			// The getBean() method is called here, so the BeanPostProcessor is instantiated here
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			priorityOrderedPostProcessors.add(pp);
			if (pp instanceofMergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); }}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
			orderedPostProcessorNames.add(ppName);
		}
		else{ nonOrderedPostProcessorNames.add(ppName); }}// First, register the BeanPostProcessors that implement PriorityOrdered.
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	// Add the BeanPostProcessor that implements the PriorityOrdered interface to the BeanFactory beanPostProcessors collection
	registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

	// Instantiate and add the Ordered interface and normal BeanPostProcessor to the combination of beanPostProcessors, the same logic as the postprocessor that handled PriorityOrdered
	List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
	for (String ppName : orderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		orderedPostProcessors.add(pp);
		if (pp instanceof MergedBeanDefinitionPostProcessor) {
			internalPostProcessors.add(pp);
		}
	}
	sortPostProcessors(orderedPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, orderedPostProcessors);
	
	// Now, register all regular BeanPostProcessors.
	List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
	for (String ppName : nonOrderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		nonOrderedPostProcessors.add(pp);
		if (pp instanceof MergedBeanDefinitionPostProcessor) {
			internalPostProcessors.add(pp);
		}
	}
	registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
	
	// Finally, re-register all internal BeanPostProcessors.
	sortPostProcessors(internalPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, internalPostProcessors);
	
	// Re-register post-processor for detecting inner beans as ApplicationListeners,
	// moving it to the end of the processor chain (for picking up proxies etc).
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));

	/ / will finally ApplicationListenerDetector this post processor back into the same beanPostProcessor, the aim is to put it in the rear to the end of the processor
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
Copy the code
  • As you can see from the source code above,BeanPostProcessorThere is a priority, achievedPriorityOrderedThe interface has the highest priority, followed byOrderedInterface, and finally genericBeanPostProcessor. The one with the highest priority will be put in firstbeanPostProcessorsThe front of this collection, so that when executed, the highest-priority post-processor is executed first (becauseListThe set is ordered).
  • So in practice, if we come across something that needs to be prioritizedBeanPostProcessorExecute, and you can make it happenPriorityOrderedInterface orOrderedInterface.
6.3 initMessageSource ()
  • Used to support message internationalization, which is not currently used in general projects.
6.4 initApplicationEventMulticaster ()

The method to initialize the radio apparatus, an event if the container of beanName for applicationEventMulticaster radio apparatus, is the use of the radio; If not, a SimpleApplicationEventMulticaster initialization. This class holds all applicationListeners. When an ApplicationEvent is published, the listener can determine the event type, Retrieves the ApplicationListener that is interested in the event.

  • initApplicationEventMulticaster()The source code for the method is as follows (omitting some log information):
protected void initApplicationEventMulticaster(a) {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	/ / whether the spring container already exists beanName = applicationEventMulticaster event broadcast
	// For example, if the developer registers one himself
	// If there is one, use one that already exists; Otherwise use the spring default: SimpleApplicationEventMulticaster
	if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
		this.applicationEventMulticaster =
				beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
	}
	else {
		this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
		beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); }}Copy the code
6.5 onRefresh ()

Performing other initialization operations, such as integrating with SpringMVC, requires initializing some other beans, but for pure Spring projects, the onRefresh() method is an empty method.

6.6 registerListeners ()

This step will put the custom listener bean name into the event broadcaster, and will also publish earlier ApplicationEvents. (For individual Spring projects, no ApplicationEvents will be published at this point, but when integrated with SpringMVC, SpringMVC executes the onRefresh() method, where events are published. The method source code is as follows:

protected void registerListeners(a) {
	// Register statically specified listeners first.
	for(ApplicationListener<? > listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); }// Find all applicationListeners from the BeanFactory, but do not initialize them because all beanPostProcessors need to modify them later during bean instantiation
	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true.false);
	for (String listenerBeanName : listenerBeanNames) {
		// Place the beanName of the event listener into the event broadcaster
		getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
	}

	// Release early events (pure Spring projects, no events at this point)
	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
	this.earlyApplicationEvents = null;
	if(earlyEventsToProcess ! =null) {
		for(ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); }}}Copy the code
6.7 finishBeanFactoryInitialization ()

This method is very important because it completes the instantiation and initialization of all non-lazy-loaded singleton beans, populates properties, and solves the problem of loop dependencies.

  • (Note that the instantiation and initialization processes are deliberately separated, as inSpringcreateBeanIn the process, is the first willBeanObjects are created by reflection and then passed through the post-processor (BeanPostProcessor) to assign a value to an object’s property. So the instantiation here is going to beBeanCreate out, initialize means forbeanAttribute assignment.
  • finishBeanFactoryInitialization()The code for the method is as follows,beanThe creation and initialization of thebeanFactory.preInstantiateSingletons()In the implementation.
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
	// Initialize the transformation service
	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));
	}
	/ / if the previous did not sign up for a similar to the rear is accomplished processor bean, then here will register a built-in rear attribute of the processor
	// Here we are dealing with annotated attributes
	if(! beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); }// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
	String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false.false);
	for (String weaverAwareName : weaverAwareNames) {
		getBean(weaverAwareName);
	}
	beanFactory.setTempClassLoader(null);
	/ / the BeanFactory configurationFrozen attribute set to true, give frozenBeanDefinitionNames attribute assignment
	// The purpose is not to modify the BeanDefinition of the bean elsewhere
	beanFactory.freezeConfiguration();

	// Instantiate all remaining (non-lazy-init) singletons.
	// instantiate all remaining non-lazy-loaded singletons
	beanFactory.preInstantiateSingletons();
}
Copy the code
6.7.1 preInstantiateSingletons () method
  • This method will judge firstbeanIs it aFactoryBeanAnd whether to instantiate immediatelyFactoryBeanthegetObject()Object that is returned, but is ultimately calledgetBean()Method to instantiate an object. inBeanAfter the instantiation and initialization is complete, it will determineBeanIs it implementedSmartSingletonInitializingInterface, which will be called if implementedafterSingletonInstantiated()Methods.
  • Tips: It’s mentioned hereFactoryBean, notBeanFactory. These two names are very similar, but the effect is very different, interested friends can first themselvesGoogleLook it up. Here is a brief introduction, and a separate article will be written laterFactoryBean, and through theFactoryBeanTo resolveSpringwithMyBatisPrinciples of integration.
  • FactoryBeanIs an interface whose implementation class registers two of them with the containerbean, an object that implements the type represented by the class itself, and an object that implements the type represented by overridingFactoryBeanIn the interfacegetObject()Method to returnbean. In the following example: two are registered to the containerbean, one isMapperFactoryBeanIn itself, one isUserMapper.
@Component
public class MapperFactoryBean implements FactoryBean {
    @Override
    public Object getObject(a) throws Exception {
        return new UserMapper();
    }

    @Override
    publicClass<? > getObjectType() {returnUserMapper.class; }}Copy the code
  • Due to thebeanInstantiation process is too complex, will be combined with the flow chart to analyze the source code.preInstantiatedSingletons()The execution flow chart of the method is as follows
  • preInstantiatedSingletons()The following code
public void preInstantiateSingletons(a) throws BeansException {
	if (logger.isDebugEnabled()) {
		logger.debug("Pre-instantiating singletons in " + this);
	}
	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
	// Trigger initialization of all non-lazy singleton beans...
	for (String beanName : beanNames) {
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		if(! bd.isAbstract() && bd.isSingleton() && ! bd.isLazyInit()) {// Determine if it is a factoryBean, and if it is a factoryBean, instantiate the factoryBean natively (other than the object corresponding to getObject()).
			// You also need to determine whether it immediately instantiates the object returned by getObject(), based on the return value of isEagerInit() of SmartFactoryBean
			if (isFactoryBean(beanName)) {
				// First instantiate the BeanFactory native object, then use isEagerInit() to determine whether to instantiate the BeanFactory getObject() object of the type returned
				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 is true, the object of the type returned by the FactoryBean is instantiated immediately
					if(isEagerInit) { getBean(beanName); }}}else{ getBean(beanName); }}}/ / in the bean is instantiated and attribute assignment is completed, if the bean implementation SmartInitializingSingleton interface, the method of the interface is the callback
	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
  • Found in the above source code, bothFactoryBeanOr ordinaryBean, and ultimately all callsgetBean()Method to createbean.
6.7.2 getBean ()
  • getBean()Method will calldoGetBean()Methods.
public Object getBean(String name) throws BeansException {
	return doGetBean(name, null.null.false);
}
Copy the code
6.7.3 doGetBean ()
  • indoGetBean()Method is first fetched from the cache (i.esingletonObjectsthismapCollection, why get it from the cache in the first place? Because fromSpringThe container gets objects and creates objects throughgetBean()Method, for singletons, the object is created only once, so the object is fetched from the cache first. If it exists, it does not need to be created. If present in cache, then callgetObjectForBeanInstance()Method, and returnbean. If it does not exist in the cache, proceed.
  • And then getBeanThe correspondingBeanDefinitionObject. Then judgebeanThere is no dependence,String[] dependsOn = mbd.getDependsOn()If there are dependent objects, the dependent objects are instantiated first.
  • Is called after the dependent object is createdgetSingleton(beanName,lambda)Method, whose second argument is alambdaThe expression is really createdbeanThe logic is in the method body of the expression, i.ecreateBean()Method,createBean()The method is createdbeanAnd then ingetSingleton(beanName,lambda)Method will be createdbeanDeposit tosingletonObjectsAttribute.createBean()Analysis later.
  • Created in the previous stepbeanAfter, eventually will still callgetObjectForBeanInstance(). The logic of this method is relatively simple. Judge firstbeanIs it aFactoryBeanIf not, return directlybean; If so, judge againbeanNameDoes it begin with an ampersand? If so, it getsFactoryBeanIs returned directlybean; Returns if it does not begin with an ampersandFactoryBeanthegetObject()Method return value object.
  • doGetBean()The method code is as follows
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
		@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
	final String beanName = transformedBeanName(name);
	Object bean;
	// Eagerly check singleton cache for manually registered singletons.
	Object sharedInstance = getSingleton(beanName);
	if(sharedInstance ! =null && args == null) {
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}
	else {
		// Fail if we're already creating this bean instance:
		// We're assumably within a circular reference.
		if (isPrototypeCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
		// Check if bean definition exists in this factory.
		BeanFactory parentBeanFactory = getParentBeanFactory();
		if(parentBeanFactory ! =null && !containsBeanDefinition(beanName)) {
			// Not found -> check parent.
			String nameToLookup = originalBeanName(name);
			if (parentBeanFactory instanceof AbstractBeanFactory) {
				return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
						nameToLookup, requiredType, args, typeCheckOnly);
			}
			else if(args ! =null) {
				// Delegation to parent with explicit args.
				return (T) parentBeanFactory.getBean(nameToLookup, args);
			}
			else {
				returnparentBeanFactory.getBean(nameToLookup, requiredType); }}if(! typeCheckOnly) {// Mark the bean as created
			// Clear the beanDefinition cache (mergedBeanDefinitions)
			markBeanAsCreated(beanName);
		}
		try {
			final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
			// Check if the bean is an abstract class
			checkMergedBeanDefinition(mbd, beanName, args);
			// Guarantee initialization of beans that the current bean depends on.
			// Ensure that the bean on which the current bean depends is initialized
			String[] dependsOn = mbd.getDependsOn();
			if(dependsOn ! =null) {
				for (String dep : dependsOn) {
					The isDependent() method is used to determine whether the deP depends on beanName
					if (isDependent(beanName, dep)) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName,
								"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
					}
					// Save the dependencies
					registerDependentBean(dep, beanName);
					try {
						getBean(dep);
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName,
								"'" + beanName + "' depends on missing bean '" + dep + "'", ex); }}}// Create bean instance.
			if (mbd.isSingleton()) {
				// At this point a lambda expression is passed into the getSingleton method,
				// Instead of executing the lambda expression immediately, the body of the lambda method starts executing when the getObject() method of the lambda expression is called
				sharedInstance = getSingleton(beanName, () -> {
					try {
						return createBean(beanName, mbd, args);
					}
					catch (BeansException ex) {
						destroySingleton(beanName);
						throwex; }}); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }else if (mbd.isPrototype()) {
				// It's a prototype -> create a new instance.
				Object prototypeInstance = null;
				try {
					beforePrototypeCreation(beanName);
					prototypeInstance = createBean(beanName, mbd, args);
				}
				finally {
					afterPrototypeCreation(beanName);
				}
				bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
			}
			else {
				String scopeName = mbd.getScope();
				final Scope scope = this.scopes.get(scopeName);
				if (scope == null) {
					throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
				}
				try {
					Object scopedInstance = scope.get(beanName, () -> {
						beforePrototypeCreation(beanName);
						try {
							return createBean(beanName, mbd, args);
						}
						finally{ afterPrototypeCreation(beanName); }}); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); }catch (IllegalStateException ex) {
					throw new BeanCreationException(beanName,
							"Scope '" + scopeName + "' is not active for the current thread; consider " +
							"defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); }}}catch (BeansException ex) {
			cleanupAfterBeanCreationFailure(beanName);
			throwex; }}if(requiredType ! =null && !requiredType.isInstance(bean)) {
		try {
			T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
			if (convertedBean == null) {
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
			return convertedBean;
		}
		catch (TypeMismatchException ex) {
			throw newBeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); }}return (T) bean;
}
Copy the code
  • getObjectForBeanInstance()The function of method is to basebeanNameTo determine returnFactoryBeanNative objects orgetObject()The object returned by the. ifbeanNameAn ampersand is used to indicate a returnFactoryBeanNative object, otherwise returnedgetObject()The object returned by the.
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
	if (BeanFactoryUtils.isFactoryDereference(name)) {
		if (beanInstance instanceof NullBean) {
			return beanInstance;
		}
		if(! (beanInstanceinstanceof FactoryBean)) {
			throw newBeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass()); }}// If it is not a FactoryBean object or a native object that obtains a FactoryBean (native objects mean beanName begins with &)
	// You can return the bean directly
	if(! (beanInstanceinstanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
		return beanInstance;
	}

	// If you are getting the type object returned by the getObject() method of a FactoryBean, you need to go to the following logic
	// For the getObject() method, the object it returns is instantiated the first time getObject is called, and the result is cached in factoryBeanObjectCache
	Object object = null;
	if (mbd == null) {
		object = getCachedObjectForFactoryBean(beanName);
	}
	if (object == null) {
		// Return bean instance from factory.FactoryBean<? > factory = (FactoryBean<? >) beanInstance;// Caches object obtained from FactoryBean if it is a singleton.
		if (mbd == null && containsBeanDefinition(beanName)) {
			mbd = getMergedLocalBeanDefinition(beanName);
		}
		booleansynthetic = (mbd ! =null && mbd.isSynthetic());
		// Gets the object returned by the FactoryBeanobject = getObjectFromFactoryBean(factory, beanName, ! synthetic); }return object;
}
Copy the code
6.7.4 createBean ()
  • doGetBean()It will end up callingcreateBean()To create abean.
  • createBean()There are two core lines of code in the method:
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
Copy the code
  • resolveBeforeInstantiation()Methods in thebeanCalled before instantiation, in this method the post-processor is executedInstantiationAwareBeanPostProcessorthepostProcessBeforeInstantiation()Methods,beanBefore instantiationbeanProcess. The significance of this extension point is significant,SpringtheAOPThis is where it’s done, and you can read it if you’re interestedAnnotationAwareAspectJAutoProxyCreatorThis class of source, the subsequent will be a separate article for analysis.
  • ifresolveBeforeInstantiation()The return value ofnull, the result is directly returned. If it isnull, the execution of the method continuesdoCreateBean(). indoCreateBean()In the method, theBeanInstantiation, attribute assignment, initialization, etc.
  • createBean()Flow chart of method
  • createBean()Method source code
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {
	RootBeanDefinition mbdToUse = mbd;
	// Make sure bean class is actually resolved at this point, and
	// clone the bean definition in case of a dynamically resolved Class
	// which cannot be stored in the shared merged bean definition.Class<? > resolvedClass = resolveBeanClass(mbd, beanName);if(resolvedClass ! =null&&! mbd.hasBeanClass() && mbd.getBeanClassName() ! =null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}
	// Prepare method overrides.
	try {
		mbdToUse.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}
	try {
		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		/ / the first call to post processor (perform all InstantiationAwareBeanPostProcessor subclass)
		/ / if a subclass of InstantiationAwareBeanPostProcessor postProcessBeforeInstantiation () method returns a value is not empty, said beans need to be enhanced,
		// The logic will not be executed at this point; this is where the actual use of AOP is implemented
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if(bean ! =null) {
			returnbean; }}catch (Throwable ex) {
		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
				"BeanPostProcessor before instantiation of bean failed", ex);
	}

	try {
		// The entry to the post-processor is executed the second time
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); }}Copy the code
6.7.5 doCreateBean ()
  • doCreateBean()The method will work through reflectionBeanCreate, and then pairbeanThe property population (which addresses the problem of loop dependencies while the property is being populated) ends up with theBeanThe callback initializes the associated methods, for example:BeanPostProcessor.postProcessBeforeInilization(),InilizaingBean.afterPropertiesSet()To givebeanConfiguration of theinitMethod()Methods, andBeanPostProcessor.postProcessAfterInilization().
  • doCreateBean()The flow chart of execution is as follows: [doCreateBean() method flowchart]P1-jj.byteimg.com/tos-cn-i-t2…)
  • doCreateBean()The code for the method (with some code deleted) is as follows:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
		throws BeanCreationException {
	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		// Instantiate the bean(the entry to the second post-processor execution), the second post-processor execution, mainly to infer the constructor needed to instantiate the bean
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	finalObject bean = instanceWrapper.getWrappedInstance(); Class<? > beanType = instanceWrapper.getWrappedClass();if(beanType ! = NullBean.class) { mbd.resolvedTargetType = beanType; }// At this point, the bean object has been created successfully, but the properties have not been set and other post-processing has not been done
	// Allow post-processors to modify the merged bean definition.
	synchronized (mbd.postProcessingLock) {
		if(! mbd.postProcessed) {try {
				// The third time the post-processor is executed, the bean's annotation metadata information is cached (for later use in property population)
				/ / this step for CommonAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor, RequiredAnnotationBeanPostProcessor such processors
				// The annotation information of the bean is parsed and cached into the injectionMetadataCache property in the afterprocessor
				/ / for the ApplicationListenerDetector processor, but if the bean is singleton logo in singletonNames this Map types of properties
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			}
			mbd.postProcessed = true; }}// Determine if a bean is placed in singletonFactories (exposed ahead of time to solve the problem of loop dependencies)
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
			isSingletonCurrentlyInCreation(beanName));
	if (earlySingletonExposure) {
		// The fourth post-processor occurs
		// Retrieve the pre-exposed bean (s) in singletonFactories with the key beanName and value a lambda expression
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}
	// Initialize the bean instance.
	Object exposedObject = bean;
	try {
		// Fill the properties, the fifth and sixth post-processor entry
		populateBean(beanName, mbd, instanceWrapper);
		// Perform the processor entry after the seventh and eighth times
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
	catch (Throwable ex) {
	}
	return exposedObject;
}
Copy the code
  • createBeanInstance()When an object is created by reflection, the post-processor is executed first, by calling the post-processor’sdeternineCondidateConstructors()Method to infer which constructor to use to createBean, typical representative classes areAutowiredAnnotationBeanPostProcessor.
  • beanAfter being created by reflection, the post-processor is called againMergedBeanDefinitionPostProcessor.postProcessMargedBeanDefinition()Method, this step is performed after the processor in order to find the added@Autowired,@ResourceWait for attributes and methods of annotations, and then cache the annotation information toinjectionMetadataCacheProperty to facilitate the followingbeanInitialization phase (attribute assignment phase), according to@AutowiredAnnotation implementation of automatic assembly. This step represents the post-processorAutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor is used to deal with the Spring annotations and parts of the JSR – 330 annotations, such as: the @autowired, @ Value, @ Inject. CommonAnnotationBeanPostProcessor is used to deal with the JSR – 250 annotations, such as @ Resource, @ PostConstruct, @ PreDestroy.

  • The next part will be semi-finishedbeanBecause it hasn’t been given yetbeanAttribute assignment, not completed autowiring, so called semi-finished) intoDefaultSingletonBeanRegistryOf the classsingletonFactoriesAttributes of,singletonFactoriesA property is aMap.keyforbeanNameAnd has a value ofObjectFactoryType (actually just onelambdaExpression) when calledObjectFactorythegetObject()Method is executedlambdaThe method body of the expression, in the current scenario,lambdaThe expression is coded as follows, which is essentially executed onceBeanThe rear processor. The purpose of this step is to solvebeanHow to solve the problem of cyclic dependence will be analyzed in the future.
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
	Object exposedObject = bean;
	if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
				SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                // Call the postprocessed method to get the bean object exposed earlier (semi-finished)exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); }}}return exposedObject;
}
Copy the code
  • And then it will execute topopulateBean()Method, in which it is executed twice moreBeanPost-processor, the first time the post-processor is executed is for judgmentBeanWhether to continue to populate the properties, ifInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()Method returnfalse, indicates that no attribute filling is carried out.beanIt’s not going to happen@AutowiredAnd the automatic assembly process,populateBean()The method will just end. If the returntrue, the following property population is performed, that is, the second post-processor is performed,InstantiationAwareBeanPostProcessor.postProcessPropertyValue()Method, the main character of this step isAutowiredAnnotationBeanPostProcessorandCommonAnnotationBeanPostBeanPostProcessorThey will be cached according to the precedinginjectionMetadataCacheAnnotated information in the
  • The execution of thepopulateBean()Method, and then execute backinitializeBean()Method, that is, enter the initialization phase. ininitializeBean()Method is executed firstinvokeAwareMethods()Method, that is, executionAwareInterface methods, such as:BeanNameAware,BeanClassLoaderAware,BeanFactoryAware. And then execute everything againBeanRear-processorBeanPostProcessor.postProcessBeforeInitialization()Methods. Then performinvokeInitMethods()Methods,invokeInitMethods()Method is executedInitializingBeantheafterPropertiesSet()Methods, and definitionsbeanIs custominitMethod()Methods. One last timebeanRear processor,BeanPostProcessor.postProcessAfterInitialization().
  • At this pointbeanThe instantiation and initialization of thebeanWill be returned if it is a singletonbeanAnd will eventually be stored inDefaultSingletonBeanRegistrythesingletonObjectsIn the.
6.8 finishRefresh ()
  • At this point,SpringThe startup of the container is almost completeBeanHas been instantiated and the autowiring is complete. performfinishRefresh()The method is for the containerrefresh()At the end, do something else, such as publishContextRefreshedEventEvent so when we want to in the containerrefreshWhen you’re done, perform some special logic, and you can pass a listenerContextRefreshedEventEvent to implement.SpringBuilt-in four and application contexts (ApplicationContextEvent) Related events:ContextRefreshedEvent,ContextStartedEvent,ContextStopedEvent,ContextClosedEvent.
protected void finishRefresh(a) {
    clearResourceCaches();
    initLifecycleProcessor();
    getLifecycleProcessor().onRefresh();
    / / release ContextRefreshedEvent
    publishEvent(new ContextRefreshedEvent(this));
    LiveBeansView.registerApplicationContext(this˛);
}
Copy the code
6.9 resetCommonCaches ()

Finally, the resetCommonCaches() method is executed in the finally block of the Refresh () method. Because the singleton bean’s metadata information was cached when the bean was created, and the singleton bean is not created after the container starts, the cached information is no longer useful, so it is cleared here to free up some memory.

protected void resetCommonCaches(a) {
    ReflectionUtils.clearCache();
    AnnotationUtils.clearCache();
    ResolvableType.clearCache();
    CachedIntrospectionResults.clearClassLoader(getClassLoader());
}
Copy the code

7. Bean life cycle

  • From the aboveSpringSource code analysis, it can be seen that during the startup process,beanIs the most complex, with a total of eight callsBeanPostPorcessor(As a matter of factbeanOver the life cycle of the9The ninth call to the post-processor occurs inbeanDestruction phase.)
  • In combination withSpringSource code, singletonbeanThe life cycle of can be summarized in the following figure

8. To summarize

  • This article introducesSpringThe startup process goes throughAnnotationConfigApplicationContextThe parametric construction method is analyzed in detailthis()Methods andrefresh()Methods. inthis()An initializer is initialized inBeanFactory, i.e.,DefaultListableBeanFactory; We then added seven built-in ones to the containerbean, includingConfigurationClassPostProcessor.
  • inrefresh()Methods, and focus on the analysisinvokeBeanFactoryPostProcessor()Methods andfinishBeanFactoryInitialization()Methods.
  • ininvokeBeanFactoryPostProcessor()Method, throughConfigurationClassPostProcessorClass scans out all handedSpringManage the class and willclassThe file is parsed into the correspondingBeanDefinition.
  • infinishBeanFactoryInitialization()Method completes the singleton of non-lazy loadingBeanThe main process of instantiation and initialization isgetBean()— >doGetBean()— >createBean()— >doCreateBean(). inbeanDuring the creation process, a total of8timeBeanPostProcessorIn the execution of these post-processors, the execution is completedAOPThe implementation of,beanAutomatic assembly, attribute assignment and other operations.
  • Finally, through a flow chart, summed upSpringThe singletonBeanLife cycle of.

Plan 9.

This article mainly introduces the Spring startup process, but there are some specific implementation details are not analyzed, so the following Spring source analysis plan is as follows:

  • ConfigurationClassPostProcessorClass how to scan packages and resolve configuration classes.
  • @ImportAnnotation and@EnableThe implementation principle of series annotations
  • JDKDynamic proxy andCGLIBThe agent
  • FactoryBeanUse and source code analysis
  • AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessorHow to achieve automatic assembly,SpringHow do I solve circular dependencies
  • AOPImplementation principle of
  • SpringBootSource code analysis

10. Performance monitoring tools are recommended

  • Finally, I recommend an open source performance monitoring toolPepper-Metrics

Address: github.com/zrbcool/pep… Making Pepper – Metrics is sitting opposite me two colleagues together with the development of open source components, main function is through comparing the lightweight way and the commonly used open source components (jedis/mybatis/motan/dubbo/servlet) integration, collect and calculate Metrics, It also supports output to logs and conversion to a variety of timing database compatible data formats, and the accompanying Grafana Dashboard is friendly to display. The principle of the project is fully documented, and all extensible architecture based on SPI design, convenient to develop new plug-ins. Otherwise a docker – compose based independent demo project can jumpstart a demo sample at https://github.com/zrbcool/pepper-metrics-demo. If you think it is useful, please give a star, welcome to participate in the development, thank you 🙂


Welcome to scan the qr code below, follow the wechat public number: rookie fei ya Fei read more source code, no longer for search engine programming