Previous portal:

  1. Pre-launch process for Spring source analysis
  2. BeanFactory Architecture for Spring source analysis
  3. Spring source analysis of BeanFactoryPostProcessor call process in detail

Content of this article:

  1. In IOC, how can a bean be created with defiance?
  2. What is the role of each BeanPostProcessor in this process, and when is it called?

Without further ado, let’s get to the point. Picture above!

Below is a general flow chart of the bean creation process. This article will analyze the source code step by step in the sequence shown in the figure

The original vector diagram address: www.processon.com/view/link/5…

As we know, there are a number of BeanPostProcessors registered in the early part of Spring IOC that will be used during Bean creation, as listed below

  • When AutowiredAnnotationBeanPostProcessor: in the new AnnotatedBeanDefinitionReader registration

  • When CommonAnnotationBeanPostProcessor: in the new AnnotatedBeanDefinitionReader registration

  • ApplicationContextAwareProcessor: when prepareBeanFactory register

  • ApplicationListenerDetector: when prepareBeanFactory register

  • ImportAwareBeanPostProcessor: in the configuration class call postProcessBeanFactory registered post processor

  • BeanPostProcessorChecker: when registerBeanPostProcessors register

That’s all the BeanPostProcessors built into Spring

Again, let’s start our analysis with the original entry refresh

public void refresh(a){
  / /... Omit the preceding part
  // Instantiate the remaining singleton beans
  finishBeanFactoryInitialization(beanFactory);
}
Copy the code

finishBeanFactoryInitialization

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory){
  // Load all non-lazy-loaded beans into the container
	beanFactory.preInstantiateSingletons();
}
Copy the code

Loop through all the BeanDefinitions we registered, one by one calling getBean to register with the container

public void preInstantiateSingletons(a){
  // Loop through all beanDefinitions
  for (String beanName : beanNames) {
    // Convert beanDefinition to RootBeanDefinition
    RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    // Is not abstract and is a singleton and is not lazily loaded
    if(! bd.isAbstract() && bd.isSingleton() && ! bd.isLazyInit()) {// Whether it is a factory bean
      if (isFactoryBean(beanName)) {
        // Since the bean is retrieved starting with &, a factory bean is returned and the getObject method is not called
        Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
        if (bean instanceof FactoryBean) {
          // Determine whether to initialize the bean immediatelyFactoryBean<? > factory = (FactoryBean<? >) bean;boolean isEagerInit = (factory instanceofSmartFactoryBean && ((SmartFactoryBean<? >) factory).isEagerInit());if (isEagerInit) {
            // Get it again as an &, which calls the FactoryBean getObject() methodgetBean(beanName); }}}else {
        // Instead of a FactoryBean, use getBean to initialize it directlygetBean(beanName); }}}}Copy the code

Next comes the usual Spring action of calling the doGetBean starting with do

public Object getBean(String name) throws BeansException {
  return doGetBean(name, null.null.false);
}
Copy the code

Here is the logic for getting a singleton bean in doGetBean

// Convert beanName to remove it if it begins with & and to get an alias if it has one
String beanName = transformedBeanName(name);
// Try to fetch the bean from the level 3 cache
Object sharedInstance = getSingleton(beanName);
// Whether the bean was retrieved from the cache
if(sharedInstance ! =null && args == null) {
  Call getObject() of the factory class if it is a factory class and the name does not begin with &
  // Otherwise return the original object
  bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
Copy the code

getSingleton

public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
}
Copy the code
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// From the singleton cache pool
		Object singletonObject = this.singletonObjects.get(beanName);
		// Check whether the bean is being created
    // If bean 2 is being created, there are two scenarios: 1. Multiple threads are creating bean 2. Cyclic dependency occurs
    // If there are multiple threads, the synchronization lock is blocked here
    // The problem of loop dependency is more complex and will be examined in detail in the next chapter
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				// From the early object cache pool
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					// Get the singleton factory from the level 3 cacheObjectFactory<? > singletonFactory =this.singletonFactories.get(beanName);
					if(singletonFactory ! =null) {
						// Call the callback method to get the early bean
						singletonObject = singletonFactory.getObject();
						// Place the early objects in the secondary cache and remove the tertiary cache
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName); }}}}return singletonObject;
	}
Copy the code

getObjectForBeanInstance

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
		// Determine if name begins with &, and return the FactoryBean directly
    /*public static boolean isFactoryDereference(@Nullable String name) { return (name ! = null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)); } * /
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}
		// Not the factory bean returns the original object directly
		if(! (beanInstanceinstanceof FactoryBean)) {
			return beanInstance;
		}
		// Try to fetch from the cache to ensure that the same bean is fetched from the factory bean multiple times
		object = getCachedObjectForFactoryBean(beanName);
		if (object == null) { FactoryBean<? > factory = (FactoryBean<? >) beanInstance;booleansynthetic = (mbd ! =null && mbd.isSynthetic());
      // Get the object from the FactoryBeanobject = getObjectFromFactoryBean(factory, beanName, ! synthetic); }return object;
	}
Copy the code

Code snippets of getObjectFromFactoryBean

protected Object getObjectFromFactoryBean(FactoryBean<? > factory, String beanName,boolean shouldPostProcess){
  // Get the bean, call factoryBean getObject()
	object = doGetObjectFromFactoryBean(factory, beanName);
}
Copy the code
private Object doGetObjectFromFactoryBean(FactoryBean
        factory, String beanName){
  object = factory.getObject();
}
Copy the code

Now that’s the logic for getting the bean from the cache and processing the FactoryBean, let’s look at the actual bean creation process

Here is the logic to follow up the doGetBean above that did not get the bean from the cache

// Create a DependsOn bean if it is marked by @dependson
String[] dependsOn = mbd.getDependsOn();
if(dependsOn ! =null) {
  for(String dep : dependsOn) { registerDependentBean(dep, beanName); getBean(dep); }}/ / the singleton beans
if (mbd.isSingleton()) {
  // Start creating the bean
  sharedInstance = getSingleton(beanName, () -> {
    // Actually create the bean
    return createBean(beanName, mbd, args);
  });
  Call getObject() of the factory class if it is a factory class and the name does not begin with &
  // Otherwise return the original object
  bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
Copy the code

GetSingleton, which is an overloaded method and is not the same as getting a bean from the cache

public Object getSingleton(String beanName, ObjectFactory
        singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		// The bean is locked when it is created. Note that the synchronization object for this lock is the same as the synchronization object for the lock when it is fetched from the cache
		synchronized (this.singletonObjects) {
			// Get it from the cache again
			Thread 1 is creating instance A. Thread 2 is trying to acquire instance A. thread 2 is blocked by synchronization lock
			// 2. Thread 1 is created, thread 2 enters the synchronized code block, and returns directly from the cache
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				// The tag is being created
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				try {
					// Call the callback function to get the bean
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				finally {
					// Clear the state
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					// Add the created bean to the singleton cache pool and remove the secondary and tertiary cachesaddSingleton(beanName, singletonObject); }}returnsingletonObject; }}Copy the code

CreateBean, finally start creating bean

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
  // The bean post-handler is called the first time before the bean is instantiated
  // There is no implementation in Spring's built-in back processor
  // A custom post-processor can be used here to abort the bean creation process
  Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
  if(bean ! =null) {
    // If a custom post-processor returns a bean, the bean creation process is interrupted
    return bean;
  }
  // Create the bean
	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}
Copy the code
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
  The second call to the bean post-processor is used to get the bean's parameter constructor
	instanceWrapper = createBeanInstance(beanName, mbd, args);
  // Process the beanDefinition metadata information for the third time
  applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  // Whether to allow exposure of early objects
  boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                                    isSingletonCurrentlyInCreation(beanName));
  // The fourth time to get the early object
  // Put the callback method that gets the earlier object into the level 3 cache
  addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  ByName byType @resource @value @AutoWired @inject
	populateBean(beanName, mbd, instanceWrapper);
  // For the seventh and eighth times, initialize
	exposedObject = initializeBean(beanName, exposedObject, mbd);
  // Check whether the bean has a destruction method for the ninth time. If so, register the bean in the destruction collection for use when the container is closed
	registerDisposableBeanIfNecessary(beanName, bean, mbd);
  // Returns the created bean
  return exposedObject;
}
Copy the code

You think this is the end of it?

So let’s take a look at what the back processor is doing here, okay

Since the first call didn’t do anything, we start with the second call

createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
  / / get beanClassClass<? > beanClass = resolveBeanClass(mbd, beanName);/ / using AutowiredAnnotationBeanPostProcessor constructor inference, find all have constructor refsConstructor<? >[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if(ctors ! =null|| mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || ! ObjectUtils.isEmpty(args)) {// Instantiate the bean and auto-assemble it according to the parameters
    return autowireConstructor(beanName, mbd, ctors, args);
  }
  // Call the constructor instantiated without arguments
	return instantiateBean(beanName, mbd);
}
Copy the code

determineConstructorsFromBeanPostProcessors

protectedConstructor<? >[] determineConstructorsFromBeanPostProcessors(@NullableClass<? > beanClass, String beanName)throws BeansException {
	
  if(beanClass ! =null && hasInstantiationAwareBeanPostProcessors()) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
      if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
        / / only AutowiredAnnotationBeanPostProcessor has carried on the implementation, all other returns null
        SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
        // Identify the candidate constructorConstructor<? >[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);if(ctors ! =null) {
          returnctors; }}}}return null;
}
Copy the code

AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors

publicConstructor<? >[] determineCandidateConstructors(Class<? > beanClass,final String beanName){
  // Get all the constructors
  rawCandidates = beanClass.getDeclaredConstructors();
  for(Constructor<? > candidate : rawCandidates) {// Whether there is an @autowired annotationMergedAnnotation<? > ann = findAutowiredAnnotation(candidate);if(ann ! =null) {
      // Whether it is necessary
      boolean required = determineRequiredStatus(ann);
      candidates.add(candidate);
    }
    else if (candidate.getParameterCount() == 0) {
      // No parameter constructordefaultConstructor = candidate; }}// The candidate constructor is not empty
  if(! candidates.isEmpty()) {// The candidate constructor is not null and requiredConstructor null denotes a constructor with the @autowired identifier
    / / but the required = false
    if (requiredConstructor == null) {
      if(defaultConstructor ! =null) {
        // Add the no-parameter constructor to the candidate constructor listcandidates.add(defaultConstructor); }}// Convert the constructor in the collection to an array
    candidateConstructors = candidates.toArray(newConstructor<? > [0]);
  }
  // If the candidate constructor is empty and there is a parameter constructor, the parameter constructor is used as the candidate constructor
  else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
    candidateConstructors = newConstructor<? >[] {rawCandidates[0]};
  }
  // Returns an array of candidate constructors
  return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
Copy the code

AutowireConstructor instantiates and automates assembly, extracting code snippet

protected BeanWrapper autowireConstructor(
			String beanName, RootBeanDefinition mbd, @NullableConstructor<? >[] ctors,@Nullable Object[] explicitArgs) {

  return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
Copy the code
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
			@NullableConstructor<? >[] chosenCtors,@Nullable Object[] explicitArgs) {
  for(Constructor<? > candidate : candidates) {// Get the type of the parameterClass<? >[] paramTypes = candidate.getParameterTypes();// Get the dependent beanargsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames..) ;// Call the instantiate method to instantiate the beanbw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse)); }}Copy the code

That is the instantiation of the bean

applyMergedBeanDefinitionPostProcessors

The third time is to parse out the attributes or methods that identify the annotations that need to be automatically assembled. The annotations mainly include @resource @Autowired @value @Inject @postconstruct @predestroy

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class
        beanType, String beanName) {
  for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof MergedBeanDefinitionPostProcessor) {
      / / CommonAnnotationBeanPostProcessor parsing @ PostConstruct @ PreDestroy @ the Resource
      / / AutowiredAnnotationBeanPostProcessor parsing the @autowired @ Value @ InjectMergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); }}}Copy the code

CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class
        beanType, String beanName) {
  / / for InitDestroyAnnotationBeanPostProcessor parent
  // Find the @postconstruct @predestroy annotation
  // Used for pre-initialization processing logic in the bean's life cycle
  super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
  // Find the property or method metadata identified by the @resource annotation
  // Store this metadata in the cache for use during the property assembly phase
  InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
  // Check for duplicate metadata to reprocess, such as an attribute with both @autowired and @Resource annotations
  // Use only one method for injection. Since @resource is parsed first, @resource is selected
  metadata.checkConfigMembers(beanDefinition);
}
Copy the code

InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class
        beanType, String beanName) {
  // Find the PostConstruct @predestroy annotation
  LifecycleMetadata metadata = findLifecycleMetadata(beanType);
	// reprocess
  metadata.checkConfigMembers(beanDefinition);
}
Copy the code

All of the post processor is similar, the process of take CommonAnnotationBeanPostProcessor here are analyzed

Let’s start by looking at the process of finding metadata

private InjectionMetadata findResourceMetadata(String beanName, finalClass<? > clazz,@Nullable PropertyValues pvs) {
  String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
  // Fetch from the cache
  / / call postProcessMergedBeanDefinition method put metadata parsing in the cache
  // Fetch the metadata when calling the postProcessProperties method
  InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
  if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    synchronized (this.injectionMetadataCache) {
      metadata = this.injectionMetadataCache.get(cacheKey);
      if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        if(metadata ! =null) {
          metadata.clear(pvs);
        }
        // Create metadata to look for attributes or methods identified by @resouce
        metadata = buildResourceMetadata(clazz);
        this.injectionMetadataCache.put(cacheKey, metadata); }}}return metadata;
}
Copy the code

buildResourceMetadata

private InjectionMetadata buildResourceMetadata(finalClass<? > clazz){
  // Determine if it is a candidate class, or return the default empty metadata
  // resourceAnnotationTypes are Annotation sets containing @resource @EJB @webServiceref
  // We usually just use @resource
  if(! AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {return InjectionMetadata.EMPTY;
  }
  do {
    // Loop through all attributes to see if there are WebServiceRef, EJB, Resource annotations, and build metadata if there are
    // doWithLocalFields takes all fields from targetClass and loops
    ReflectionUtils.doWithLocalFields(targetClass, field -> {
      if(webServiceRefClass ! =null && field.isAnnotationPresent(webServiceRefClass)) {
        currElements.add(new WebServiceRefElement(field, field, null));
      }
      else if(ejbClass ! =null && field.isAnnotationPresent(ejbClass)) {
        currElements.add(new EjbRefElement(field, field, null));
      }
      // Whether there is an @resource annotation
      else if (field.isAnnotationPresent(Resource.class)) {
        if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
          currElements.add(new ResourceElement(field, field, null)); }}});// Similar to the previous step, determine whether these annotations exist on the method
    ReflectionUtils.doWithLocalMethods(targetClass, method -> {
      / /... omit
    });
    // Get the parent class
    targetClass = targetClass.getSuperclass();
  }
  // If the parent class is not Object, continue to loop through the attributes and methods in the parent class
  while(targetClass ! =null&& targetClass ! = Object.class);// Encapsulates the built metadata into InjectionMetadata
  return InjectionMetadata.forElements(elements, clazz);
}
Copy the code

Now let’s look at the reprocessing process

public void checkConfigMembers(RootBeanDefinition beanDefinition) {
		Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());
  for (InjectedElement element : this.injectedElements) {
    Member member = element.getMember();
    / / check if the beanDefinition externallyManagedConfigMembers set already contains the members (properties or methods)
    if(! beanDefinition.isExternallyManagedConfigMember(member)) {// If it does not, the member will be registered
      beanDefinition.registerExternallyManagedConfigMember(member);
      // Add to the checked collectioncheckedElements.add(element); }}this.checkedElements = checkedElements;
}
Copy the code

For the fourth time, there is no implementation in Spring’s built-in processor for the call to process the earlier object, so skip it

This step, like the first, will be used with AOP and will be examined in the next chapter

The next step is to fill in the properties

populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
  / / here can be suspended filling property operation, implement InstantiationAwareBeanPostProcessor interface
	/ / and postProcessAfterInstantiation returns false, the returned directly, not to perform
  // All post-processors in Spring return true
  if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {
      if (bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        if(! ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return; }}}}// Get the autowiring type, default is 0,
  / / here only XML configuration, ImportBeanDefinitionRegistrar, spring BeanFactoryPostProcessor can be changed
  Mybatis = Mapper = BY_TYPE;
  / / in Mapper can be populated here SqlSessionTemplate, SqlSessionFactory properties
  int resolvedAutowireMode = mbd.getResolvedAutowireMode();
  if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
      autowireByName(beanName, mbd, bw, newPvs);
    }
    if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
      // Get the dependent bean and put it in newPvs
      autowireByType(beanName, mbd, bw, newPvs);
    }
    // Assign the new attribute list to the old referencepvs = newPvs; }}Copy the code

The autowireByName is similar to the autowireByType, but the autowireByType is more complex, and only the processing of the autowireByType is analyzed here

protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
	// Query properties that are not simple (Java built-in primitive types, String,Date, etc.)
  String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
  // Loop through all attribute names
  for (String propertyName : propertyNames) {
  	// Get method parameters
    MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
    // Build a dependency descriptor
    DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
    // Get the dependent bean
    // doResolveDependency is called in the resolveDependency method, which we will examine in the next post-handler call
		Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
    // Place the bean in the property collection
    if(autowiredArgument ! =null) { pvs.add(propertyName, autowiredArgument); }}}Copy the code

Now, back to the process of populating the properties

This sixth call puts the processor behind it, this time focusing on the auto-assembly of properties and methods

/ / @ Resouce CommonAnnotationBeanPostProcessor processing annotations of assembly
/ / AutowiredAnnotationBeanPostProcessor processing @autowired @ Value @ Inject annotation of assembly
for (BeanPostProcessor bp : getBeanPostProcessors()) {
  if (bp instanceof InstantiationAwareBeanPostProcessor) {
    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    // Handles autowiring, which assembles dependent properties into beans
    PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
    / /... Omit deprecated code...pvs = pvsToUse; }}Copy the code

The logic of this step is about the same, due to the complexity of AutowiredAnnotationBeanPostProcessor, we take the analysis of logic of AutowiredAnnotationBeanPostProcessor

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
  / / remove before postProcessMergedBeanDefinition parsed metadata
  // @autowired @value @inject Identifies an attribute or method
  // findAutowiringMetadata
  InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
  // Perform automatic assembly
  metadata.inject(bean, beanName, pvs);
  return pvs;
}
Copy the code

FindAutowiringMetadata, and see how much like the fourth step ~

private InjectionMetadata findAutowiringMetadata(String beanName, Class<? > clazz,@Nullable PropertyValues pvs) {
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		// Fetch from cache
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
			synchronized (this.injectionMetadataCache) {
				metadata = this.injectionMetadataCache.get(cacheKey);
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
					if(metadata ! =null) {
						metadata.clear(pvs);
					}
					// Build metadata, find the attribute or method identified by @autowird @value @inject to build
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata); }}}return metadata;
	}
Copy the code

Automatic assembly process

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) {
  // Retrieve the list of metadata that was previously reworked
  Collection<InjectedElement> checkedElements = this.checkedElements;
  if(! elementsToIterate.isEmpty()) {for (InjectedElement element : elementsToIterate) {
      // Perform attribute or method assemblyelement.inject(target, beanName, pvs); }}}Copy the code
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs){
  // force Field
  Field field = (Field) this.member;
  // Create a dependency descriptor
  DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
  // Get the dependent bean
	value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
  if(value ! =null) {
    ReflectionUtils.makeAccessible(field);
    // Assemble the obtained dependent beans into properties using reflectionfield.set(bean, value); }}Copy the code
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
  / / get a bean
  result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
  return result;
}
Copy the code
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter){
  // Parse @value annotations
  Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
  if(value ! =null) {
  	return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
  }
  // Find matching Beandefinitions by type
	Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
  if (matchingBeans.isEmpty()) {
    // If it is empty, determine whether it is necessary
    if (isRequired(descriptor)) {
      / / must have thrown NoSuchBeanDefinitionException anomalies
      raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
    }
    return null;
  }
  // If there is more than one candidate bean matching by type, you need to confirm which one it is
  if (matchingBeans.size() > 1) {
    // Identify what you really need to rely on
    // check if there is a @primary annotation
    // The Priority annotation is not implemented
    // There is no final match using the attribute name
    // Return null if no match is found
    autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
    if (autowiredBeanName == null) {
      // Check if it is necessary and throw an exception if it is
      if(isRequired(descriptor) || ! indicatesMultipleBeans(type)) {return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
      }
      else {
        return null;
      }
    }
    instanceCandidate = matchingBeans.get(autowiredBeanName);
  }
  if (instanceCandidate instanceof Class) {
    // Call the getBean method
    instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
  }
  Object result = instanceCandidate;
  return result;
}
Copy the code

GetBean method

public Object resolveCandidate(String beanName, Class
        requiredType, BeanFactory beanFactory) {
  return beanFactory.getBean(beanName);
}
Copy the code

So that’s the autowiring process, going back to the method of filling the properties for a little finishing touch

// PVS is null if it is not XML byName byType
if(pvs ! =null) {
  // Call set to assign a value
  applyPropertyValues(beanName, mbd, bw, pvs);
}
Copy the code
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
	// Use reflection to assign values to attributes
  bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
Copy the code

Procedure for filling properties, over~

Initialization process

initializeBean

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd){
  // If the bean implements the BeanNameAware, BeanClassLoaderAware, BeanFactoryAware interface
  // call back the corresponding method
  invokeAwareMethods(beanName, bean);
  // The seventh time the bean is processed before initialization
  // Call the @postconstruct annotation method, the Aware interface callback method
  wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  // Call the initialization method
  // If the bean implements the InitializingBean interface, the afterPropertiesSet method is called
  // Also called if the bean also implements a custom initialization method
  // afterPropertiesSet, then custom
  invokeInitMethods(beanName, wrappedBean, mbd);
  // Process the initialized bean for the eighth time
  wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
Copy the code

The above is the general process of initialization, and we will analyze it one by one

The first is invokeAwareMethods

private void invokeAwareMethods(String beanName, Object bean) {
  // The following process is clear at a glance, without much analysis
  if (bean instanceof Aware) {
    if (bean instanceof BeanNameAware) {
      ((BeanNameAware) bean).setBeanName(beanName);
    }
    if (bean instanceof BeanClassLoaderAware) {
      ClassLoader bcl = getBeanClassLoader();
      if(bcl ! =null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); }}if (bean instanceof BeanFactoryAware) {
      ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); }}}Copy the code

applyBeanPostProcessorsBeforeInitialization

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName){
  Object result = existingBean;
  for (BeanPostProcessor processor : getBeanPostProcessors()) {
    / / ImportAwareBeanPostProcessor processing ImportAware interface
    / / InitDestroyAnnotationBeanPostProcessor processing @ PostContrust annotation
    / / ApplicationContextAwareProcessor processing series of Aware interface callback methods
    Object current = processor.postProcessBeforeInitialization(result, beanName);
    if (current == null) {
      return result;
    }
    result = current;
  }
  return result;
}
Copy the code

InitDestroyAnnotationBeanPostProcessor

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  // Retrieve the metadata from the @postcontrust @predestroy parsing in step 4
  LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
  // call init (@postconstruct)
  metadata.invokeInitMethods(bean, beanName);
  return bean;
}
Copy the code
public void invokeInitMethods(Object target, String beanName) throws Throwable {
  // Fetch only init metadata (and destroy metadata)
  Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
  if(! initMethodsToIterate.isEmpty()) {for(LifecycleElement element : initMethodsToIterate) { element.invoke(target); }}}Copy the code
public void invoke(Object target) throws Throwable {
  ReflectionUtils.makeAccessible(this.method);
  // Direct reflection calls
  this.method.invoke(target, (Object[]) null);
}
Copy the code

ApplicationContextAwareProcessor process and invokeAwareMethods similar, here is not analyzed

invokeInitMethods

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd){
  // If InitializingBean interface is implemented, call afterPropertiesSet method
  boolean isInitializingBean = (bean instanceof InitializingBean);
  if (isInitializingBean && (mbd == null| |! mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
    ((InitializingBean) bean).afterPropertiesSet();
  }
  if(mbd ! =null&& bean.getClass() ! = NullBean.class) {// Call a custom initialization method
    String initMethodName = mbd.getInitMethodName();
    if(StringUtils.hasLength(initMethodName) && ! (isInitializingBean &&"afterPropertiesSet".equals(initMethodName)) && ! mbd.isExternallyManagedInitMethod(initMethodName)) {// Custom init methods are declared mainly in the @bean annotation, just pull out the initMethod call from beanDefinitioninvokeCustomInitMethod(beanName, bean, mbd); }}}Copy the code

applyBeanPostProcessorsAfterInitialization

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {
  Object result = existingBean;
  for (BeanPostProcessor processor : getBeanPostProcessors()) {
    / / rear Spring built-in processor, only ApplicationListenerDetector processing logic
    / / ApplicationListenerDetector will implement the interface ApplicationListener bean to add to the list of event listeners
    Object current = processor.postProcessAfterInitialization(result, beanName);
    if (current == null) {
      return result;
    }
    result = current;
  }
  return result;
}
Copy the code
public Object postProcessAfterInitialization(Object bean, String beanName){
  if (bean instanceof ApplicationListener) {
    // Add the bean to the list of event listeners
    this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
  }
}
Copy the code

That’s it! The bean is initialized!

With the bean initialization completed, the creation of the bean is complete, and this article is over. If you have any questions, please leave a comment below

Preview below: Loop dependencies for Spring source analysis

Spring Source code series
  1. Spring source code analysis of IOC container prestart process (completed)
  2. BeanFactory Architecture for Spring source analysis (completed)
  3. Spring Source Analysis BeanFactoryPostProcessor call process (completed)
  4. Spring source analysis Bean creation process (completed)
  5. What are cyclic dependencies and solutions for Spring source analysis
  6. AOP for Spring source analysis from parsing to invocation
  7. Spring source analysis of transaction management (1), transaction management is a feature of Spring as a container, summarize his basic implementation and principle
  8. Spring source analysis of transaction management (below), about his underlying thing isolation and thing propagation principle, focus on the analysis
Spring Mvc source code series
  1. The SpringMvc architecture
  2. SpringMvc source code analysis Handler parsing process
  3. Request chain process for SpringMvc source code analysis
Mybatis source series

tentative


Chase after more, can pay attention to me, recently have time to write the whole article, share pure for fun, also have a sense of achievement, the author of this article to this first