With that said, let’s go back to the refresh method, and I reposted the code to see where we were. Yes, we just finished the obtainFreshBeanFactory method.

For the sake of space, I’m going to drastically cut down the parts that don’t need to be explained in detail, so you can just look at the comments in the code below.

@overridePublic void refresh throws BeansException, IllegalStateException {// Start or destroy the container before refresh. The mixed with synchronized (enclosing startupShutdownMonitor) {/ / preparation, record the container tag's start time, in the configuration file is "started" state, the processing placeholder prepareRefresh; // The configuration file is parsed into Bean definitions and registered with the BeanFactory. // The configuration file is not initialized yet. / / register is the information is stored in the registry (at the end of the day is a core beanName - > beanDefinition map) ConfigurableListableBeanFactory the beanFactory = obtainFreshBeanFactory; PrepareBeanFactory (BeanFactory); prepareBeanFactory(BeanFactory); BeanFactory(BeanFactory); Spring calls the postProcessBeanFactory method after the container is initialized. Spring calls the postProcessBeanFactory method after the container is initialized. // This is the extension point provided to subclasses. At this point, all the beans have been loaded and registered. PostProcessBeanFactory (beanFactory); postProcessBeanFactory(beanFactory); / / call spring BeanFactoryPostProcessor postProcessBeanFactory of each implementation class (factory) callback methods invokeBeanFactoryPostProcessors (the beanFactory); BeanPostProcessor (factoryPostProcessor) ¶ PostProcessBeforeInitialization and postProcessAfterInitialization / / two methods in the Bean initialization respectively before and after the initialization are implemented. Here is just registered, will see the callback after the timing of these two methods registerBeanPostProcessors (the beanFactory); // Initialize the MessageSource of the current ApplicationContext. / / initialize the current ApplicationContext event broadcast, here also not launched initApplicationEventMulticaster; // Specific subclasses can initialize special beans here (before initializing Singleton beans) onRefresh; // Register event listeners that implement the ApplicationListener interface. These are not important listeners either. / / focus, focus, focus on / / initialize all singleton beans / / (except for the lazy - init) finishBeanFactoryInitialization (the beanFactory); // Finally, the event is broadcast, ApplicationContext is initialized, and finishRefresh is not expanded; }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. In case some beans will always use the resource destroyBeans; // Reset 'active' flag.cancelRefresh(ex); // throw ex; }finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore... resetCommonCaches; }}}Copy the code

Prepare the Bean container: prepareBeanFactory

As mentioned earlier, Spring “manually” registers special beans after registering all the beans we configured in XML.

Here’s a quick look at the prepareBeanFactory(Factory) method:

/*** Configure the factory's standard context characteristics,* such as the context's ClassLoader and post-processors.* @param beanFactory the BeanFactory to configure*/protected void prepareBeanFactory(ConfigurableListableBeanFactory BeanFactory) {// Set the beanFactory class loader, we know that beanFactory needs to load classes, so we need the class loader, / / here is set to the load current ApplicationContext class class loader. The beanFactory setBeanClassLoader getClassLoader (); / / set BeanExpressionResolverbeanFactory. SetBeanExpressionResolver (new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader)); //beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment)); // Add a BeanPostProcessor, which is relatively simple: // When the beans are initialized, this processor is responsible for the callback. As we will implement in order to obtain ApplicationContext ApplicationContextAware / / note: It not only callback ApplicationContextAware, but also callback EnvironmentAware, ResourceLoaderAware, etc. Was clear to see the source code. The beanFactory addBeanPostProcessor (new ApplicationContextAwareProcessor (this)); // The following lines mean that if a bean depends on the implementation classes of any of the following interfaces and ignores them during autoloassembly, Spring will handle these dependencies in other ways. beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); /*** The following lines assign values to specific beans. If any beans depend on any of the following, the corresponding values will be injected. Here to explain the first line * ApplicationContext also inherited the ResourceLoader, ApplicationEventPublisher, MessageSource * for this a few dependencies, so can be assigned to this, Note that this is an ApplicationContext* so we don't see assignment to MessageSource. That's because the MessageSource is registered as a common bean * / the beanFactory registerResolvableDependency (the beanFactory. Class, the beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // If the bean is a subclass of ApplicationListener after instantiation, add it to the listener list. Register event listeners the beanFactory. AddBeanPostProcessor (new ApplicationListenerDetector (this)); // There is a special bean involved, called loadTimeWeaver, which is not our focus, so ignore it. LTW is an AspectJ concept that refers to weaving at run time, which unlike Spring AOP, / / interested readers refer me to write another article about AspectJ https://www.javadoop.com/post/aspectjif (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)); }/*** From the following lines of code, we can see that Spring is "smart" because it registers useful beans by default. * We can also choose to override *// if the bean "environment" is not defined, Then Spring will "manually" register an if (! beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment); }// If the "systemProperties" bean is not defined, Spring will "manually" register an if (! beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment.getSystemProperties); }// If the "systemEnvironment" bean is not defined, Spring will "manually" register an if (! beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment.getSystemEnvironment); }}Copy the code

In the above code, Spring handles some special beans, so if you can’t digest them for a while, it doesn’t matter.

Initialize all Singleton Beans

We, of course, is the focus of the finishBeanFactoryInitialization (the beanFactory); This giant is responsible for initializing all Singleton Beans.

Note that I use initialization or pre-initialization to represent this phase in the following descriptions, and Spring completes instantiation of all Singleton Beans at this stage.

To summarize, so far, we should say that the BeanFactory has been created, And all beans that implement the BeanFactoryPostProcessor interface have been initialized and the postProcessBeanFactory(Factory) method in them has been callback executed. And Spring has already “manually” registered some special beans, such as’ environment ‘, ‘systemProperties’, etc.

All that remains is to initialize the Singleton Beans. We know that they are singleton. If lazy loading is not set, Spring will initialize all the Singleton beans next.

// AbstractApplicationContext.java 834

/ / initializes the rest of the singleton beansprotected void finishBeanFactoryInitialization (ConfigurableListableBeanFactory the beanFactory) {/ / First, initialize the Bean named conversionService. In the spirit of sending the beans to the west, I have briefly introduced the ConversionService in the appendix, because it is too useful. // Notice that the initialized action is wrapped in beanFactory.getBean(...). Without going into the details, If (beanfactory.containsbean (CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.istypematch (CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); }// Register a default embedded value resolver if no bean post-processor// (such as a PropertyPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values.if (! beanFactory.hasEmbeddedValueResolver) {beanFactory.addEmbeddedValueResolver(new StringValueResolver {@Overridepublic String resolveStringValue(String strVal) {return getEnvironment.resolvePlaceholders(strVal); }}); }// Initialize the Bean of type LoadTimeWeaverAware // as mentioned earlier, this is AspectJ related, Feel free to skip it String weaverAwareNames = the beanFactory. GetBeanNamesForType (LoadTimeWeaverAware. Class, false, false); for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName); }// Stop using the temporary ClassLoader for type matching.beanFactory.setTempClassLoader; // There is no other purpose, because at this point Spring will already be pre-initializing the Singleton beans, and you don't want to see bean definition resolution, loading, and registration at this point. beanFactory.freezeConfiguration; / / initialize the beanFactory. PreInstantiateSingletons; }Copy the code

From above to see the last line, we went back to DefaultListableBeanFactory this class, this class everyone should not unfamiliar.

preInstantiateSingletons

// DefaultListableBeanFactory 728

@Overridepublic void preInstantiateSingletons throws BeansException {if (this.logger.isDebugEnabled) {this.logger.debug("Pre-instantiating singletons in " + this); }// this.beandefinitionNames saves all beanNamesList<String> beanNames = new ArrayList<String>(this.beandefinitionNames); // Trigger the initialization of all non-lazy-loaded Singleton beans for (String beanName: < Bean id="" class="" parent="" /> < Bean id="" class="" parent="" /> I explained in appendix "Bean inheritance", don't understand, please to see the appendix RootBeanDefinition bd = getMergedLocalBeanDefinition (beanName); // Non-abstract, non-lazy-loaded singletons. If 'abstract = true' is configured, there is no need to initialize if (! bd.isAbstract && bd.isSingleton && ! Bd.islazyinit) {// If (isFactoryBean(beanName)) {// If (isFactoryBean(beanName)) { Prefix beanName with an ampersand. Call getBean, getBean, final FactoryBean<? > factory = (FactoryBean<? >) getBean(FACTORY_BEAN_PREFIX + beanName); Boolean isEagerInit; // Check whether the current FactoryBean is an implementation of SmartFactoryBean. if (System.getSecurityManager ! = && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean> {@Overridepublic Boolean run {return ((SmartFactoryBean<? >) factory).isEagerInit; }}, getAccessControlContext); }else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<? >) factory).isEagerInit); }if (isEagerInit) {getBean(beanName); }}else {// For normal beans, just call getBean(beanName) method to initialize getBean(beanName); }}} / / here that all the lazy loading of singleton beans has completed initialization / / if we define the bean is realized SmartInitializingSingleton interface, so get back here, Ignore for (String beanName: beanNames) {Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) {final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager ! = ) {AccessController.doPrivileged(new PrivilegedAction<Object> {@Overridepublic Object run {smartSingleton.afterSingletonsInstantiated; return ; }}, getAccessControlContext); }else {smartSingleton.afterSingletonsInstantiated; }}}}Copy the code

Next, we go to the getBean(beanName) method, which we often use to get a Bean from the BeanFactory, and the initialization process is encapsulated in this method.

getBean

Before moving on, the reader should have some knowledge of FactoryBeans. If not, please refer to the appendix section to learn about FactoryBeans.

// AbstractBeanFactory 196

@Overridepublic Object getBean(String name) throws BeansException {return doGetBean(name, , , false); }// We are looking at the process of initializing the Bean, but we usually use the getBean method to get the Bean from the container. Protected <T> T doGetBean(Final String name, final Class<T> requiredType, final String name, final Class<T> requiredType, Final Object[] args, Boolean typeCheckOnly)throws BeansException {// Obtain a "proper" beanName. One is the FactoryBean(preceded by an ampersand), and the other is the alias problem. Since this method is getBean, you can pass in an alias for the Bean. Final String beanName = transformedBeanName(name); // Notice that following this, this is the return value Object bean; Object sharedInstance = getSingleton(beanName); // Args is not important. If args is not empty, it means that the caller does not want to fetch the Bean. Instead, it creates Beanif (sharedInstance! = && args == ) {if (logger.isDebugEnabled) {if (isSingletonCurrentlyInCreation(beanName)) {logger.debug("..." ); }else {logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); }}// Use the following method: If it is a normal Bean, return sharedInstance. If it is a FactoryBean, return the instance it created. Bean = getObjectForBeanInstance(sharedInstance, name, beanName,); } else {the if (isPrototypeCurrentlyInCreation (beanName)) {/ / create the prototype of this beanName type of bean, then throw exceptions, / / is often because in a circular reference throw new BeanCurrentlyInCreationException (beanName); }// Check if BeanFactory parentBeanFactory = getParentBeanFactory; if (parentBeanFactory ! = &&! ContainsBeanDefinition (beanName) {// If the container does not have a BeanDefinition, check if the parent container has String nameToLookup = originalBeanName(name); if (args ! =) {/ / return the parent container of query results in return (T) parentBeanFactory. GetBean (nameToLookup, args); }else {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType); }}if (! TypeCheckOnly) {// typeCheckOnly is false and puts the current beanName into an alreadyCreated Set. markBeanAsCreated(beanName); }/** To summarize a bit: * At this point, we are ready to create the Bean, which for singleton's Bean has not been created in the container; For prototype beans, the original idea is to create a new Bean. */try {final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Initialize all dependent beans first, which is easy to understand. String dependsOn = mbd.getson; String dependsOn = mbd.getson; if (dependsOn ! = ) {for (String dep : DependsOn) {// Check if there is a cyclic dependency. (dependsOn) {// Check if there is a cyclic dependency. Readers to think about it, you will know the if (isDependent (beanName, dep)) {throw new BeanCreationException (MBD) getResourceDescription, beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); RegisterDependentBean (dep, beanName); // initialize the dependent getBean(dep); }}// If it is singleton scope, If (mbd.isSingleton) {sharedInstance = getSingleton(beanName, New ObjectFactory<Object> {@overridePublic Object getObject throws BeansException {try { Return createBean(beanName, MBD, args); }catch (BeansException ex) {destroySingleton(beanName); throw ex; }}}); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }// If prototype scope, Else if (mbd.isPrototype) {// It's a prototype -> create a new instance.Object prototypeInstance =; try {beforePrototypeCreation(beanName); BeanprototypeInstance = 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 == ) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); }try {Object scopedInstance = scope.get(beanName, new ObjectFactory<Object> {@Overridepublic Object getObject throws BeansException {beforePrototypeCreation(beanName); // Create Beanreturn 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); throw ex; }}// If (requiredType!) {if (requiredType! = && bean ! = &&! requiredType.isInstance(bean)) {try {return getTypeConverter.convertIfNecessary(bean, requiredType); }catch (TypeMismatchException ex) {if (logger.isDebugEnabled) {logger.debug("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex); }throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass); }}return (T) bean; }Copy the code

As you might have guessed, the next step is to analyze the createBean method:

protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException;
Copy the code

The third parameter, the args array, represents the parameters needed to create the instance, either for the constructor or for the factory Bean, but note that in our initialization phase, args is.

This time we want to a new kind of AbstractAutowireCapableBeanFactory, see the name of the class, AutowireCapable? The class name tells you something.

The @AutoWired annotation is used to inject attribute values for the following scenarios:

public class MessageServiceImpl implements MessageService {@Autowiredprivate UserService userService; public String getMessage {return userService.getMessage; }} <bean id="messageService" class="com.javadoop.example.MessageServiceImpl" />Copy the code

This is a hybrid configuration of XML and annotations, and Spring handles this.

All right, that’s all the reader needs to know. Move on.

// AbstractAutowireCapableBeanFactory 447

/*** Central method of this class: creates a bean instance,* populates the bean instance, applies post-processors, etc.* @see #doCreateBean*/@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {if (logger.isDebugEnabled) {logger.debug("Creating instance of bean '" + beanName + "'"); }RootBeanDefinition mbdToUse = mbd; // Make sure the Class in BeanDefinition is loaded Class<? > resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass ! = &&! mbd.hasBeanClass && mbd.getBeanClassName ! = ) {mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); }// Prepare method overwrite, here again involves a concept: MethodOverrides, which comes from <lookup-method />// and < appet-method /> in the bean definition. If you're interested, go back to bean parsing to see how these two tags are resolved. / / I also in the appendix to this two label related knowledge are introduced, the reader can move to go and see the try {mbdToUse. PrepareMethodOverrides; }catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription,beanName, "Validation of method overrides failed", ex); } the try {/ / let InstantiationAwareBeanPostProcessor at this stage the opportunity to return to the agent, / / in the Spring AOP source code analysis with explanation in the article, Here to skip the first Object bean = resolveBeforeInstantiation (beanName mbdToUse); if (bean ! = ) {return bean; }}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription, beanName,"BeanPostProcessor before instantiation of bean failed", ex); BeanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isDebugEnabled) {logger.debug("Finished creating instance of bean '" + beanName + "'"); }return beanInstance; }Copy the code

Create a Bean

Let’s move on to the doCreateBean method:

/*** Actually create the specified bean. Pre-creation processing has already happened* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.* <p>Differentiates between default bean instantiation, use of a* factory method, and autowiring a constructor.* @param beanName the name of the bean* @param mbd the merged bean definition for the bean*  @param args explicit arguments to use for constructor or factory method invocation* @return a new instance of the bean*  @throws BeanCreationException if the bean could not be created* @see #instantiateBean* @see #instantiateUsingFactoryMethod* @see #autowireConstructor*/protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = ; if (mbd.isSingleton) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); }if (instanceWrapper ==) {// This is not a FactoryBean. InstanceWrapper = createBeanInstance(beanName, MBD, args); }// This is an instance of the class we defined in the Bean. In many places I describe it as "Bean instance". Final Object Bean = (instanceWrapper! =? instanceWrapper.getWrappedInstance : ); / / type Class <? > beanType = (instanceWrapper ! =? instanceWrapper.getWrappedClass : ); mbd.resolvedTargetType = beanType; / / Suggestions to skip, involving interface: MergedBeanDefinitionPostProcessorsynchronized (MBD) postProcessingLock) {if (! MBD. PostProcessed) {try {/ / MergedBeanDefinitionPostProcessor, said this I really don't, just skip it, Seldom used applyMergedBeanDefinitionPostProcessors (MBD, beanType, beanName); }catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription, beanName,"Post-processing of merged bean definition failed", ex); }mbd.postProcessed = true; }}// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces Like BeanFactoryAware.// This code is designed to solve the problem of loop dependency. I then parsing problem of circular dependencies this Boolean earlySingletonExposure = (MBD) isSingleton && enclosing allowCircularReferences &&isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) {if (logger.isDebugEnabled) {logger.debug("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references"); }addSingletonFactory(beanName, new ObjectFactory<Object> {@Overridepublic Object getObject throws BeansException {return getEarlyBeanReference(beanName, mbd, bean); }}); }// Initialize the bean instance.Object exposedObject = bean; Try {// This step is also critical. This step is responsible for the property assembly, because the previous instance was instantiated without setting the value. Here is the value populateBean(beanName, MBD, instanceWrapper); if (exposedObject ! =) {// Remember init-method? And the InitializingBean interface? And the BeanPostProcessor interface? ExposedObject = initializeBean(beanName, exposedObject, MBD); }}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName)) {throw (BeanCreationException) ex; }else {throw new BeanCreationException(mbd.getResourceDescription, beanName, "Initialization of bean failed", ex); }}if (earlySingletonExposure) {//Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference ! = ) {if (exposedObject == bean) {exposedObject = earlySingletonReference; }else if (! this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length); for (String dependentBean : dependentBeans) {if (! removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean); }}if (! actualDependentBeans.isEmpty) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw  version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This  is often the result of over-eager type matching - consider using " +"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); }}}}// Register bean as disposable.try {registerDisposableBeanIfNecessary(beanName, bean, mbd); }catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription, beanName, "Invalid destruction signature", ex); }return exposedObject; }Copy the code

At this point, we have analyzed the doCreateBean method, and in general, we have covered the entire initialization process.

Let’s pick out three details from doCreateBean. There is the createBeanInstance method for creating Bean instances, the populateBean method for dependency injection, and the callback method initializeBean.

Note that the next three methods are extremely complicated, and I’ll just touch on a few of them. If you’re interested, you can read them yourself. If you don’t understand them, you can write your own code to debug them.

Creating a Bean instance

Let’s look at the createBeanInstance method first. It should be noted that this method, if analyzed at every branch, would be extremely complicated and lengthy, so let’s focus on it. The purpose of this method is to instantiate the class we specify.

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {// Make sure this classClass<? > beanClass = resolveBeanClass(mbd, beanName); If (beanClass! = &&! Modifier.isPublic(beanClass.getModifiers) && ! mbd.isNonPublicAccessAllowed) {throw new BeanCreationException(mbd.getResourceDescription, beanName,"Bean class isn't public, and non-public access not allowed: " + beanClass.getName); }if (mbd.getFactoryMethodName ! =) {/ / the factory method instantiation, not familiar with the concept of the reader see appendix, note that not FactoryBeanreturn instantiateUsingFactoryMethod (beanName, MBD, args); }// If the prototype bean is not created for the first time, such as the second time. // In this case, we can know from the first creation whether to use the constructor with no arguments or dependency injection. boolean autowireNecessary = false; if (args == ) {synchronized (mbd.constructorArgumentLock) {if (mbd.resolvedConstructorOrFactoryMethod ! = ) {resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; Error (resolved) {error (resolved) {error (resolved) {return autowireConstructor(beanName, MBD,,); }else {return instantiateBean(beanName, MBD); }}// Check whether the parameterized Constructor<? > ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors ! = ||mbd.getResolvedAutowireMode == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues || ! Objectutils.isempty (args)) {return autowireConstructor(beanName, MBD, ctors, args); } return instantiateBean(beanName, MBD); }Copy the code

Take a simple example of a no-parameter constructor:

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {try {Object beanInstance; final BeanFactory parent = this; if (System.getSecurityManager ! = ) {beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object> {@Overridepublic Object run {return getInstantiationStrategy.instantiate(mbd, beanName, parent); }}, getAccessControlContext); } else {/ / instantiate beanInstance = getInstantiationStrategy. Instantiate (MBD, beanName, parent); }// return BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; }catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription, beanName, "Instantiation of bean failed", ex); }}Copy the code

As we can see, the key is:

beanInstance = getInstantiationStrategy.instantiate(mbd, beanName, parent);
Copy the code

Here’s the actual instantiation. Let’s go inside:

// SimpleInstantiationStrategy 59

@instantiate public Object instantiate(RootBeanDefinition BD, String beanName, BeanFactory Owner) { So instantiate it using Java reflection, Otherwise, use additional, overwrite / / method Please see appendix "methods" of the lookup method and replaced - method to introduce the if (bd) getMethodOverrides) isEmpty) {Constructor <? > constructorToUse; synchronized (bd.constructorArgumentLock) {constructorToUse = (Constructor<? >) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == ) {final Class<? > clazz = bd.getBeanClass; if (clazz.isInterface) {throw new BeanInstantiationException(clazz, "Specified class is an interface"); }try {if (System.getSecurityManager ! = ) {constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<? >> {@Overridepublic Constructor<? > run throws Exception {return clazz.getDeclaredConstructor((Class[]) ); }}); }else {constructorToUse = clazz.getDeclaredConstructor((Class[]) ); }bd.resolvedConstructorOrFactoryMethod = constructorToUse; }catch (Throwable ex) {throw new BeanInstantiationException(clazz, "No default constructor found", ex); }}} / / using a constructor to instantiate the return BeanUtils. InstantiateClass (constructorToUse); }else {// there is a method overridden, using CGLIB to complete the instantiation, need to rely on CGLIB generation of subclasses, not expanded here. / / tips: because, if does not use additional conditions exist that override the JDK and does not provide corresponding instantiation support return instantiateWithMethodInjection (bd, beanName, owner); }}Copy the code

At this point, we’re done instantiating. We started talking about how to do property injection.

Bean property injection

After reading the createBeanInstance (…). Method, let’s look at populateBean(…) Method, which is responsible for setting property values and handling dependencies.

// AbstractAutowireCapableBeanFactory 1203

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {// All properties of the bean instance are there PropertyValues PVS = mbd.getPropertyValues; if (bw == ) {if (! pvs.isEmpty) {throw new BeanCreationException(mbd.getResourceDescription, beanName, "Cannot apply property values to instance"); }else {// Skip property population phase for instance.return; }} / / to this step, bean instantiation finish (through the factory method or constructor), but have not yet begun to attribute set value, / / InstantiationAwareBeanPostProcessor implementation class can be here to state change of bean, / / I didn't find a practical use, so we'll ignore the Boolean continueWithPropertyPopulation = true; if (! mbd.isSynthetic && hasInstantiationAwareBeanPostProcessors) {for (BeanPostProcessor bp : getBeanPostProcessors) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // If false is returned, no further attribute setting is required and no further BeanPostProcessor processing is required. ibp.postProcessAfterInstantiation(bw.getWrappedInstance, beanName)) {continueWithPropertyPopulation = false; break; }}}}if (! continueWithPropertyPopulation) {return; }if (mbd.getResolvedAutowireMode == RootBeanDefinition.AUTOWIRE_BY_NAME ||mbd.getResolvedAutowireMode == RootBeanDefinition.AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Find all attribute values by name. If it is a bean dependency, initialize the dependent bean first. Record dependencies if (MBD) getResolvedAutowireMode = = RootBeanDefinition) AUTOWIRE_BY_NAME) {autowireByName (beanName, MBD, bw, newPvs); }// Assemble by type. Complicated if (MBD) getResolvedAutowireMode = = RootBeanDefinition) AUTOWIRE_BY_TYPE) {autowireByType (beanName, MBD, bw, newPvs); }pvs = newPvs; }boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors; boolean needsDepCheck = (mbd.getDependencyCheck ! = RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) {PropertyDescriptor filteredPds = filterPropertyDescriptorsForDependencyCheck(bw,  mbd.allowCaching); if (hasInstAwareBpps) {for (BeanPostProcessor bp : getBeanPostProcessors) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // There is a very useful BeanPostProcessor in here: AutowiredAnnotationBeanPostProcessor / / dependence on using @autowired, @ Value annotation to set Value, the content is very rich, but this article said, Readers interested in PVS = ibp. Please make your own research postProcessPropertyValues (PVS, filteredPds, bw getWrappedInstance, beanName); if (pvs == ) {return; }}}}if (needsDepCheck) {checkDependencies(beanName, mbd, filteredPds, pvs); ApplyPropertyValues (beanName, MBD, bw, PVS); }Copy the code

initializeBean

Once property injection is complete, this step is all about handling the various callbacks, which is relatively simple.

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {if (System.getSecurityManager ! = ) {AccessController.doPrivileged(new PrivilegedAction<Object> {@Overridepublic Object run {invokeAwareMethods(beanName, bean); return ; }}, getAccessControlContext); }else {// If the bean implements the BeanNameAware, BeanClassLoaderAware, or BeanFactoryAware interface, call back invokeAwareMethods(beanName, bean); }Object wrappedBean = bean; if (mbd == || ! MBD. IsSynthetic) {/ / BeanPostProcessor postProcessBeforeInitialization callback wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); }try {// process init-method defined in the bean, // or if the bean implements the InitializingBean interface, Call the afterPropertiesSet method invokeInitMethods(beanName, wrappedBean, MBD); }catch (Throwable ex) {throw new BeanCreationException((mbd ! =? mbd.getResourceDescription : ),beanName, "Invocation of init method failed", ex); }if (mbd == || ! MBD. IsSynthetic) {/ / BeanPostProcessor postProcessAfterInitialization callback wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }return wrappedBean; }Copy the code

Do you notice that BeanPostProcessor’s two callbacks happen on this side, but init-method is handled in the middle?