Spring source code: @Autowired implementation principle

@Autowired using

  1. constructor injection
public Class Outer {
    
    
	private Inner inner;
	@Autowired
	public Outer(Inner inner) {
    
    
		this.inner = inner;
	}
}
  1. attribute injection
public Class Outer {
    
    
	@Autowired
	private Inner inner;
}
  1. method injection
public Class Outer {
    
    
	private Inner inner;
	public Inner getInner() {
    
    
		return inner;
	}
	@Autowired
	public void setInner(Inner inner) {
    
    
		this.inner = inner;
	}
}

At present, most of the codes use the second and third types. The first type is completed when the bean is instantiated, while the implementation principles of the second and third types are the same, and it is completed when the property is filled. This article will introduce the second and third is the implementation principle

Before we start, @Autowiredhow should we implement it if we design it ourselves? I think the method is relatively simple

  1. @AutowiredFind all annotated 字段sums under the bean class by reflection方法
  2. Get the field, getBean(字段)get the corresponding bean, and then inject the bean through the reflection fieldcallset

@Autowired source code analysis

AutowiredAnnotationBeanPostProcessor class

This class is @Autowiredthe concrete implementation class, first preview the class method

AutowiredAnnotationBeanPostProcessorPreview.png

It is found that the only possibility to intervene in the bean creation operation is the post-processor. There are 3 methods for post-processing, one of which is outdated, namely, post- postProcessMergedBeanDefinitionprocessing postProcessProperties. Let’s take a look at the specifics of these two methods the code

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
		implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
    
    

	...

	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    
    
		// 1. 寻找bean中所有被@Autowired注释的属性,并将属性封装成InjectedElement类型
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}

	...

	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    
    
		// 1. 寻找通过@Autowired注解的属性或者方法
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
    
    
			// 2. 注入
			metadata.inject(bean, beanName, pvs);
		}
		catch (BeanCreationException ex) {
    
    
			throw ex;
		}
		catch (Throwable ex) {
    
    
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}

	...
}

It is the same as our guess. First, find out all the annotated @Autowiredproperties or methods, and then inject them. Of course, postProcessMergedBeanDefinitionthe call of the post processor must be postProcessPropertiesbefore. Here we review the creation process of spring beans. 2 processors I have marked in yellow

spring @Autowired injection timing.jpg


1. Find all @Autowired

// 寻找bean中所有被@Autowired注释的属性,并将属性封装成InjectedElement类型
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
12
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    
    
		// Fall back to class name as cache key, for backwards compatibility with custom callers.
		// 获取缓存的key值,一般以beanName做key
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		// Quick check on the concurrent map first, with minimal locking.
		// 从缓存中获取metadata
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		// 检测metadata是否需要更新
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    
    
			synchronized (this.injectionMetadataCache) {
    
    
				metadata = this.injectionMetadataCache.get(cacheKey);
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    
    
					if (metadata != null) {
    
    
						metadata.clear(pvs);
					}
					// 通过clazz类,查找所有@Autowired的属性或者方法,并封装成InjectionMetadata类型
					metadata = buildAutowiringMetadata(clazz);
					// 将metadata加入缓存
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

It can be seen that spring is still using caching to improve performance and continue to track the core codebuildAutowiringMetadata(clazz)

	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    
    
		// 查看clazz是否有Autowired注解
		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
    
    
			return InjectionMetadata.EMPTY;
		}
		// 这里需要注意AutowiredFieldElement,AutowiredMethodElement均继承了InjectionMetadata.InjectedElement
		// 因此这个列表是可以保存注解的属性和被注解的方法的
		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;

		// 1. 通过do while循环,递归的往直接继承的父类寻找@Autowired
		do {
    
    
			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
			
			// 2. 通过反射,获取所有属性,doWithLocalFields则是循环的对每个属性应用以下匿名方法
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
    
    
				// 判断当前field属性是否含有@Autowired的注解
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				if (ann != null) {
    
    
					// 返回该属性在类中的修饰符,如果等于static常量,则抛出异常,@Autowired不允许注解在静态属性上
					if (Modifier.isStatic(field.getModifiers())) {
    
    
						if (logger.isInfoEnabled()) {
    
    
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					// @Autowired有required属性,获取required的值,默认为true
					boolean required = determineRequiredStatus(ann);
					// 3. 将field封装成InjectedElement,并添加到集合中,这里用的是AutowiredFieldElement
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			// 4. @Autowired可以注解在方法上
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
    
    
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
    
    
					return;
				}
				MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
    
    
					if (Modifier.isStatic(method.getModifiers())) {
    
    
						if (logger.isInfoEnabled()) {
    
    
							logger.info("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					if (method.getParameterCount() == 0) {
    
    
						if (logger.isInfoEnabled()) {
    
    
							logger.info("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					boolean required = determineRequiredStatus(ann);
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					// 5. 将方法封装成InjectedElement,并添加到集合中,这里用的是AutowiredMethodElement
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});

			elements.addAll(0, currElements);
			// 返回直接继承的父类
			targetClass = targetClass.getSuperclass();
		}
		// 如果父类不为空则需要把父类的@Autowired属性或方法也找出
		while (targetClass != null && targetClass != Object.class);
		// 6. new InjectionMetadata(clazz, elements),将找到的所有的待注入属性或方法生成metadata返回
		return InjectionMetadata.forElements(elements, clazz);
	}
  1. The outer do ... while ... loop is used to recursively find @Autowiredproperties or methods of the parent class
  2. Obtain all attributes through reflection and loop through to verify whether each attribute is@Autowired注解
  3. Find filedthe package that contains the @Autowired annotation AutowiredFieldElementand add it to the list
  4. Loop through annotations on methods
  5. Encapsulate the found method AutowiredMethodElementand add it to the list.
    It is important to emphasize here that InjectedElement is inherited by AutowiredFieldElement, AutowiredMethodElementand they all have their own injectfunctions to achieve their own injection. So change ArrayList elements to have 2 types of properties
    InjectedElement.png
  6. Generate metadata data and return all found element lists and clazz as parameters

2. Injection

// 注入
metadata.inject(bean, beanName, pvs);
	public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    
    
		// 获取所有需要被注入的元素
		Collection<InjectedElement> checkedElements = this.checkedElements;
		Collection<InjectedElement> elementsToIterate =
				(checkedElements != null ? checkedElements : this.injectedElements);
		// 迭代的元素不为空
		if (!elementsToIterate.isEmpty()) {
    
    
			for (InjectedElement element : elementsToIterate) {
    
    
				if (logger.isTraceEnabled()) {
    
    
					logger.trace("Processing injected element of bean '" + beanName + "': " + element);
				}
				// 循环注入,这里有可能是AutowiredFieldElement也可能AutowiredMethodElement,因此调用的inject是2个不同的方法
				element.inject(target, beanName, pvs);
			}
		}
	}

Use the for loop to traverse what we just found elements列表and inject. There is a special reminder above that the element here may be AutowiredFieldElementa type, or AutowiredMethodElementa type. Each represents @Autowired注解two different elements on attributes and annotations on methods. So they call element.inject(target, beanName, pvs);it differently

2.1 Field injection (AutowiredFieldElement)

	private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
    
    
		@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    
    
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
    
    
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
    
    
				// 专门用于注入的包装类,包装构造函数参数,方法参数或字段
				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
				// 设置class
				desc.setContainingClass(bean.getClass());
				// 需要被自动注入的beanNames,这里只有可能 = 1,方法注入时才有可能为多个
				Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
				Assert.state(beanFactory != null, "No BeanFactory available");
				TypeConverter typeConverter = beanFactory.getTypeConverter();// 获取类型转换器
				try {
    
    
					// 通过beanFactory获取属性对应的值,比如需要调用getBean("b")获取依赖的属性单例,并且通过自动转型转为需要的类型
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				}
				catch (BeansException ex) {
    
    
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				}
				synchronized (this) {
    
    
					if (!this.cached) {
    
    
						if (value != null || this.required) {
    
    
							this.cachedFieldValue = desc;
							// 注册依赖,
							registerDependentBeans(beanName, autowiredBeanNames);
							// 因为是属性注入,因此这里只有可能等于1
							if (autowiredBeanNames.size() == 1) {
    
    
								String autowiredBeanName = autowiredBeanNames.iterator().next();
								if (beanFactory.containsBean(autowiredBeanName) &&
										beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
    
    
									// 缓存当前value
									this.cachedFieldValue = new ShortcutDependencyDescriptor(
											desc, autowiredBeanName, field.getType());
								}
							}
						}
						else {
    
    
							this.cachedFieldValue = null;
						}
						this.cached = true;
					}
				}
			}
			if (value != null) {
    
    
				// 通过反射,将value值设置到bean中
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}
	}

Most of the work above is doing the acquisition of the bean to be injected and the conversion of the type. If you go deeper, you can talk about spring Ioc again, but the core is to get the corresponding bean from getBean (field)... We are concerned with the core statement here, which is these two sentences

            if (value != null) {
    
    
                // 通过反射,将value值设置到bean中
                ReflectionUtils.makeAccessible(field);
                field.set(bean, value);
            }

Through reflection, spring calls the set of field to inject properties

2.2 Method injection (AutowiredMethodElement)

	private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {
    
    

		
		@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    
    
			if (checkPropertySkipping(pvs)) {
    
    
				return;
			}
			// @Autowired标注在方法上
			Method method = (Method) this.member;
			Object[] arguments;
			if (this.cached) {
    
    
				// Shortcut for avoiding synchronization...
				// 有缓存
				arguments = resolveCachedArguments(beanName);
			}
			else {
    
    
				// 没缓存,直接获取方法上所有的参数
				int argumentCount = method.getParameterCount();
				arguments = new Object[argumentCount];
				DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
				Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
				Assert.state(beanFactory != null, "No BeanFactory available");
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				// 循环所有参数
				for (int i = 0; i < arguments.length; i++) {
    
    
					MethodParameter methodParam = new MethodParameter(method, i);
					DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
					currDesc.setContainingClass(bean.getClass());
					descriptors[i] = currDesc;
					try {
    
    
						// 通过beanFactory,获取代注入的bean,并进行类型转换
						Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
						if (arg == null && !this.required) {
    
    
							arguments = null;
							break;
						}
						arguments[i] = arg;
					}
					catch (BeansException ex) {
    
    
						throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
					}
				}
				synchronized (this) {
    
    
					if (!this.cached) {
    
    
						if (arguments != null) {
    
    
							DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);
							// 注册依赖
							registerDependentBeans(beanName, autowiredBeans);
							// 如果自动注入的个数 = 参数个数,则缓存
							if (autowiredBeans.size() == argumentCount) {
    
    
								Iterator<String> it = autowiredBeans.iterator();
								Class<?>[] paramTypes = method.getParameterTypes();
								for (int i = 0; i < paramTypes.length; i++) {
    
    
									String autowiredBeanName = it.next();
									if (beanFactory.containsBean(autowiredBeanName) &&
											beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
    
    
										// 缓存
										cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
												descriptors[i], autowiredBeanName, paramTypes[i]);
									}
								}
							}
							// 缓存方法
							this.cachedMethodArguments = cachedMethodArguments;
						}
						else {
    
    
							this.cachedMethodArguments = null;
						}
						this.cached = true;
					}
				}
			}
			if (arguments != null) {
    
    
				try {
    
    
					// 反射调用注入方法,将获取到的所有bean作为参数
					ReflectionUtils.makeAccessible(method);
					method.invoke(bean, arguments);
				}
				catch (InvocationTargetException ex) {
    
    
					throw ex.getTargetException();
				}
			}
		}

	}

The biggest difference between this and attribute injection is that @Autowired注解in terms of methods, methods can have multiple parameters, so here you need to obtain them one by one through a loop, and the way to obtain beans is the same as above, essentially through acquisition getBean. And the core sentence is still 2 sentences

// 反射调用注入方法,将获取到的所有bean作为参数
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);

Different from attribute injection, when it @Autowired注解is on a method, for example, we annotate it on a setter method, we only need to directly call the setter method to pass in the parameter array, that is, use invoke to trigger the method, and the specific attribute assignment process is in the setter method written by the user.

Guess you like

Origin blog.csdn.net/qq_43842093/article/details/131262051