Spring 之 @Autowired 详解

概念

@Autowired是一种注解,可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作,@Autowired标注可以放在成员变量上,也可以放在成员变量的set方法上,也可以放在任意方法上表示,自动执行当前方法,如果方法有参数,会在IOC容器中自动寻找同类型参数为其传值。
这里必须明确:@Autowired是根据类型进行自动装配的,如果需要按名称进行装配,则需要配合@Qualifier使用;

核心

我们先来看下实现的核心类 AutowiredAnnotationBeanPostProcessor 对应的类图,从中可以看到也是通过 BeanPostProcessor 来实现的。因为实现了 InstantiationAwareBeanPostProcessor 接口,所以在依赖注入的时候就会进行执行。
Spring 之 @Autowired 详解_第1张图片

原理

在Spring 之 DI 详解讲解到的 AbstractAutowireCapableBeanFactory.populateBean() 方法这样一段代码,这里正是 @Autowried 注解进行解析执行的地方。

//对非autowiring的属性进行依赖注入处理
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
	if (pvs == null) {
		pvs = mbd.getPropertyValues();
	}
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof InstantiationAwareBeanPostProcessor) {
			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
			//@Autowired、@Value、@Inject等注入注解就是在此处进入进行实现(AutowiredAnnotationBeanPostProcessor)
			PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
			if (pvsToUse == null) {
				if (filteredPds == null) {
					filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
				}
				pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					return;
				}
			}
			pvs = pvsToUse;
		}
	}
}

继续跟进,跳转到 AutowiredAnnotationBeanPostProcessor.postProcessProperties() 方法,源码如下:

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
	//获取bean的所有需要自动注入的属性和方法封装到InjectionMetadata的injectedElements集合里面
	InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
	try {
		//进行依赖注入
		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;
}

我们先来看看是如何查找自动注入的属性和方法,

//初始化时就将@Autowried、@Value或javax.inject.Inject包下的注解添加到自动注入的类型中,以便后续使用扫描数据
public AutowiredAnnotationBeanPostProcessor() {
	this.autowiredAnnotationTypes.add(Autowired.class);
	this.autowiredAnnotationTypes.add(Value.class);
	try {
		this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
				ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
		logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
	}
	catch (ClassNotFoundException ex) {
		// JSR-330 API not available - simply skip.
	}
}
//寻找需要进行自动注入的数据
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
	// Fall back to class name as cache key, for backwards compatibility with custom callers.
	String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
	// Quick check on the concurrent map first, with minimal locking.
	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);
				}
				metadata = buildAutowiringMetadata(clazz);
				this.injectionMetadataCache.put(cacheKey, metadata);
			}
		}
	}
	return metadata;
}

//构建需要进行自动装配的数据对象
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
	List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
	Class<?> targetClass = clazz;

	do {
		//存储当前包含了自动装配注解的元素
		final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

		ReflectionUtils.doWithLocalFields(targetClass, field -> {
			//获取包含自动装配注解的字段
			AnnotationAttributes ann = findAutowiredAnnotation(field);
			if (ann != null) {
				if (Modifier.isStatic(field.getModifiers())) {
					if (logger.isInfoEnabled()) {
						logger.info("Autowired annotation is not supported on static fields: " + field);
					}
					return;
				}
				boolean required = determineRequiredStatus(ann);
				currElements.add(new AutowiredFieldElement(field, required));
			}
		});

		ReflectionUtils.doWithLocalMethods(targetClass, method -> {
			Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
			if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
				return;
			}
			//获取包含自动装配注解的方法
			AnnotationAttributes 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);
				currElements.add(new AutowiredMethodElement(method, required, pd));
			}
		});

		elements.addAll(0, currElements);
		targetClass = targetClass.getSuperclass();
	}
	while (targetClass != null && targetClass != Object.class);

	return new InjectionMetadata(clazz, elements);
}

private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
	//如果字段或方法没有注解则直接返回
	if (ao.getAnnotations().length > 0) {  // autowiring annotations have to be local
		for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
			//如果配置了@Autowried、@Value或javax.inject.Inject包下的注解(如:@Inject等),则添加到要处理的注解数据集合中
			AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
			if (attributes != null) {
				return attributes;
			}
		}
	}
	return null;
}

从上面我们可以清楚看到,Spring 会查找到当前 Bean 所有配置了@Autowried、@Value或javax.inject.Inject包下的注解的属性或方法并将其添加到要处理的注解数据集合中。

这里有一点需要说明,其实这不是第一次加载这边注解数据,在 AbstractAutowireCapableBeanFactory.doCreateBean() 方法中调用 createBeanInstance 方法实例化数据后就会调用 AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition() 方法进行解析对应的注解数据并缓存起来。第二次走到 findAutowiringMetadata 方法时,直接从缓存中获取即可。但在理解 @Autowried 原理上来说并不受影响。

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	//获取bean的所有需要自动注入的属性和方法封装到InjectionMetadata的injectedElements集合里面
	InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
	//判断是否外部管理的配置成员
	metadata.checkConfigMembers(beanDefinition);
}

接下来看看是如何进行依赖注入的,跳转到 InjectionMetadata.inject() 方法。源码如下:

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.inject()从beanFactory中获取到对应属性bean进行依赖注入
			//调用AutowiredMethodElement.inject()从beanFactory中获取到对应入参bean,并执行方法
			element.inject(target, beanName, pvs);
		}
	}
}

后面都是通过 BeanName 从 BeanFactory 中获取到对应的 Bean 引用,然后通过反射注入属性或执行方法。有兴趣的同学可以自己进一步看看,这里就不再跟进了。

总结

在进行依赖注入的时候,进入到 AutowiredAnnotationBeanPostProcessor 类执行对应方法。将配置了@Autowried、@Value或javax.inject.Inject包下的注解的属性或方法封装成AutowiredFieldElement或者AutowiredMethodElement对象,最后统一把这些对象封装成InjectionMetadata对象。在后续遍历这些对象数据时,通过反射给属性赋值或调用方法。

你可能感兴趣的:(Spring)