Spring源码-IOC容器(十)-@Autowired解析

Spring IOC容器 源码解析系列,建议大家按顺序阅读,欢迎讨论

(spring源码均为4.1.6.RELEASE版本)

  1. Spring源码-IOC容器(一)-构建简单IOC容器
  2. Spring源码-IOC容器(二)-Bean的定位解析注册
  3. Spring源码-IOC容器(三)-GetBean
  4. Spring源码-IOC容器(四)-FactoryBean
  5. Spring源码-IOC容器(五)-Bean的初始化
  6. Spring源码-IOC容器(六)-bean的循环依赖
  7. Spring源码-IOC容器(七)-ApplicationContext
  8. Spring源码-IOC容器(八)-NamespaceHandler与自定义xml
  9. Spring源码-IOC容器(九)-Component-Scan源码解析
  10. Spring源码-IOC容器(十)-@Autowired解析

1.前言

部门有实习生来的时候,都会先了解系统的基本架构,再写一个基本的demo。通常强调的就是新建的类上要加@Controller或@Service,而类中的引用的其他对象的属性上加上@Autowired,然后写点增删改查就ok了。一般初学一个框架时只需知道如何使用,但想要用的好,就必须要深入了解其原理。所谓知其然,也要知其所以然。在Spring使用注解后,因为其本身就是非侵入式的设计,导致使用的人能感知到的就是几个注解。这样的框架的设计自然是极好的,对于使用的人来说,更是值得学习。

@Controller和@Service都是继承自@Component,只是分别标识Controller层和Service层,用于对类进行分类。@Component作为Spring的类扫描的默认注解,在Spring源码-IOC容器(九)-Component-Scan源码解析中已介绍过。而@Autowired可以说是Spring依赖注入的最重要的注解,本章就来详细解析它的使用原理。

2.使用范围及方式

@Autowired最常用的方式就是放在属性或setter方法上,而其还能放在构造函数以及非setter方法的任意方法上。

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

	/**
	 * Declares whether the annotated dependency is required.
	 * <p>Defaults to {@code true}.
	 */
	boolean required() default true;

}

可以看到支持的目标包括构造函数,属性,方法,也可以被作为元注解。这里需要强调的有两个:

  1. 属性和方法可以为private
  2. 无参的构造方法上使用会报错,原因在后面解析。

@Autowired是根据对象类型来进行匹配的,如果想通过指定具体的bean的名称,可以使用@Qualifier。@Autowired只有required属性可以设置,默认为true,即默认必须能匹配到相应的bean,否则就会报出NoSuchBeanDefinitionException异常。如果允许依赖注入失败,则可以设置required=false。

@Autowired的解析器是AutowiredAnnotationBeanPostProcessor,它是BeanPostProcessor后置处理器的子类。如果通过BeanFactory的启动方式,需要手动注入。

xml文件

<bean id="autowiredAnnotationBeanPostProcessor" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

并且通过

beanFactory.addBeanPostProcessor((BeanPostProcessor) beanFactory.
            getBean("autowiredAnnotationBeanPostProcessor"));

添加到beanPostProcessor集合中。

但通常情况下component-scan扫描的配置处理中默认就加载了AutowiredAnnotationBeanPostProcessor。

<context:component-scan base-package=".."/>

如果不使用component-scan的扫描配置,可以通过

<context:annotation-config/>

来默认配置。

3.原理及源码

在Spring的bean实例化过程中有许多BeanPostProcessor扩展点,支持内置的以及用户自定义的BeanPostProcessor对bean的实例化进行干预和操作。BeanPostProcessor接口本身只支持bean的初始化前后的扩展,但它的子接口则增加了更多扩展点。

  1. BeanPostProcessor
    • postProcessBeforeInitialization 初始化前扩展
    • postProcessAfterInitialization 初始化后扩展
  2. InstantiationAwareBeanPostProcessor
    • postProcessBeforeInstantiation 实例化前扩展
    • postProcessAfterInstantiation 实例化后扩展
    • postProcessPropertyValues 依赖注入前扩展
  3. MergedBeanDefinitionPostProcessor
    • postProcessMergedBeanDefinition 实例化后针对BeanDefinition的扩展
  4. SmartInstantiationAwareBeanPostProcessor(InstantiationAwareBeanPostProcessor的子接口,还有两个方法这里没有列举)
    • determineCandidateConstructors 实例化时返回构造函数候选者

对于AutowiredAnnotationBeanPostProcessor,先来看它的实现

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
	implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware

它实现了MergedBeanDefinitionPostProcessor接口,而继承的InstantiationAwareBeanPostProcessorAdapter其实是SmartInstantiationAwareBeanPostProcessor接口的默认实现类。所以基本支持了所有的扩展点,但很多都是继承的默认方法,主要实现的有三个方法:

  1. determineCandidateConstructors
  2. postProcessMergedBeanDefinition
  3. postProcessPropertyValues

第一个方法支撑了@Autowired作用于构造函数,第二和三方法支撑了@Autowired作用于属性和方法。

1.构造函数

在AbstractAutowireCapableBeanFactory中的createBeanInstance方法中,对bean进行实例化操作。如果没有通过xml指定构造函数或工厂方法,则会判断是否有InstantiationAwareBeanPostProcessor注册到容器中,并判断是否为其子接口SmartInstantiationAwareBeanPostProcessor的实现类,然后调用determineCandidateConstructors方法返回构造函数候选者集合。

AbstractAutowireCapableBeanFactory.createBeanInstance()

// Need to determine the constructor...
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
		mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
		mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
	return autowireConstructor(beanName, mbd, ctors, args);
}

protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(Class<?> beanClass, String beanName)
		throws BeansException {

	if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
				SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
				Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
				if (ctors != null) {
					return ctors;
				}
			}
		}
	}
	return null;
}

此时就进入AutowiredAnnotationBeanPostProcessor的determineCandidateConstructors方法中

public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName) throws BeansException {
	// 解析Lookup注解,并设置到BeanDefinition中
	if (!this.lookupMethodsChecked.contains(beanName)) {
		ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
			@Override
			public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
				Lookup lookup = method.getAnnotation(Lookup.class);
				if (lookup != null) {
					LookupOverride override = new LookupOverride(method, lookup.value());
					try {
						RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
						mbd.getMethodOverrides().addOverride(override);
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanCreationException(beanName,
								"Cannot apply @Lookup to beans without corresponding bean definition");
					}
				}
			}
		});
		this.lookupMethodsChecked.add(beanName);
	}

	// Quick check on the concurrent map first, with minimal locking.
	Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
	if (candidateConstructors == null) {
		synchronized (this.candidateConstructorsCache) {
			candidateConstructors = this.candidateConstructorsCache.get(beanClass);
			if (candidateConstructors == null) {
				// 拿到所有public的构造函数
				Constructor<?>[] rawCandidates = beanClass.getDeclaredConstructors();
				List<Constructor<?>> candidates = new ArrayList<Constructor<?>>(rawCandidates.length);
				Constructor<?> requiredConstructor = null;
				Constructor<?> defaultConstructor = null;
				for (Constructor<?> candidate : rawCandidates) {
					// 寻找构造函数上的@Autowired注解
					AnnotationAttributes ann = findAutowiredAnnotation(candidate);
					if (ann != null) {
						// 只允许有一个required=true的@Autowired
						if (requiredConstructor != null) {
							throw new BeanCreationException(beanName,
									"Invalid autowire-marked constructor: " + candidate +
									". Found constructor with 'required' Autowired annotation already: " +
									requiredConstructor);
						}
						// 无参构造函数上设置@Autowired抛出异常
						if (candidate.getParameterTypes().length == 0) {
							throw new IllegalStateException(
									"Autowired annotation requires at least one argument: " + candidate);
						}
						boolean required = determineRequiredStatus(ann);
						if (required) {
							if (!candidates.isEmpty()) {
								throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructors: " + candidates +
										". Found constructor with 'required' Autowired annotation: " +
										candidate);
							}
							requiredConstructor = candidate;
						}
						candidates.add(candidate);
					}
					else if (candidate.getParameterTypes().length == 0) {
						defaultConstructor = candidate;
					}
				}
				if (!candidates.isEmpty()) {
					// Add default constructor to list of optional constructors, as fallback.
					if (requiredConstructor == null) {
						if (defaultConstructor != null) {
							candidates.add(defaultConstructor);
						}
						else if (candidates.size() == 1 && logger.isWarnEnabled()) {
							logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
									"': single autowire-marked constructor flagged as optional - this constructor " +
									"is effectively required since there is no default constructor to fall back to: " +
									candidates.get(0));
						}
					}
					candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
				}
				else {
					candidateConstructors = new Constructor<?>[0];
				}
				this.candidateConstructorsCache.put(beanClass, candidateConstructors);
			}
		}
	}
	return (candidateConstructors.length > 0 ? candidateConstructors : null);
}

基本步骤为:

  1. 查找是否有Lookup注解,如果有,设置到BeanDefinition的methodOverrides中
  2. 从Class对象中获取所有public构造方法
  3. 返回所有设置@Autowired注解的构造方法(只能有一个required=true)

返回的构造函数集合根据一定的策略找到最佳的一个,然后通过newInstance方法实例化bean对象。

2.属性及方法

在bean实例化完成后,MergedBeanDefinitionPostProcessor的扩展点支持对BeanDefinition进行处理。

AbstractAutowireCapableBeanFactory.doCreateBean()

// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
	if (!mbd.postProcessed) {
		applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
		mbd.postProcessed = true;
	}
}

而在AutowiredAnnotationBeanPostProcessor的实现中,通过查找并组装所有有@Autowired的属性及方法。

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	if (beanType != null) {
		// 查找所有@Autowired的属性和方法,组装成InjectionMetadata,存放到Map中
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}
}

在findAutowiringMetadata方法中,对属性和方法分开解析并组装不同的数据结构中,AutowiredFieldElement和AutowiredMethodElement。

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
	// Fall back to class name as cache key, for backwards compatibility with custom callers.
	// 缓存key为bean名称
	String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
	// Quick check on the concurrent map first, with minimal locking.
	// 先从Map中查询是否存在
	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);
				}
				try {
					// 构建元数据数据结构
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
				catch (NoClassDefFoundError err) {
					throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() +
							"] for autowiring metadata: could not find class that it depends on", err);
				}
			}
		}
	}
	return metadata;
}

// 根据Class对象,对属性和方法分别进行组装
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
	LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
	Class<?> targetClass = clazz;

	do {
		LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<InjectionMetadata.InjectedElement>();
		// 属性
		for (Field field : targetClass.getDeclaredFields()) {
			AnnotationAttributes ann = findAutowiredAnnotation(field);
			if (ann != null) {
				if (Modifier.isStatic(field.getModifiers())) {
					if (logger.isWarnEnabled()) {
						logger.warn("Autowired annotation is not supported on static fields: " + field);
					}
					continue;
				}
				boolean required = determineRequiredStatus(ann);
				currElements.add(new AutowiredFieldElement(field, required));
			}
		}

		// 方法
		for (Method method : targetClass.getDeclaredMethods()) {
			Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
			if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
				continue;
			}
			AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
			if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
				if (Modifier.isStatic(method.getModifiers())) {
					if (logger.isWarnEnabled()) {
						logger.warn("Autowired annotation is not supported on static methods: " + method);
					}
					continue;
				}
				if (method.getParameterTypes().length == 0) {
					if (logger.isWarnEnabled()) {
						logger.warn("Autowired annotation should be used on methods with actual 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);
}

这样在实例化后,bean中所有@Autowired的属性和方法都被组装成InjectionMetadata存储到以bean名称为key的Map中。

AbstractAutowireCapableBeanFactory的populateBean方法用来对bean进行依赖注入,而在真正的依赖注入前,同样检查是否有InstantiationAwareBeanPostProcessor,并调用postProcessPropertyValues方法对bean的依赖进行外部扩展处理。

AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues也非常清晰。

public PropertyValues postProcessPropertyValues(
		PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

	// 再次查找所有@Autowired的属性和方法,如果有缓存,直接从缓存中获取
	InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
	try {
		// 执行属性的依赖注入和方法的执行
		metadata.inject(bean, beanName, pvs);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
	}
	return pvs;
}

findAutowiringMetadata在上面已经介绍过了,此时直接从Map的缓存中获取即可。主要来看InjectionMetadata的inject方法。

public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable {
	Collection<InjectedElement> elementsToIterate =
			(this.checkedElements != null ? this.checkedElements : this.injectedElements);
	if (!elementsToIterate.isEmpty()) {
		boolean debug = logger.isDebugEnabled();
		for (InjectedElement element : elementsToIterate) {
			if (debug) {
				logger.debug("Processing injected element of bean '" + beanName + "': " + element);
			}
			element.inject(target, beanName, pvs);
		}
	}
}

遍历取出所有的InjectedElement,包括属性和方法,分别执行inject方法。

1.AutowiredFieldElement

主要的操作是

  1. 通过beanFactory的resolveDependency方法从beanFactory中匹配相同类型的BeanDefition,并通过getBean方法实例化对象,如果有多个匹配项,默认返回第一个。

  2. 向容器注册依赖关系,并缓存RuntimeBeanReference类型的FieldValue

  3. 通过反射注入属性值

     protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
     	Field field = (Field) this.member;
     	try {
     		Object value;
     		if (this.cached) {
     			value = resolvedCachedArgument(beanName, this.cachedFieldValue);
     		}
     		else {
     			DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
     			desc.setContainingClass(bean.getClass());
     			Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
     			TypeConverter typeConverter = beanFactory.getTypeConverter();
     			// 从beanFactory匹配类型相同的bean对象
     			value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
     			synchronized (this) {
     				if (!this.cached) {
     					if (value != null || this.required) {
     						this.cachedFieldValue = desc;
     						// 注册对象依赖关系
     						registerDependentBeans(beanName, autowiredBeanNames);
     						if (autowiredBeanNames.size() == 1) {
     							String autowiredBeanName = autowiredBeanNames.iterator().next();
     							if (beanFactory.containsBean(autowiredBeanName)) {
     								if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
     									this.cachedFieldValue = new RuntimeBeanReference(autowiredBeanName);
     								}
     							}
     						}
     					}
     					else {
     						this.cachedFieldValue = null;
     					}
     					this.cached = true;
     				}
     			}
     		}
     		if (value != null) {
     			// 反射注入属性值
     			ReflectionUtils.makeAccessible(field);
     			field.set(bean, value);
     		}
     	}
     	catch (Throwable ex) {
     		throw new BeanCreationException("Could not autowire field: " + field, ex);
     	}
     }
    

    }

2.AutowiredMethodElement

方法的操作同属性相近,只是根据方法中的每个参数的类型去beanFactory中去匹配bean对象。

  1. 遍历方法中的所有参数,按照类型从beanFactory中匹配相应的BeanDefition并实例化,过程同AutowiredFieldElement中一致

  2. 注册对象依赖关系,方法中所有的参数都是bean的依赖方,然后每个参数分别缓存为RuntimeBeanReference类型的结构。

  3. 调用反射方法执行方法

     protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
     	if (checkPropertySkipping(pvs)) {
     		return;
     	}
     	Method method = (Method) this.member;
     	try {
     		Object[] arguments;
     		if (this.cached) {
     			// Shortcut for avoiding synchronization...
     			arguments = resolveCachedArguments(beanName);
     		}
     		else {
     			Class<?>[] paramTypes = method.getParameterTypes();
     			arguments = new Object[paramTypes.length];
     			DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
     			Set<String> autowiredBeanNames = new LinkedHashSet<String>(paramTypes.length);
     			TypeConverter typeConverter = beanFactory.getTypeConverter();
     			// 遍历方法中的参数,查找对应的bean实例
     			for (int i = 0; i < arguments.length; i++) {
     				MethodParameter methodParam = new MethodParameter(method, i);
     				DependencyDescriptor desc = new DependencyDescriptor(methodParam, this.required);
     				desc.setContainingClass(bean.getClass());
     				descriptors[i] = desc;
     				Object arg = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
     				if (arg == null && !this.required) {
     					arguments = null;
     					break;
     				}
     				arguments[i] = arg;
     			}
     			synchronized (this) {
     				if (!this.cached) {
     					if (arguments != null) {
     						this.cachedMethodArguments = new Object[arguments.length];
     						for (int i = 0; i < arguments.length; i++) {
     							this.cachedMethodArguments[i] = descriptors[i];
     						}
     						// 注册所有的参数为bean的依赖方
     						registerDependentBeans(beanName, autowiredBeanNames);
     						if (autowiredBeanNames.size() == paramTypes.length) {
     							Iterator<String> it = autowiredBeanNames.iterator();
     							for (int i = 0; i < paramTypes.length; i++) {
     								String autowiredBeanName = it.next();
     								if (beanFactory.containsBean(autowiredBeanName)) {
     									if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
     										this.cachedMethodArguments[i] = new RuntimeBeanReference(autowiredBeanName);
     									}
     								}
     							}
     						}
     					}
     					else {
     						this.cachedMethodArguments = null;
     					}
     					this.cached = true;
     				}
     			}
     		}
     		if (arguments != null) {
     			// 反射执行方法
     			ReflectionUtils.makeAccessible(method);
     			method.invoke(bean, arguments);
     		}
     	}
     	catch (InvocationTargetException ex) {
     		throw ex.getTargetException();
     	}
     	catch (Throwable ex) {
     		throw new BeanCreationException("Could not autowire method: " + method, ex);
     	}
     }
    

这样所有的@Autowired设置都执行完成,注解方式的依赖注入就通过BeanPostProcessor这种扩展点的方式完成。

转载于:https://my.oschina.net/u/2377110/blog/1358626

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值