Spring全家桶源码解析--2.3 Spring bean 的依赖注入--@Autowired@Value

文章目录

  • 前言
  • 一、@Autowired&@Value:
    • 1.1 @Autowired:
    • 1.2 @Value:
  • 二、依赖注入:
    • 2.1 注入点获取:
    • 2.2 通过 populateBean 入口依赖注入
      • 2.2.1 populateBean :主要通过 postProcessProperties 方法进行依赖注入
      • 2.2.2 postProcessProperties 方法对@Autowired@Value 填充
  • 三、扩展点
    • 3.1 @Primary
    • 3.2 @Qualifier
  • 总结:


前言

在bean完成实例化后之后,还需要对其属性值进行填充。本文介绍@Autowired&@Value 依赖注入


一、@Autowired&@Value:

1.1 @Autowired:

@Autowired是Spring框架提供的一种依赖注入(Dependency Injection)的注解。它可以用于标注在字段、setter方法、构造函数或方法参数上,用于自动装配依赖对象。

@Autowired注解的作用可以总结如下:

(1). 自动装配依赖对象:当使用@Autowired注解标注在一个字段、setter方法、构造函数或方法参数上时,它告诉Spring容器需要自动装配一个对应的依赖对象。

(2). 解决依赖对象冲突:当有多个符合类型的依赖对象可用时,@Autowired注解会尝试根据类型来自动装配对应的依赖对象。如果出现依赖对象冲突,可以使用@Qualifier注解配合@Autowired注解来指定具体要注入的依赖对象。

(3). 支持按照类型匹配和名称匹配:当没有使用@Qualifier注解时,@Autowired注解会首先按照字段类型、方法参数类型或构造函数参数类型进行匹配,如果找到多个符合条件的依赖对象,会再根据字段名、方法名或构造函数参数名称进行匹配。

(4). 方便的依赖注入:使用@Autowired注解可以省去动配置依赖对象的步骤,Spring容器会自动帮助我们解析并装配所需的依赖对象。

需要注意的是,@Autowired解通常与Spring容器中的ApplicationContext一起使用。容器可以根据注解信息自动解析依赖关系,并将对应的依赖对象自动注入到被注解标注的字段、setter方法、构造函数或方法参数中。

1.2 @Value:

@Value是Spring框架提供的一种属性注入的注解。它可以用于标注在字段、setter方法、构造函数或方法参数上,用于注入属性值。

@Value注解的作用可以总结如下:

(1). 注入属性值:当使用@Value注解标注在一个字段、setter方法、构造函数或方法参数上时,它告诉Spring容器需要注入一个指定的属性值。

(2). 从配置文件中读取属性:@Value注解可以用于读取配置文件中的属性值。可以通过${}占位符来引用配置文件中的属性值,并将其注入到被注解标注的字段、setter方法、构造函数或方法参数中。

(3). 注入SpEL表达式值:@Value注解可以用于注入SpEL(Spring Expression Language)表达式值。可以在#{}内使用SpEL表达式,并将计算结果注入到被注解标注的字段、setter方法、构造函数或方法参数中。

(4). 简化配置:使用@Value注解可以省去手动配置属性值的过程,Spring容器会根据注解信息自动将属性值注入到对应的位置。

需要注意的是,@Value注解通常与Spring容器中的ApplicationContext一起使用。容器可以根据注解信息自动解析属性值,并将其注入到注解标注的字段、setter方法、构造函数或方法参数中。另外,@Value注解也支持注入外部化配置属性值,需要配置对应的PropertySourcesPlaceholderConfigurer来解析配置文件中的属性值。

二、依赖注入:

2.1 注入点获取:

通过AutowiredAnnotationBeanPostProcessor的 postProcessMergedBeanDefinition 处理 @Autowired@Value的注入点,在封装后放入到集合中;

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 获取到@Autowired 和@Value 注解的属性和方法的注入点
// 放入到 map 缓存中 private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap(256);
    InjectionMetadata metadata = this.findAutowiringMetadata(beanName, beanType, (PropertyValues)null);
    metadata.checkConfigMembers(beanDefinition);
}

findAutowiringMetadata 注入点获取:

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    String cacheKey = StringUtils.hasLength(beanName) ? beanName : clazz.getName();
    InjectionMetadata metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        synchronized(this.injectionMetadataCache) {
            metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    metadata.clear(pvs);
                }
				// 获取@Autowired 和@Value 注解的属性,然后包装成类记录属性注入点
                metadata = this.buildAutowiringMetadata(clazz);
                this.injectionMetadataCache.put(cacheKey, metadata);
            }
        }
    }

    return metadata;
}

buildAutowiringMetadata 注入点获取:
注解判断:寻找注入点 加了@Autowired 和@Value 注解的属性和方法

private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
    // 如果这个类是基本类 以java. 开头 直接进行返回
   if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
       return InjectionMetadata.EMPTY;
   } else {
       List<InjectionMetadata.InjectedElement> elements = new ArrayList();
       Class<?> targetClass = clazz;

       do {
           List<InjectionMetadata.InjectedElement> fieldElements = new ArrayList();
           // 属性的遍历
           ReflectionUtils.doWithLocalFields(targetClass, (field) -> {
               // 获取到注解
               MergedAnnotation<?> ann = this.findAutowiredAnnotation(field);
               if (ann != null) {
                   if (Modifier.isStatic(field.getModifiers())) {
                      // 注解 的属性是static 直接返回 遍历下一个filed; static 修饰的 是属于类的
                       if (this.logger.isInfoEnabled()) {
                           this.logger.info("Autowired annotation is not supported on static fields: " + field);
                       }

                       return;
                   }
                   // required 属性获取
                   boolean required = this.determineRequiredStatus(ann);
                   fieldElements.add(new AutowiredFieldElement(field, required));
               }

           });

           List<InjectionMetadata.InjectedElement> methodElements = new ArrayList();
              // 方法的遍历 ,遍历处理@Autowired 和@Value 注解的方法
           ReflectionUtils.doWithLocalMethods(targetClass, (method) -> {
              // 如果是桥接方法,则找到被桥接的方法
               Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
               if (BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
				
                   MergedAnnotation<?> ann = this.findAutowiredAnnotation(bridgedMethod);
                   if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {

                       if (Modifier.isStatic(method.getModifiers())) {
                           if (this.logger.isInfoEnabled()) {
                               this.logger.info("Autowired annotation is not supported on static methods: " + method);
                           }

                           return;
                       }

                       if (method.getParameterCount() == 0 && this.logger.isInfoEnabled()) {
                           this.logger.info("Autowired annotation should only be used on methods with parameters: " + method);
                       }

                       boolean required = this.determineRequiredStatus(ann);
                       PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                       methodElements.add(new AutowiredMethodElement(method, required, pd));
                   }

               }
           });
           elements.addAll(0, this.sortMethodElements(methodElements, targetClass));
           elements.addAll(0, fieldElements);
           targetClass = targetClass.getSuperclass();
           // 子类遍历完毕,然后遍历父类
       } while(targetClass != null && targetClass != Object.class);
          // 封装对象并返回
       return InjectionMetadata.forElements(elements, clazz);
   }
}

2.2 通过 populateBean 入口依赖注入

2.2.1 populateBean :主要通过 postProcessProperties 方法进行依赖注入

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    if (bw == null) {
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
    } else {
        if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
            Iterator var4 = this.getBeanPostProcessorCache().instantiationAware.iterator();

            while(var4.hasNext()) {
                InstantiationAwareBeanPostProcessor bp = (InstantiationAwareBeanPostProcessor)var4.next();
                // 先执行bean 的实例化之后方法
                if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    return;
                }
            }
        }
  
        PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;
        int resolvedAutowireMode = mbd.getResolvedAutowireMode();
        if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) {
            MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
            if (resolvedAutowireMode == 1) {
                this.autowireByName(beanName, mbd, bw, newPvs);
            }

            if (resolvedAutowireMode == 2) {
                this.autowireByType(beanName, mbd, bw, newPvs);
            }

            pvs = newPvs;
        }

        boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = mbd.getDependencyCheck() != 0;
        PropertyDescriptor[] filteredPds = null;
        if (hasInstAwareBpps) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }

            PropertyValues pvsToUse;
            for(Iterator var9 = this.getBeanPostProcessorCache().instantiationAware.iterator(); var9.hasNext(); pvs = pvsToUse) {
                InstantiationAwareBeanPostProcessor bp = (InstantiationAwareBeanPostProcessor)var9.next();
				// @Autowired@Value, @Resource 注解的进行属性注入
                pvsToUse = bp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    if (filteredPds == null) {
                        filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                    }

                    pvsToUse = bp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        return;
                    }
                }
            }
        }

        if (needsDepCheck) {
            if (filteredPds == null) {
                filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }

            this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
        }

        if (pvs != null) {
        	// 如果在BeanDefinition 中定义了 bean 的value 进行value 值的填充
            this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
        }

    }
}

2.2.2 postProcessProperties 方法对@Autowired@Value 填充

在这里插入图片描述

populateBean 方法中 postProcessProperties 进行依赖注入:通过AutowiredAnnotationBeanPostProcessor 下postProcessProperties进行属性值的填充:

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
     // 获取缓存的注入点
    InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);

    try {
        // 给注入点 ,设置值
        metadata.inject(bean, beanName, pvs);
        return pvs;
    } catch (BeanCreationException var6) {
        throw var6;
    } catch (Throwable var7) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
    }
}

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 (!((Collection)elementsToIterate).isEmpty()) {
        Iterator var6 = ((Collection)elementsToIterate).iterator();

        while(var6.hasNext()) {
            InjectedElement element = (InjectedElement)var6.next();
           //  属性或者方法进行赋值
            element.inject(target, beanName, pvs);
        }
    }

}

filed 属性的注入 AutowiredFieldElement

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Field field = (Field)this.member;
    Object value;
    if (this.cached) {
        try {
            value = AutowiredAnnotationBeanPostProcessor.this.resolveCachedArgument(beanName, this.cachedFieldValue);
        } catch (BeansException var7) {
            this.cached = false;
            AutowiredAnnotationBeanPostProcessor.this.logger.debug("Failed to resolve cached argument", var7);
            value = this.resolveFieldValue(field, bean, beanName);
        }
    } else {
			// 获取value
        value = this.resolveFieldValue(field, bean, beanName);
    }

    if (value != null) {
        ReflectionUtils.makeAccessible(field);
		// 反射设置value
        field.set(bean, value);
    }

}

resolveFieldValue 获取value:

private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
	// 获取字段依赖描述 @Autowired 的 required 属性获取
    DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
    desc.setContainingClass(bean.getClass());
    Set<String> autowiredBeanNames = new LinkedHashSet(2);
    Assert.state(AutowiredAnnotationBeanPostProcessor.this.beanFactory != null, "No BeanFactory available");
    // bean 的类型转换器获取
    TypeConverter typeConverter = AutowiredAnnotationBeanPostProcessor.this.beanFactory.getTypeConverter();

    Object value;
    try {
       // 通过spring 容器获取bean
        value = AutowiredAnnotationBeanPostProcessor.this.beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    } catch (BeansException 	ar12) {
        throw new UnsatisfiedDependencyException((String)null, beanName, new InjectionPoint(field), var12);
    }

    synchronized(this) {
        if (!this.cached) {
            if (value == null && !this.required) {
                this.cachedFieldValue = null;
            } else {
                Object cachedFieldValue = desc;
                AutowiredAnnotationBeanPostProcessor.this.registerDependentBeans(beanName, autowiredBeanNames);
                if (value != null && autowiredBeanNames.size() == 1) {
                    String autowiredBeanName = (String)autowiredBeanNames.iterator().next();
                    if (AutowiredAnnotationBeanPostProcessor.this.beanFactory.containsBean(autowiredBeanName) && AutowiredAnnotationBeanPostProcessor.this.beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                        cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName);
                    }
                }

                this.cachedFieldValue = cachedFieldValue;
                this.cached = true;
            }
        }

        return value;
    }
}

method 方法的注入 AutowiredMethodElement

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    if (!this.checkPropertySkipping(pvs)) {
		// 没有在beandefintion 中为其设置 值,则进入
        Method method = (Method)this.member;
        Object[] arguments;
        if (this.cached) {
            try {
                arguments = this.resolveCachedArguments(beanName, this.cachedMethodArguments);
            } catch (BeansException var8) {
                this.cached = false;
                AutowiredAnnotationBeanPostProcessor.this.logger.debug("Failed to resolve cached argument", var8);
                arguments = this.resolveMethodArguments(method, bean, beanName);
            }
        } else {
           // 获取多个参数的的bean
            arguments = this.resolveMethodArguments(method, bean, beanName);
        }

        if (arguments != null) {
            try {
                ReflectionUtils.makeAccessible(method);
                // 反射执行
                method.invoke(bean, arguments);
            } catch (InvocationTargetException var7) {
                throw var7.getTargetException();
            }
        }

    }
}

resolveMethodArguments 获取方法的参数值:

@Nullable
private Object[] resolveMethodArguments(Method method, Object bean, @Nullable String beanName) {
	// 这个方法有几个参数
    int argumentCount = method.getParameterCount();
    // 存放对应参数的结果bean
    Object[] arguments = new Object[argumentCount];
    DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
    Set<String> autowiredBeanNames = new LinkedHashSet(argumentCount * 2);
    Assert.state(AutowiredAnnotationBeanPostProcessor.this.beanFactory != null, "No BeanFactory available");
    TypeConverter typeConverter = AutowiredAnnotationBeanPostProcessor.this.beanFactory.getTypeConverter();
     // 遍历入参
    for(int ix = 0; ix < arguments.length; ++ix) {
         // 封装方法参数占位符
        MethodParameter methodParam = new MethodParameter(method, ix);
       // 方法参数依赖描述
        DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
        currDesc.setContainingClass(bean.getClass());
        descriptors[ix] = currDesc;

        try {
              // 向spring 容器获取bean
            Object arg = AutowiredAnnotationBeanPostProcessor.this.beanFactory.resolveDependency(currDesc, beanName, autowiredBeanNames, typeConverter);
            if (arg == null && !this.required) {
                arguments = null;
                break;
            }

            arguments[ix] = arg;
        } catch (BeansException var17) {
            throw new UnsatisfiedDependencyException((String)null, beanName, new InjectionPoint(methodParam), var17);
        }
    }

    synchronized(this) {
        if (!this.cached) {
            if (arguments != null) {
                DependencyDescriptor[] cachedMethodArguments = (DependencyDescriptor[])Arrays.copyOf(descriptors, argumentCount);
                AutowiredAnnotationBeanPostProcessor.this.registerDependentBeans(beanName, autowiredBeanNames);
                if (autowiredBeanNames.size() == argumentCount) {
                    Iterator<String> it = autowiredBeanNames.iterator();
                    Class<?>[] paramTypes = method.getParameterTypes();

                    for(int i = 0; i < paramTypes.length; ++i) {
                        String autowiredBeanName = (String)it.next();
                        if (arguments[i] != null && AutowiredAnnotationBeanPostProcessor.this.beanFactory.containsBean(autowiredBeanName) && AutowiredAnnotationBeanPostProcessor.this.beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
                            cachedMethodArguments[i] = new ShortcutDependencyDescriptor(descriptors[i], autowiredBeanName);
                        }
                    }
                }

                this.cachedMethodArguments = cachedMethodArguments;
                this.cached = true;
            } else {
                this.cachedMethodArguments = null;
            }
        }

        return arguments;
    }
}
}

resolveDependency 最终都通过改方法获取bean:

@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
   // 初始化 方法参数/属性 名称的 发现其
    descriptor.initParameterNameDiscovery(this.getParameterNameDiscoverer());
    if (Optional.class == descriptor.getDependencyType()) {
        return this.createOptionalDependency(descriptor, requestingBeanName);
    } else if (ObjectFactory.class != descriptor.getDependencyType() && ObjectProvider.class != descriptor.getDependencyType()) {
        if (javaxInjectProviderClass == descriptor.getDependencyType()) {
            return (new Jsr330Factory()).createDependencyProvider(descriptor, requestingBeanName);
        } else {
             // 如果有lazy 注解 则返回一个代理对象,没有lazy 注解则返回null
            Object result = this.getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
            if (result == null) {
                 // 非lazy的依赖注入
                result = this.doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
            }

            return result;
        }
    } else {
        return new DependencyObjectProvider(descriptor, requestingBeanName);
    }
}

getLazyResolutionProxyIfNecessary :
ContextAnnotationAutowireCandidateResolver 下的getLazyResolutionProxyIfNecessary 如过被@Lazy 注解标注,返回一个代理对象,等到改对象真正被使用的时候才去获取到真正的bean

@Nullable
public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
		// 有lazy 注解 通过buildLazyResolutionProxy获取一个代理对象,没有返回null
       //  有lazy 注解 当真正使用的时候 在从spring 容器中获取到对应的bean 然后使用
    return this.isLazy(descriptor) ? this.buildLazyResolutionProxy(descriptor, beanName) : null;
}

isLazy 判断是否懒加载:

protected boolean isLazy(DependencyDescriptor descriptor) {
    Annotation[] var2 = descriptor.getAnnotations();
    int var3 = var2.length;

    for(int var4 = 0; var4 < var3; ++var4) {
        Annotation ann = var2[var4];
        Lazy lazy = (Lazy)AnnotationUtils.getAnnotation(ann, Lazy.class);
        if (lazy != null && lazy.value()) {
            return true;
        }
    }

    MethodParameter methodParam = descriptor.getMethodParameter();
    if (methodParam != null) {
        Method method = methodParam.getMethod();
        if (method == null || Void.TYPE == method.getReturnType()) {
            Lazy lazy = (Lazy)AnnotationUtils.getAnnotation(methodParam.getAnnotatedElement(), Lazy.class);
            if (lazy != null && lazy.value()) {
                return true;
            }
        }
    }

    return false;
}

doResolveDependency 处理非懒加载的bean进行注入:

@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);

    Object var23;
    try {
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
            Object var20 = shortcut;
            return var20;
        }

        Class<?> type = descriptor.getDependencyType();
		// 获取@Value 注解的值
        Object value = this.getAutowireCandidateResolver().getSuggestedValue(descriptor);
        Object var11;
        if (value == null) {
			//  根据bean 的类型和名字获取bean
			// 如果使用 Map<String,UserSerivce> 或者List <UserService>则会 拿到UserService 类型的多个bean
			// 注意Map 的key 必须是String 因为key 为bean 的名称
			// List的泛型为Object 会拿到所有的bean ,如果是<T> 则拿不到bean
			// bean name 获取的筛选责任链:
			// 1 SimpleAutowireCandidateResolver检查BeanDefinition的autowireCandidate属性,为true表示通过筛选
			// 2 GenericTypeAwareAutowireCandidateResolver检查BeanDefinition的beanClass属性和当前注入点的type是否匹配,
			// 匹配则通过筛选
			// 3 QualifierAnnotationAutowireCandidateResolvel检查BeanDefinition的qualifier属性
			// 和当前注入点的qualifier属性是否匹配,匹配则通过筛选
            Object multipleBeans = this.resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			// 如果不是Map /List /Array 则multipleBeans 为null, 为普通的对象注入
            if (multipleBeans != null) {
				// 如果获取到了bean 则直接返回
                var23 = multipleBeans;
                return var23;
            }
             // 根据类型获取得到多个bean key 为bean 的名称,value 为bean对象或者bean 的class
            Map<String, Object> matchingBeans = this.findAutowireCandidates(beanName, type, descriptor);
            if (matchingBeans.isEmpty()) {
                 // 根据类型没有获取到bean 并且required 为true 则报错
                if (this.isRequired(descriptor)) {
                    this.raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                }

                var11 = null;
                return var11;
            }

            Object instanceCandidate;
            Object result;
            String autowiredBeanName;
            if (matchingBeans.size() > 1) {
               //根据类型获取到多个bean ,需要根据名称再次进行过滤
                autowiredBeanName = this.determineAutowireCandidate(matchingBeans, descriptor);
                if (autowiredBeanName == null) {
                      // 如果按照名称没有找到,它的required 是true 则报错
                    if (!this.isRequired(descriptor) && this.indicatesMultipleBeans(type)) {
                        result = null;
                        return result;
                    }

                    result = descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
                    return result;
                }
                 // 根据bean 的名称获取到bean
                instanceCandidate = matchingBeans.get(autowiredBeanName);
            } else {
                Map.Entry<String, Object> entry = (Map.Entry)matchingBeans.entrySet().iterator().next();
                autowiredBeanName = (String)entry.getKey();
                instanceCandidate = entry.getValue();
            }

            if (autowiredBeanNames != null) {
                autowiredBeanNames.add(autowiredBeanName);
            }
             // 如果现在的bean 还只是class 则创建这个bean
            if (instanceCandidate instanceof Class) {
                instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
            }

            result = instanceCandidate;
            if (instanceCandidate instanceof NullBean) {
                if (this.isRequired(descriptor)) {
                    this.raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                }

                result = null;
            }

            if (!ClassUtils.isAssignableValue(type, result)) {
                throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
            }

            Object var14 = result;
            return var14;
        }

        if (value instanceof String) {
              // value 占位符 @Value("${xxx.test}")   获取key 为xxx.test 的value值
             // 如果是@Value("#{userService}") # 的表达式 返回#{userService}"
            String strVal = this.resolveEmbeddedValue((String)value);
            BeanDefinition bd = beanName != null && this.containsBean(beanName) ? this.getMergedBeanDefinition(beanName) : null;
             // 表达式解析 向spring获取 userService 的bean
            value = this.evaluateBeanDefinitionString(strVal, bd);
        }

        TypeConverter converter = typeConverter != null ? typeConverter : this.getTypeConverter();

        try {
             // 如果类型转换器,则使用转换器 对value 进行转换
            var23 = converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
        } catch (UnsupportedOperationException var18) {
            var11 = descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter());
            return var11;
        }
    } finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }

    return var23;
}

determineAutowireCandidate 多个相同类型的bean 进行名称的过滤:


@Nullable
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
    Class<?> requiredType = descriptor.getDependencyType();
    // 先看下这些bean 有没有被@Primary 注解标识,标注多个报错
    String primaryCandidate = this.determinePrimaryCandidate(candidates, requiredType);
    if (primaryCandidate != null) {
        return primaryCandidate;
    } else {
         // 获取优先级最高的bean   通过@Priority 类的注解 多个@Priority  值一样则报错
        String priorityCandidate = this.determineHighestPriorityCandidate(candidates, requiredType);
        if (priorityCandidate != null) {
            return priorityCandidate;
        } else {
              // 按照bean的名称 获取一个并返回
            Iterator var6 = candidates.entrySet().iterator();

            String candidateName;
            Object beanInstance;
            do {
                if (!var6.hasNext()) {
                    return null;
                }

                Map.Entry<String, Object> entry = (Map.Entry)var6.next();
                candidateName = (String)entry.getKey();
                beanInstance = entry.getValue();
            } while((beanInstance == null || !this.resolvableDependencies.containsValue(beanInstance)) && !this.matchesBeanName(candidateName, descriptor.getDependencyName()));

            return candidateName;
        }
    }
}

三、扩展点

3.1 @Primary

@Primary 是 Spring 框架中的一个注解,用于指定在存在多个候选者时首选的 bean 实例。

当存在多个相同类型的 bean 实例需要被注入时,使用 @Primary 注解标注的 bean 实例将被视为首选的实例,优先被注入。

使用方法:

  1. 定义多个相同类型的 bean 实例,并在其中一个实例上添加 @Primary 注解。
@Component
@Primary
public class PrimaryBean implements MyBean {
    // ...
}

@Component
public class AnotherBean implements MyBean {
    // ...
}
  1. 在需要注入的地方使用对应的类型进行注入。
@Component
public class MyComponent {
    @Autowired
    private MyBean bean;
    
    // ...
}

在上面的示例中,PrimaryBean 类上使用了 @Primary 注解,意味着它是首选的 bean 实例。当需要注入 MyBean 类型的实例时,会优先选择注入 PrimaryBean 实例。这样就可以通过 @Primary 注解指定首选的 bean 实例,解决多个候选者的注入歧义。

3.2 @Qualifier

@Qualifier 是 Spring 框架中的一个注解,用于解决依赖注入时的歧义性问题。当存在多个类型一致的 bean 实例可供选择时,可以通过 @Qualifier 注解进行标识,以明确指定要注入的 bean 实例。

通常情况下,@Qualifier 注解与其他注解(如 @Autowired@Resource)共同使用,用于指定具体要注入的 bean例。

使用方法:

  1. 定义多个相同类型的 bean 实例,并添加对应的 @Qualifier 注解标识符,可以是类名首字母小写的形式。
@Component
@Qualifier("beanA")
public class BeanA implements MyBean {
    // ...
}

@Component
@Qualifier("beanB")
public class BeanB implements MyBean {
    // ...
}
  1. 在需要注入的地方使用 @Qualifier 注解指定要注入的具体 bean 实例。
@Component
public class MyComponent {
    @Autowired
    @Qualifier("beanA")
    private MyBean bean;
    
    // ...
}

在上面的示例中,通过 @Qualifier("beanA") 指定要注入的 bean 实例为标识符为 “beanA” 的 BeanA 类。这样就可以解决依赖注入时的歧义性问题,确保正确注入指定的 bean 实例。

总结:

在bean 实例化之后 通过populateBean 对属性和方法的入参进行依赖注入,首先扫描记录哪些属性和方法需要进行依赖注入,AutowiredAnnotationBeanPostProcessor 的 postProcessMergedBeanDefinition @Autowired 和@Value 注解的属性和方法的注入点;
然后遍历完成注入,通过AutowiredAnnotationBeanPostProcessor 进行完成@Autowired 和@Value的依赖注入;

@Autowired 和@Value 依赖注入: AutowiredFieldElement 和AutowiredMethodElement 分别对属性和方法的入参进行依赖注入

DefaultListableBeanFactory.doResolveDependency 方法中首先对@Value 进行处理:

  • 如果使用@Value(" x x x " ) 使用 {xxx}") 使用 xxx")使用 符号则解析到xxx 对应的value 值,然后判断是否有类型转换器,有的话则进行转换在赋值,没有直接赋值,如果类型错误则报错;
  • 如果使用@Value(“#{xxx}”) 使用$ 符号则解析到xxx 对应的value 值,然后在容器中寻找对应xxx 的bean ,找到后进行赋值,找不到则报错;

@Value 处理之后,获取到该类型的所以bean,获取的过程:

  • SimpleAutowireCandidateResolver检查BeanDefinition的autowireCandidate属性,为true表示通过筛选;可以通过在bean的@Autowired注解中设置required属性来控制,默认情况下,required属性的值为true,表示该bean是必需进行自动装配的。如果没有找到匹配的依赖项,则会抛出NoSuchBeanDefinitionException异常。要将required属性设置为false,表示该依赖项是可选的,如果找不到匹配的依赖项,Spring会将该字段设置为null,而不会抛出异常 ;
  • GenericTypeAwareAutowireCandidateResolver检查BeanDefinition的beanClass和当前注入点的type是否匹配,匹配则通过筛选;
  • QualifierAnnotationAutowireCandidateResolver检查BeanDefinition的qualifier属性值和当前注入点的qualifier属性值是否匹配,匹配则通过筛选
  • 把筛选之后的bean添加到一个Map中key为beanName,value为bean对象,如果Map中有多个Bean,继续进行筛选;
  • 从多个Bean中获取被@Primary注解标注的Bean;
  • 从多个Bean中获取优先级最高的Bean;
  • 从多个Bean中获取注入点name对应的bean;
  • 通过反射进行属性赋值或方法调用;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/143280.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL数据库入门到大牛_基础_07__单行函数

文章目录 1. 函数的理解1.1 什么是函数1.2 不同DBMS函数的差异1.3 MySQL的内置函数及分类 2. 数值函数2.1 基本函数2.2 角度与弧度互换函数2.3 三角函数2.4 指数与对数2.5 进制间的转换 3. 字符串函数4. 日期和时间函数4.1 获取日期、时间4.2 日期与时间戳的转换4.3 获取月份、…

Shell脚本 CPU,内存,磁盘占用率检测

CPU&#xff1a;运算资源占用 内存&#xff1a;RAM类介质 磁盘&#xff1a;ROM类介质 一、CPU #!/bin/bash# 设置阈值&#xff0c;当CPU占用超过该阈值时进行输出提示 threshold80while true do# 使用top命令获取CPU占用信息&#xff0c;并使用grep和awk筛选和解析输出结果…

Python机器学习基础(三)---数据预处理

一.数据预处理作用 数据预处理会将选定的数据转换为我们可以使用的形式或可以提供给ML算法的形式&#xff0c;以使其符合机器学习算法的期望。 二.数据处理的常用方法 1.规范化 数据规范化是使属性数据按比例缩放&#xff0c;这样就将原来的数值映射到一个新的特定区域中&#…

使用gitflow时如何合并hotfix

前言 在使用 git flow 流程时, 对于项目型的部署项目经常会遇到一个问题, 就是现场项目在使用历史版本时发现的一些问题需要修复, 但升级可能会有很大的风险或客户不愿意升级, 这时就要求基于历史版本进行 hotfix 修复. 基于历史发布版本的缺陷修复方式不同于最新发布版本的补…

适配器模式 ( Adapter Pattern )(6)

适配器模式 ( Adapter Pattern ) 适配器模式&#xff08;Adapter Pattern&#xff09;是作为两个不兼容的接口之间的桥梁 适配器模式涉及到一个单一的类&#xff0c;该类负责加入独立的或不兼容的接口功能 举个真实的例子&#xff0c;读卡器是作为内存卡和笔记本之间的适配器…

应用亚马逊云科技,Share Creators1个月内上线生成式AI生图模块

随着生成式AI在全球范围爆火&#xff0c;如何充分利用生成式AI自动生成内容提高创作效率已成为设计领域创新的关键突破口。对于设计行业和游戏行业的众多企业和团队而言&#xff0c;管理数字资产的能力是其实现高效创作最大的挑战之一&#xff0c;也是在降本增效的流程中非常容…

自己搭设开源密码管理工具 bitwarden

简介 Bitwarden是一款自由且开源的密码管理服务&#xff0c;用户可在加密的保管库中存储敏感信息&#xff08;例如网站登录凭据&#xff09;。Bitwarden平台提供有多种客户端应用程序&#xff0c;包括网页用户界面、桌面应用&#xff0c;浏览器扩展、移动应用以及命令行界面。[…

【Linux网络】1分钟使用shell脚本完成DNS主从解析服务器部署(适用于centos主机)

DNS正向解析主从解析服务器脚本 1、脚本内容 主服务器脚本 #!/bin/bash ##先修改本地DNS缓存服务器 read -p "请输入主服务器ip地址&#xff1a;" masterIP sed -i /DNS/d /etc/sysconfig/network-scripts/ifcfg-ens33 echo "DNS$masterIP" >> /e…

干洗店管理系统洗鞋店小程序开发搭建;

干洗店管理软件&#xff0c;实现从门店收衣到工厂洗涤&#xff0c;全程数字化监控&#xff0c;操作简单易用。客户在线下单&#xff0c;商家通过物流App完成上门取件&#xff0c;提升用户体验的同时&#xff0c;提高运营效率。 洗衣软件打造专属于每个商户的小程序&#xff0c;…

MySQL-事务

什么是事务 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 事务的特性 (ACID) 原子性(Atomicity)&#xff1a;事务是不…

稳定扩散与潜伏扩散:哪个更好?

在线工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 3D数字孪生场景编辑器 本文对这两种类型的扩散、它们的工作原理、差异和未来影响进行了详细讨论。 了解稳定扩散 通过稳定扩散生成的图像 Stable Diffu…

RabbitMQ 核心部分之简单模式和工作模式

文章目录 一、Hello World&#xff08;简单&#xff09;模式1.导入依赖2.消息生产者3.消息消费者 二、Work Queues&#xff08;工作&#xff09;模式1.抽取工具类2.启动两个工作线程3.启动一个发送线程4.结果 总结 一、Hello World&#xff08;简单&#xff09;模式 在下图中&…

内衣洗衣机和手洗哪个干净?好用的内衣洗衣机推荐

在日常生活中&#xff0c;我们的衣服不可避免地会沾染上各种细菌、毛发和污渍&#xff0c;将它们与贴身衣物混合清洗&#xff0c;很容易发生交叉感染&#xff0c;而被感染后&#xff0c;贴身衣物也有可能导致我们人体引起皮肤病。这也是为什么大部分人都喜欢用手洗的原因&#…

SA实战 ·《SpringCloud Alibaba实战》第13章-服务网关:项目整合SpringCloud Gateway网关

大家好,我是冰河~~ 一不小心[SpringCloud Alibaba实战》专栏都更新到第13章了,再不上车就跟不上了,小伙伴们快跟上啊! 在《SpringCloud Alibaba实战》专栏前面的文章中,我们实现了用户微服务、商品微服务和订单微服务之间的远程调用,并且实现了服务调用的负载均衡。也基于…

MBTI职业性格测试,用于职业选择是否靠谱

关于性格测试的看法 所有人都会说我了解自己的性格&#xff01;但真的了解吗&#xff1f;性格有外在表现&#xff0c;也有内因的驱动&#xff0c;我们通常感受到的是性格的外在表现.... 性格测试&#xff0c;是针对有想法要改变自己和提高自己的人&#xff0c;如果你一个懒字…

cubemx为啥在SPI配置时将MISO设置为AFPP,而不是输入模式

一般来说在配置SPI的时候&#xff0c;SCK、MOSI、NSS&#xff1a;通常配置为推挽输出模式&#xff0c;在单主机模式下&#xff0c;可以将NSS引脚配置为GPIO输出&#xff0c;MISO通常需要配置为浮空输入或上拉输入模式&#xff0c;但是cubemx却其配置成推挽输出模式&#xff0c;…

多模态及图像安全的探索与思考

前言 第六届中国模式识别与计算机视觉大会&#xff08;The 6th Chinese Conference on Pattern Recognition and Computer Vision, PRCV 2023&#xff09;已于近期在厦门成功举办。通过参加本次会议&#xff0c;使我有机会接触到许多来自国内外的模式识别和计算机视觉领域的研究…

janus 安装部署

本文使用docker进行安装&#xff0c;还没有安装docker和docker-compose的&#xff0c;请自行安装&#xff0c;这里就不介绍了 环境 janus-gateway镜像版本:anyan/janus-gateway:0.10.7 linux版本: Ubuntu 18.04.6 LTS coturn/coturn 镜像版本: coturn/coturn:latest 镜像ID 8…

觉非科技发布【轻地图高速NOA智驾方案】|地平线,觉非科技,MobileDrive超捷生态协作实现技术落地

11月10日&#xff0c;2023世界新汽车技术合作生态展期间&#xff0c;觉非科技正式发布了基于地平线征程系列以及MobileDrive超捷规控系统的【轻地图高速NOA智驾解决方案】。该方案首次实现了从芯片能力输出、到数据闭环建设、再到规控部署的产业生态链协作与打通&#xff0c;为…

员工电脑监控的方法有哪些

有人在后台问&#xff0c;员工电脑监控的方法有哪些&#xff1f; 其实主要包括以下几方面&#xff1a;1&#xff09;安装监控软件 2&#xff09;使用操作系统自带的工具 3&#xff09;部署网络监控设备 4&#xff09;定期检查电脑 5&#xff09;制定严格的规章制度 因为内容比…