003-依赖注入、属性赋值源码分析

目录

    • 引入
    • 作用
    • 代码分析
    • InstantiationAwareBeanPostProcessor#postProcessProperties()
      • AutowiredAnnotationBeanPostProcessor
        • 查找注入点元数据
        • 给注入点注入属性

引入

之前我们了解到BeanDefinition到Bean,经历了

  1. 实例化
  2. 属性赋值
  3. 初始化
    3个步骤现在详细分析下属性赋值:populateBean(beanName, mbd, instanceWrapper);

作用

就是查找Bean内字段或者方法上是否有@Autowired
如果有则从 context中查找并赋值,完成依赖注入

代码分析

其实就是解析各种依赖存入 getPropertyValues 缓存(相当于一个Map)
最后在统一反射到属性中

beanName – the name of the bean 
mbd – the bean definition for the bean 
bw – the BeanWrapper with bean instance
populateBean(beanName, mbd, instanceWrapper);

ropertyValues pvs = mbd.getPropertyValues();

//可以这样设置@Bean(autowire = Autowire.BY_NAME)
//这里只是解析 但是并没有真的设置 设值在最后一行
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || AUTOWIRE_BY_TYPE) {
	创建一个缓存 newPvs
	//意思是Bean的属性注入自动根据其Setter的名字或者属性
	if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
		newPvs.put(属性的名字(propertyName), getBean(propertyName));
	}
	//也可以 Autowire.BY_TYPE 就是根据Setter 参数的类型
	if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
		newPvs.put(属性的名字(propertyName), getBean(属性Setter的参数的类型));
	}
	pvs = newPvs;
}
//注意:这个方式已经被标记为过时的 因为这样调试起来很麻烦 而且不是很方便推荐还是@Autowired

遍历处理器 InstantiationAwareBeanPostProcessor bp {
	pvs = bp.postProcessProperties();
}

//根据pvs给对象设值
if (pvs != null) {
	//这里最终也是通过反射把值设置到字段中BeanWrapperImpl.BeanPropertyHandler#setValue
	applyPropertyValues(beanName, mbd, bw, pvs);
}

InstantiationAwareBeanPostProcessor#postProcessProperties()

这个处理器就是用来专门处理Bean的属性的

AutowiredAnnotationBeanPostProcessor

这个处理器实现就是专门处理@Autowired之类的逻辑
初始化的时候autowiredAnnotationTypes设置了

  1. Autowired.class
  2. Value.class
  3. javax.inject.Inject
postProcessProperties():

//查找注入点元数据
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
//给注入点注入属性
metadata.inject(bean, beanName, pvs);

查找注入点元数据

findAutowiringMetadata():

//这里metadata 其实已经有值了
//在 MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
//其实就进入了AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
//在buildAutowiringMetadata()就把带注解的字段和方法解析完了
//并设置到injectedElements字段中
//最后 this.injectionMetadataCache.put(cacheKey, new InjectionMetadata(clazz, injectedElements)));
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (metadata == null) {
	metadata = buildAutowiringMetadata(clazz);
	this.injectionMetadataCache.put(beanName, );
}
//这里就是构建元数据
//构建元数据的前提是有需要注入的点 如果有则创建一个AutowiredFieldElement加入currElements
buildAutowiringMetadata(clazz):

遍历所有的字段(field) {
	if(带有4个注解之一) {
		currElements.add(new AutowiredFieldElement(field, required));
	}
}

遍历所有方法(method){
	if(带有4个注解之一) {
		PropertyDescriptor pd = 这个方法是否是某个字段的读写
		currElements.add(new AutowiredMethodElement(method, required, pd));
	}
}

return new InjectionMetadata(currElements, clazz);

给注入点注入属性

AutowiredFieldElement#inject

//找到字段的值
value = resolveFieldValue(field, bean, beanName);
//反射
if (value != null) {
	ReflectionUtils.makeAccessible(field);
	field.set(bean, value);
}
resolveFieldValue(field, bean, beanName):

//包装成统一的描述符
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
//找到值
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);

return value;
resolveDependency(desc, beanName, autowiredBeanNames, typeConverter):

//设置参数Name发现器
//1. -parameters java8 编译带了这个参数就能获取参数的name
//2. 本地变量表 基于ASM技术
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (类型不是 ObjectFactory || Optional) {
	if(依赖带有@Lazy) {
		return 对名称和依赖进行代理(在用的时候再查找注入);
	} 
	
	return doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter):

if (descriptor储存了快速解析出来的对象) {
	return shortcut;
}

Object value = 查找依赖是否有@Value, 并获取值
if (value != null && value instanceof String) {
	//解析 ${} 配置内容并获取值
	//计算解析不到也把#Value的值读取出来 后续el表达式解析
	String strVal = resolveEmbeddedValue((String) value);
	value = evaluateBeanDefinitionString(strVal, bd);
	return 类型转化(value);
}

//这里就是判断依赖是否是复数的 下边的Object只是指代对象 不是特定的类型
//Map 会注入 BeanName : 符合要求的Bean对象 作为map的entry
//List 和 Object[] 会直接注入符合要求的所有Bean对象
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
	return multipleBeans;
}

//根据类型查找所有的符合要求的实例
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans 为空) {
	if (isRequired) {
		throw new NoSuchBeanDefinitionException()
	} 
	return null;
}

//确定依赖的实例和名称
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
	autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
	if (autowiredBeanName != null) {
		throw new NoUniqueBeanDefinitionException();
	}
	instanceCandidate = matchingBeans.get(autowiredBeanName);
} else {
	Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
	autowiredBeanName = entry.getKey();
	instanceCandidate = entry.getValue();
}

Object result = instanceCandidate;
//这个就是自己@Bean方法返回null 就会被处理成 NullBean 这样不需要到处判空
if (result instanceof NullBean) {
	if (isRequired(descriptor)) {
		throw new NoSuchBeanDefinitionException();
	}
	result = null;
}
//确定是否符合要求的类型 在getBean(beanName, Class)方法中
//第二个参数就是用来在这里做校验的 会判断找出的实例类型是否符合要求
if (!ClassUtils.isAssignableValue(type, result)) {
	throw new BeanNotOfRequiredTypeException();
}
return result;

 
  
findAutowireCandidates(beanName, requiredType, dependencyDescriptor):

Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
//根据类型获取所有的 候选名称
//其实就是 beanFactory中 
//遍历 this.beanDefinitionNames 获取name mergedBeanDefinitions.get(beanName) 获取 RootBeanDefinition 
//其中 RootBeanDefinition 是用来提前判断是否符合要求
//matchFound = isTypeMatch(beanName, requiredType, true);
//matchFound == trur 就符合要求
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
				this, requiredType, true, descriptor.isEager());
				
判断 resolvableDependencies 中是否有符合requiredType的对象

遍历 candidateNames {
	if(不是自依赖 && isAutowireCandidate(candidate, descriptor)) {
		candidates.put(candidateName, getSingleton(beanName, false).getClass());
	}
}

//再次判断一下是否符合要求
isAutowireCandidate(candidate, descriptor)if (候选Definition.isAutowireCandidate() && 依赖的类型是一个 class) {
	match = true; 
	//检查 @Qualifier 没配置返回true
	match = checkQualifiers(bdHolder, dependencyType.getType() instanceof Class);
	if (match)) {
		//检查 @Qualifier 没配置返回true
		match = checkQualifiers(bdHolder, descriptor.getMethodAnnotations();
	}
	return match;
}
//在查找到多个 候选实例的时候 确定一个最终的实例
determineAutowireCandidate(matchingBeans, descriptor):

String primaryBeanName;
//解析 @Primary
遍历 candidates : candidateBeanName{
	if (@Primary) {
		if (primaryBeanName != null) {
			throw new NoUniqueBeanDefinitionException();
		}
		primaryBeanName = candidateBeanName;
	}
}
if (primaryBeanName != null) {
	return primaryBeanName;
}
//解析 @javax.annotation.Priority
Integer highestPriority = null;
遍历 candidates : candidateBeanName{
	if (@javax.annotation.Priority) {
		Integer thisPriority = Priority(value);
		if (thisPriority  == null) {
			continue;
		}
		if (highestPriority != null && highestPriority == thisPriority ) {
			throw new NoUniqueBeanDefinitionException();
		}
		if (highestPriority == null || highestPriority < thisPriority  ) {
			highestPriority = thisPriority;
			primaryBeanName = candidateBeanName;
		}
	}
}
if (primaryBeanName != null) {
	return primaryBeanName;
}

遍历 candidates : candidateBeanName{
	//这个缓存里有4个可直接解析的实例
	//{Class@501}"interface org.springframework.core.io.ResourceLoader" -> {AnnotationConfigApplicationContext@1779}
	//{Class@508}"interface org.springframework.context.ApplicationEventPublisher" -> {AnnotationConfigApplicationContext@1779}
	//{Class@510}"interface org.springframework.context.ApplicationContext" -> {AnnotationConfigApplicationContext@1779}
	//{Class@504}"interface org.springframework.beans.factory.BeanFactory" -> {DefaultListableBeanFactory@1475}
	if (this.resolvableDependencies.containsValue(beanInstance)) {
		return candidateName;
	}
	//这里就是判断字段或者参数名称 是否和BeanName一致
	if (matchesBeanName(candidateName, descriptor.getDependencyName()) {
		return candidateName;
	}
}

你可能感兴趣的:(spring,spring,java,spring,boot)