热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Spring源码分析(三)@Autowired依赖注入源码分析

Spring里面到底有几种依赖注入的方式呢?1:手动注入1)我们在xml文件中定义一个bean的时候,在bean标签下面使用

Spring里面到底有几种依赖注入的方式呢?

1:手动注入

     1)我们在xml文件中定义一个bean的时候,在bean标签下面使用 代码中提供set方法,把外部对象注入到bean中的方式就是属于手动注入,因为我们要手动的维护这个属性。

     2)也可以在bean标签下面使用构造函数标签,来指定使用那个构造函数来向bean中注入属性。

2:自动注入

     1)XML里面的自动注入

autowire可以选择 byType,byName, constructor default,no

   ----- byType


class="com.my.ioc.pojo.People" autowire="byType"/>

class="com.my.ioc.pojo.factorybean.Bird" />

 

  技术分享图片

 

 people里只提供了brid的set方法。

调用getBean(people)就可以得到注入bird的people实例,

技术分享图片

 

 这种自动注入,就是在填充people属性的时候获取set方法,发现set方法参数也是个bean的时候,就根据这个参数的类的类型来获取对应的bean,然后调用这个set方法,并把参数的bean实例传递进来赋值给当前的属性,完成自动注入。

---- byName

xml中填写的是byName的时候,这个name不是根据属性名,也不是set方法的参数名,而是set方法名,把set去掉之后剩下的首字母小写之后的内容作为beanName来找bean。

----constructor

 构造方法就涉及到到构造方法的选择,选择的逻辑,分析源码的时候具体记录。

--- default

在xml的最上层有个beans标签,可以在那个里面定义default-autowire="byType"  属性,然后可以在下面定义具体的bean的时候用default值,就按照最上层的那个设置来,如果bean标签没有写autorie属性,也是默认按照default-autowire 指定的来。

技术分享图片

-----no

就是不进行自动注入

上篇记录中有看到在填充属性的时候会从从BeanDefinition中获取这个属性值进行判断。 

技术分享图片

 

 

2) @Autowired的自动注入

     注解可以用在的地方:方法,属性上,构造方法。如果使用xml来构造容器的话,这个注解默认是不生效的,需要在xml中开启注解: 

    或者直接使用注解容器。AnnotationConfigApplicationContext

    这个注解其实是上面xml中autowire属性的升级,

    第一个升级的地方就是可以用在属性定义上面,而且注入的过程是先根据byType找到这个类是不是有多个类型,如果找到多个类型再根据属性名byName来找到bean。

    第二个升级的地方就是这个注解可以用在方法上,但是不一定非要用在属性的set方法上,用在任意方法名都可以,只要方法参数是个bean。



 

自动注入的流程:

技术分享图片

 

 

 


自动注入使用到的后置处理器:AutowiredAnnotationBeanPostProcessor

 技术分享图片

 

 上面两个标黄的接口和类,上篇实例化过程中提到了。其中的MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition 是在实例化后执行的一个后置处理器,而上面的这个实现类AutowiredAnnotationBeanPostProcessor

,就在这个方法逻辑里找到注入点进行解析。在 InstantiationAwareBeanPostProcessor.postProcessProperties 方法中进行实际的注入操作。

AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition

技术分享图片

 AutowiredAnnotationBeanPostProcessor继承了InstantiationAwareBeanPostProcessorAdapter重写了里面的postProcessProperties,在这个方法里把上面那个方法找到的注入点进行属性注入。


@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// InjectionMetadata 中保存了所有被@Autowired注解标注的属性/方法 并封装成一个个的InjectedElement
// 在postProcessMergedBeanDefinition 方法里已经得到放到缓存中了
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;
}



 

先从怎么找到注入点的方法进行跟进。

 会把一个bean的注入点封装成一个InjectionMetadata( new InjectionMetadata(clazz, elements))elements为所有的注入点。并缓存到this.injectionMetadataCache 一个Map中,key为beanName。


private InjectionMetadata findAutowiringMetadata(String beanName, Class clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
// 把beanName作为缓存的key
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);
}
//寻找当前class的注入点,把所有注入点整合为一个InjectionMetadata
metadata = buildAutowiringMetadata(clazz);
//放入缓存中
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}

 

buildAutowiringMetadata(clazz)

private InjectionMetadata buildAutowiringMetadata(final Class clazz) {
// 判断是不是候选者类,比如说类名是以 java.开头的则不是候选者类 Order的实现类也不是候选者类
// 但是如果this.autowiredAnnotationTypes 中有以java.开头的注解就返回true了
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List
elements = new ArrayList<>();
Class
targetClass = clazz;
do {
final List currElements = new ArrayList<>();
// 遍历属性,看是否有@Autowired @Value @Inject注解
ReflectionUtils.doWithLocalFields(targetClass, field -> {
MergedAnnotation
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;
}
// 是否required
boolean required = determineRequiredStatus(ann);
// 生成一个注入点AutowiredFieldElement
currElements.add(new AutowiredFieldElement(field, required));
}
});
//遍历所有的方法 看是否有@Autowired @Value @Inject注解
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;
}
//方法参数为0 不能用来注入属性
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 InjectionMetadata.forElements(elements, clazz);
}

 

这个方法首先会判断当前类是否为候选者。this.autowiredAnnotationTypes 中存着可以被识别为注入点的注解:Inject只有在项目中存在的时候才会添加进来,如果没有报错也不会处理。

技术分享图片

 

 候选者的判断条件:


public static boolean isCandidateClass(Class clazz, Collectionextends Annotation>> annotationTypes) {
for (Classextends Annotation> annotationType : annotationTypes) {
if (isCandidateClass(clazz, annotationType)) {
return true;
}
}
return false;
}


public static boolean isCandidateClass(Class clazz, String annotationName) {
// 注解有java开头的注解就算是候选者,但是一般不会有,除非自己添加
if (annotationName.startsWith("java.")) {
return true;
}
// 如果clazz是以java.开头或Order的子类,也不算是候选者
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
return false;
}
return true;
}


static boolean hasPlainJavaAnnotationsOnly(Class type) {
return (type.getName().startsWith("java.") || type == Ordered.class);
}

 



 

判断它是候选者之后,找到候选者中所有的注入点,分为属性和方法。

1:遍历属性,查看属性上面是否有上面说的三种注解的其中之一,有的话就返回。


@Nullable
private MergedAnnotation findAutowiredAnnotation(AccessibleObject ao) {
// 查看当前字段上是否存在@Autowired @Value @Inject注解 存在其中一个则返回,表示可以注入
MergedAnnotations annotatiOns= MergedAnnotations.from(ao);
// autowiredAnnotationTypes 是一个LinkHashSet 所以会按照顺序去判断当前字段中是否有Autowired注解,如果有则返回,
//如果没有则Autowired注解 则判断是否有value注解 再判断是否有Inject注解
for (Classextends Annotation> type : this.autowiredAnnotationTypes) {
MergedAnnotation
annotation = annotations.get(type);
if (annotation.isPresent()) {
return annotation;
}
}
return null;
}

 

   请注意,上面属性注入点,生成的 InjectionMetadata.InjectedElement的子类 AutowiredFieldElement来存储。

2:找方法中的注入点,这里找的是被桥接后的注入点。关于什么是桥接方法,https://blog.csdn.net/mhmyqn/article/details/47342577

     方法的注入点用  InjectionMetadata.InjectedElement的子类  AutowiredMethodElement  来存储。

 把两中element放入elements 中,

最后调用InjectionMetadata.forElements(elements, clazz); 生成InjectionMetadata返回。


public static InjectionMetadata forElements(Collection elements, Class clazz) {
return (elements.isEmpty() ? InjectionMetadata.EMPTY : new InjectionMetadata(clazz, elements));
}

 



 


AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition 找到注入点之后。就 在AutowiredAnnotationBeanPostProcessor.postProcessProperties 方法进行注入。


@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// InjectionMetadata 中保存了所有被@Autowired注解标注的属性/方法 并封装成一个个的InjectedElement
// 在postProcessMergedBeanDefinition 方法里已经得到放到缓存中了
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;
}

 


public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection
checkedElements = this.checkedElements;
Collection
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);
}
// element可能是Method 也可能是Field 会走不同的子类 AutowiredFieldElement AutowiredMethodElement 都在AutowiredAnnotationBeanPostProcessor 内部

element.inject(target, beanName, pvs);
}
}
}

 




属性注入点注入的的逻辑,AutowiredFieldElement.inject  


@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field
= (Field) this.member;
Object value;
if (this.cached) {
// 当前注入点已经注入过了 有缓存了 则利用缓存this.cachedFieldValue找到对应的bean
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
//spring在真正查找属性对应的对象之前 会先将该属性的描述封装成一个DependencyDescriptor 里面存了Field
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set
autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory
!= null, "No BeanFactory available");
TypeConverter typeConverter
= beanFactory.getTypeConverter();
try {
// 根据field去寻找合适的bean
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);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName
= autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
// 这里才是真正的赋值操作
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}

 

第一次注入属性,会执行:value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); 


找到属性对应的bean。  DefaultListableBeanFactory.resolveDependency,


//只负责找对象返回出去,赋值时在外面进行的,比如如果时@Value(xxx) 就把xxx返回出去
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set
autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// DependencyDescriptor 表示一个依赖,可以是一个字段,可以是一个属性字段,可能是一个构造方法参数,可能是一个set方法参数
//根据descriptor去BeanFactory中找到bean
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
//如果依赖类型是Optional
if (Optional.class == descriptor.getDependencyType()) {
// 注入的时候就是 Optional orderservice; 这个方法内部调用的也是doResolveDependency方法只是把返回结果封装成了Optional. orderservice.get()才能得到里面的实例
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.
class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
//在使用@Autowired 注解时 也可以使用@Lazy注解,到时候注入的会是一个代理对象
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
//通过解析descriptor找到bean对象
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}

 

 先看主要获取实例的方法: doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);  自动注入的逻辑最主要逻辑就是找到注入的对象,这个方法就是处理这个逻辑的:


@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set
autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint
= ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
//1: 如果DepenDencyDescriptor是一个 ShortcutDependencyDescriptor
// 那么 会直接理解成beanName从beanfactoryz中拿到一个bean
//在利用@autowired注解来进行依赖注入时会利用shortcutDependencyDescriptor来进行依赖注入的缓存
//表示当解析完某个依赖信息后 会把依赖的bean的beanName缓存起来
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
//获取descriptor具体的类型 某个Filed的类型 或者某个方法参数的类型
Class type = descriptor.getDependencyType();
// 2:如果descriptor上有@Value注解 获取@Value注解中所配置的值 这个resolver是 QualifierAnnotationAutowireCandidateResolver
// AutowireCandidateResolver autowireCandidateResolver = SimpleAutowireCandidateResolver.INSTANCE; 这是默认的resolver,它可以判断某个bean是不是一个自动注入的候选bean
// 比如: xml中定义的bean可以写个 autowire-candidate="false" 把bean排除 不是自动装配的bean
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
// 先进行占位符的填充,解析$符号 $(xxx) spring会从环境变量中获取xxx对应的value进行填充
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd
= (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) :
null);
// 解析Spring EL表达式 解析# 符号 (可以进行运算 可以写某个bean的名字)
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter
= (typeConverter != null ? typeConverter : getTypeConverter());
try {
// 使用类型转换器,转换@Value得到的字符串到type类型
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
// 没有使用@Value注解
//3:要注入的类型是不是一个Map,collection
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//4: 表示会根据type去找bean,Map的key为beanName,Map 的value为对象 (注意可能是bean对象 也可能是某个bean的class对象,因为该方法只负责根据类型找到对应的bean,
// 如果该bean 还没有实例化,那么就返回bean对应的class对象
// 该方法也不负责实例化,只返回该bean对应的Class对象,表示这个Bean也是结果之一)
Map matchingBeans = findAutowireCandidates(beanName, type, descriptor);
// 如果根据类型没有找到bean 如果时必须的则抛出异常 如果不是必须的则直接返回 null
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
//如果找到多个,根据其它参数确定一个返回 {@code @Primary} and {@code @Priority} (in that order)
if (matchingBeans.size() > 1) {
autowiredBeanName
= determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn‘t even look for collection beans).
return null;
}
}
instanceCandidate
= matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName
= entry.getKey();
instanceCandidate
= entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
//如果返回的是Class类型就从beanFactory中getBean
if (instanceCandidate instanceof Class) {
instanceCandidate
= descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result
= instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result
= null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}

 

第一步先判断 descriptor是不是具体的类型,ShortcutDependencyDescriptor 说明已经处理过了,直接从工厂中获取。

第二步,先判断的注解是@Value, 如果存在这个注解就解析,如果解析出来的值能找到类型转换器进行转换,就把结果返回出去。

第三步,判断是不是map和集合的类型,如果是的话就返回相对应的类型实例。

第四步,如果上面都没匹配到结果,就根据类型找到这个的类型的相关bean,封装成一个map返回,Map的key为beanName,Map 的value为对象 (注意可能是bean对象 也可能是某个bean的class对象)

找到候选者bean的逻辑: findAutowireCandidates


// 根据requiredType 找到自动匹配的候选者bean
protected Map findAutowireCandidates(
@Nullable String beanName, Class
requiredType, DependencyDescriptor descriptor) {
// Ancestors 是祖先的意思,这个方法是根据requiredType去当前以及祖先的beanFactory中找这个类型的beanName
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map
result = new LinkedHashMap<>(candidateNames.length);
// 先从 resolvableDependencies 中
for (Map.Entry, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class
autowiringType = classObjectEntry.getKey();
// requiredType 是autowiringType的子类
//requiredType 类是不是继承或实现了autowiringType,autowiringType为父类或接口,子类对象可以赋值给父类属性
if (autowiringType.isAssignableFrom(requiredType)) {
// 是resolvableDependencies中子类所存的对象
Object autowiringValue = classObjectEntry.getValue();
autowiringValue
= AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
//把 resolvableDependencies中保存的对象作为当前属性的一个候选者
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
// 对候选者bean进行过滤,首先候选者不是自己,然后候选者是支持自动注入给其它beand的
for (String candidate : candidateNames) {
// isAutowireCandidate方法中会去判断候选者是否和descriptor匹配 并不是所有bean都是可以进行注入的
// 如果isAutowireCandidate返回的false,也是不会把它作为候选者beanName

if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty()) {
boolean multiple = indicatesMultipleBeans(requiredType);
// Consider fallback matches if the first pass failed to find anything...
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(
!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty() && !multiple) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(
!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}

 

 返回候选者的map之后,如果这个map为空,则直接返回方法结束,如果map中只有一个候选者,那就是需要注入的值就是这个map的value值了。

但是如果Map中有多个候选者,就要从这些候选者中筛选出一个唯一的一个候选者返回。

筛选唯一beanName的方法是:determineAutowireCandidate 。就是判断这个候选者的bean上是否有@Primary  @Priority(注意是有顺序的) ,如果都没有就  根据属性名/方法参数名确定,找到的candidateName 和当前descriptor.getDependencyName 相等就返回


@Nullable
protected String determineAutowireCandidate(Map candidates, DependencyDescriptor descriptor) {
Class
requiredType = descriptor.getDependencyType();
// 取@Primary 的bean
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
// 取优先级最高的bean,通过@Priority来定义优先级 数字越小 优先级越高
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
// 如果根据上面的 @Primary @Priorityd都没找到,就根据属性名/方法参数名从map中获取一个候选beanName
for (Map.Entry entry : candidates.entrySet()) {
String candidateName
= entry.getKey();
Object beanInstance
= entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
// 根据属性名/方法参数名确定,找到的candidateName 和当前descriptor.getDependencyName 相等就返回
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}

 

 



 

根据 找到的autowiredBeanName 从map获取到 instanceCandidate,上面提到过这个实例候选者不一定就是需要注入的对象,可能是Class对象,如果是Class对象,就从beanFactory中获取对象的bean对象返回。

 



 

 在上面找候选者bean的方法 findAutowireCandidates 是一段很重要的逻辑,里面有怎么根据type找到对应的所有的beanName(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager())),  以及怎么判断找到的这些bean是不是可以作为候选者bean(方法isAutowireCandidate)。

 根据类型找到所有的beanName, 就是遍历所有的beanDefinition看对应的类型是不是和type匹配,当然这个过程设计到很多逻辑,因为beanDefinition类型太多了,这里不展开讲了。

根据类型找到的这些beanName还不能直接返回,还要判断是不是可以作为候选者beanName, 这里我们上面提到过,有一个 autowire-candidate 属性如果是false,表示这个bean不能作为候选者让其它bean注入。

技术分享图片

 

 isAutowireCandidate 方法我们点进去看:

1:技术分享图片 2:技术分享图片

3:技术分享图片 在第三个方法中,才调用真正判断是否为候选者。实现类是 QualifierAnnotationAutowireCandidateResolver。



 

1:QualifierAnnotationAutowireCandidateResolver# isAutowireCandidate

首先调用父类的 isAutowireCandidate 方法,如果父类匹配的上再进行自己逻辑的判断,如果父类都不过,则直接false。

技术分享图片

 

 2:父类1  GenericTypeAwareAutowireCandidateResolver# isAutowireCandidate

技术分享图片

 

 3:父类2   SimpleAutowireCandidateResolver# isAutowireCandidate

到这里才是判断 autowire-candidate 属性是否为true的,也就是首先判断这个属性是否为true,如果为false,则这个bean直接认为不是候选者。但是为true了,这个bean也不一定是候选者,还有其它判断。

 技术分享图片

 

 回到父类2中。如果父类3返回true了,执行自己的判断逻辑: checkGenericTypeMatch(bdHolder, descriptor);   这是泛型匹配,也就是注入点可以是泛型。举个例子:


public class Father {
@Autowired
private T t;
public T getT() {
return t;
}
}


@Service
public class Son extends Father {
}


AnnotationConfigApplicationContext applicatiOnContext= new AnnotationConfigApplicationContext(BeanConfig.class);
System.out.println("======================");
Son son
=(Son)applicationContext.getBean("son");
System.out.println(son.getT());

 

 上面的结果是People可以正常被注入到t上面的。

技术分享图片

 

注意如果注入点是个泛型,在上面 findAutowireCandidates  把所有的beanName都找出来了,挨个遍历找到和泛型类型匹配的类型bean。

技术分享图片

 

 

如果没有泛型,这个父类2就返回true了。

走到QualifierAnnotationAutowireCandidateResolver 中的逻辑。这个类自己的逻辑就是匹配@Qualifier注解的。关于这个的作用参考:https://www.cnblogs.com/krock/p/14820404.html  



 


总结:

对于@Autowired ,@Value,@Inject注解标识的注入点,注入的流程:

1:根据注解找到注入点

2:根据注入点进行注入,首先判断的是@Value,如果有@Value注解,就把注解中配置的属性值解析进行注入,这里会有类型转换。

3: 如果没有@Value注解,就先byType,再byName的方式找到唯一的bean进行注入。

4:byType会找到很多类型的beanName出来,先byType到byName中间会经过6步筛选:

1)判断是否为候选者isAutowireCandidate是否为true

2)如果是候选者,判断是否注入点的类型是泛型,如果是泛型执行GenericTypeAwareAutowireCandidateResolver中的逻辑

3)判断注入点是否使用了@Qualifier 注解,如果使用了执行QualifierAnnotationAutowireCandidateResolver 的匹配逻辑

经过上面的三步,得到一个Map,这个Map中数据可能是多个

 4)继续筛选Map中的beanName,判断,beanName对应的bean上面是否有 @Primary注解,如果有的话,直接用这个beanName对应的value值。

5) 如果没有@Primary,判断bean上面是否有@Priority(1/2/3) 优先级,值越小优先级越高。

6)如果上面都没能唯一确认一个bean, 就根据注入点的属性名或方法参数名从Map看是否有对应的key,如果找到了就返回。

 

 

 

 

 


推荐阅读
  • 本文内容为asp.net微信公众平台开发的目录汇总,包括数据库设计、多层架构框架搭建和入口实现、微信消息封装及反射赋值、关注事件、用户记录、回复文本消息、图文消息、服务搭建(接入)、自定义菜单等。同时提供了示例代码和相关的后台管理功能。内容涵盖了多个方面,适合综合运用。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 本文讲述了作者通过点火测试男友的性格和承受能力,以考验婚姻问题。作者故意不安慰男友并再次点火,观察他的反应。这个行为是善意的玩人,旨在了解男友的性格和避免婚姻问题。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
author-avatar
李新绿寧惠_330
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有