“This is the fifth day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

Step 3: AbstractAutowireCapableBeanFactory createBean

To review:

  • At this point, the beanClass object in MBD is still a String and does not support constructing an object directly.

So the first step is to find the corresponding class.

To find the class
Class<? > resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass ! = null && ! mbd.hasBeanClass() && mbd.getBeanClassName() ! = null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } protected Class<? > resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<? >... TypesToMatch) throws CannotLoadBeanClassException {try {/ / there is not any beanClass object, If (mbd.hasbeanClass ()) {return mbd.getBeanClass(); } if (System.getSecurityManager() ! = null) { return AccessController.doPrivileged((PrivilegedExceptionAction<Class<? >>) () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext()); } else { return doResolveBeanClass(mbd, typesToMatch); } } catch (PrivilegedActionException pae) { ClassNotFoundException ex = (ClassNotFoundException) pae.getException(); throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); } catch (ClassNotFoundException ex) { throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); } catch (LinkageError err) { throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err); }}Copy the code

This method is called here according to the flow above:

@Nullable private Class<? > doResolveBeanClass(RootBeanDefinition mbd, Class<? >... TypesToMatch) throws ClassNotFoundException {// Get the classloader // this may be the default, It may also be explicitly set before ClassLoader beanClassLoader = getBeanClassLoader(); ClassLoader dynamicLoader = beanClassLoader; boolean freshResolve = false; if (! ObjectUtils.isEmpty(typesToMatch)) { // When just doing type checks (i.e. not creating an actual instance yet), // use the specified temporary class loader (e.g. in a weaving scenario). ClassLoader tempClassLoader = getTempClassLoader(); if (tempClassLoader ! = null) { dynamicLoader = tempClassLoader; freshResolve = true; if (tempClassLoader instanceof DecoratingClassLoader) { DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader; for (Class<? > typeToMatch : typesToMatch) { dcl.excludeClass(typeToMatch.getName()); }}}} // get the className String className = mbd.getbeanclassname (); if (className ! = null) {/ / analytic expression Spring SPEL, can replace the name of the class Object evaluated = evaluateBeanDefinitionString (className, MBD); if (! ClassName. Equals (evaluated)) {// A dynamically resolved expression, supported as of 4.2... if (evaluated instanceof Class) { return (Class<? >) evaluated; } else if (evaluated instanceof String) { className = (String) evaluated; freshResolve = true; } else { throw new IllegalStateException("Invalid class name expression result: " + evaluated); Resolving against a temporary class loader if (resolresolver) {// When resolving against a temporary class loader, exit early in order // to avoid storing the resolved Class in the bean definition. if (dynamicLoader ! = null) { try { return dynamicLoader.loadClass(className); } catch (ClassNotFoundException ex) { if (logger.isTraceEnabled()) { logger.trace("Could not load class [" + className +  "] from " + dynamicLoader + ": " + ex); } } } return ClassUtils.forName(className, dynamicLoader); } } // Resolve regularly, caching the result in the BeanDefinition... return mbd.resolveBeanClass(beanClassLoader); }Copy the code
  • GetBeanClassLoader () :

    Thread.currentthread ().getContextClassLoader() Can’t get is ClassUtils. Class. GetClassLoader (), then gain is less than this. GetSystemClassLoader ().

Then, if it gets it, it assigns:

 mbdToUse = new RootBeanDefinition(mbd);
 mbdToUse.setBeanClass(resolvedClass);
Copy the code
Overriding methods

The @todo annotation is related to the @lookup annotation

 try {
    mbdToUse.prepareMethodOverrides();
 }
 catch (BeanDefinitionValidationException ex) {
    throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
          beanName, "Validation of method overrides failed", ex);
 }
Copy the code
Try to get beanPostProcessor to do the creation for us

Now that we have the beanClass name, we need to do some pre-processing.

BeanPostProcessor can proxiate the bean before initialization. BeanPostProcessor can proxiate the bean before initialization. BeanPostProcessor can proxiate the bean before initialization.

try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean ! = null) {// If the bean is obtained, the return bean is returned; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } // We can see what this is, The following two apply is the circulation beanPostProcessor protected Object resolveBeforeInstantiation (String beanName, RootBeanDefinition mbd) { Object bean = null; if (! Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. / / hasInstantiationAwareBeanPostProcessors () : / / in this step will determine whether have InstantiationAwareBeanPostProcessor cache, there will be at startup initialization BeanPostProcessorCache first, if you don't call it doesn't matter, this call will come to an initialization of the if (! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<? > targetType = determineTargetType(beanName, mbd); if (targetType ! = null) {// If a class is created successfully, it does not need to be initialized. // If a class is created successfully, it does not need to be initialized. // A key postProcessor here is an AOP proxy, Pay attention to the bean = applyBeanPostProcessorsBeforeInstantiation behind (targetType, beanName); if (bean ! If null is returned, the process will continue. If null is returned, the process will continue. It returns null bean = applyBeanPostProcessorsAfterInitialization (bean, beanName); }}} / / mark the pre-processing done didn't MBD beforeInstantiationResolved = (bean! = null); } return bean; }Copy the code
Create a bean

If there is no suitable BeanPostProcessor from the previous step, then you have to create your own:

try { Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); }}Copy the code

Here is another doCreateBean, remember that in Spring XXX usually does some extra processing, and doXXX is the most basic XXX, working locally:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {// Instantiate the bean. // Deduce constructor related BeanWrapper instanceWrapper = null; If (mbd.issingleton ()) {// It is possible to generate some factoryBeans in advance during Spring startup, So here will process the instanceWrapper = this. FactoryBeanInstanceCache. Remove (beanName); } if (instanceWrapper == null) {// The constructor is inferred here: InstanceWrapper = createBeanInstance(beanName, MBD, args); } / / here will pick up the bean from the above beanWrapper Object bean. = instanceWrapper getWrappedInstance (); Class<? > beanType = instanceWrapper.getWrappedClass(); if (beanType ! = NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. @autoWired synchronized (mbd.postProcessingLock) {if (! mbd.postProcessed) { try { 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 is related to loop dependencies, Regardless of Boolean earlySingletonExposure = (MBD isSingleton () && enclosing allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. // This property fills the Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); 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 ! = null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (! this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(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 " + "'getBeanNamesForType' 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
  • PopulateBean: Property population.

    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { if (mbd.hasPropertyValues()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // To support styles of field injection. //beanPostProcessor handles dependency injection (! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { if (! bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; PVS = (mbd.haspropertyValues ()? mbd.getPropertyValues() : null); int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs  = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } // beanPostProcessor, @autowired, @ the Resource are here for Boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors (); boolean needsDepCheck = (mbd.getDependencyCheck() ! = AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs ! = null) { applyPropertyValues(beanName, mbd, bw, pvs); }}Copy the code
  • Built-in Autowired:
int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs  = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; }Copy the code

What if there is no @autowired attribute?

  • Here you need to annotate @Bean(AutoWired = Autowired.BY_TYPE)(or byName) somewhere and declare the bean as @bean, And variables that are not labeled @autowired need to be given the corresponding set method so that they can be injected.

    However, this method has been marked deprecated.