Detailed explanation of Spring @Autowire annotation source code

Table of contents

1: Triggering method:

Two: Source code analysis

2.1 Scan injection point

2.2 Attribute assignment


1: Triggering method:

1. After each Bean is instantiated, the Spring container calls the postProcessMergedBeanDefinition method of AutowireAnnotationBeanPostProcessor to scan the injection point.

2. After Spring instantiates each Bean and scans the injection point, it calls populateBean for Bean injection and calls the postProcessPropertyValues ​​method.

Two: Source code analysis

2.1 Scan injection point

Beans can be dependency injected by adding @Autowire annotations to properties, constructors, and set methods.

package service;

import org.springframework.beans.factory.annotation.Autowired;

public class UserService1 {

    @Autowired
    private  OrderService orderService;

    public void test(){
        System.out.println(orderService);
    }

}

First, find the injection point. When creating the Bean, after instantiation, call

AbstractAutowireCapableBeanFactory.java

	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

....

  if (!mbd.postProcessed) {
				try {
					//todo 在实例化后,对MergeBeanDefinition进行属性修改
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}

..

}

Enter the applyMergedBeanDefinitionPostProcessors method and call processor.postProcessMergedBeanDefinition(mbd,beanType,beanName);

	protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
		for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
			processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
		}
	}

AutowiredAnnotationBeanPostProcessor when processing @Autowire annotated classes

 Enter findAutowiringMetadata(beanName,beanType,null);

 

In the buildAutowiringMetadata(final Class<?> clazz) method, loop through properties and loop through methods

, the properties and methods cannot be static, encapsulate field and required into an AutowireFieldElement item, add it to currElements, and finally merge it into elements 

 

The above is the process of finding the injection point through dependency injection. Property assignment has not yet been performed.

2.2 Attribute assignment

After the bean is instantiated, circular dependencies, attribute filling, initialization, and bean destruction are performed.

Enter populateBean(beanName, mbd, instanceWrapper);

Mainly perform attribute injection based on postProcessProperties

Find injection points and attribute assignments here. Finding the injection point has been analyzed above, and the attribute assignment is analyzed below.

 The inject() method added to the field by the @Autowire annotation is in the AutowiredFieldElement internal class

 The first time there is no cache in resolveFieldValue(field,bean,beanName), the cache is for the prototype bean, because the singleton bean will only be created once and the properties will be injected once.

Finally, the bean is found and returned in DefaultListableBeanFactory.java

1. First process the @Value annotation

2. Determine whether it is a Map or List complex bean. Among them, call the findAutowireCandidates method and go to the Spring container to find it according to the type.

Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
      new MultiElementDescriptor(descriptor));

3. Find the bean in the Spring container according to the type. The returned key is beanName. The value may be a bean object or a bean class.

Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

4. If matcingbeans.size >1 and multiple beans are found based on the type, then find them based on the name and call

The determineAutowireCandidate method first determines whether the @primary annotation is added. If so, it returns the bean, then determines the priority of the bean, and then matches the name of the descriptor, which is either the name of the field or the name of the set method parameter. Finally, the beanName is returned. If these annotations are not added, null is returned.

5. If the bull returned in step 4 is not configured with @Autowire (required=false) and the beans are not complex types, an exception expected single matching bean but found beanName will be thrown.

6.According to beanName, get the bean/bean class and return

 

Guess you like

Origin blog.csdn.net/qq_24186017/article/details/128159912