SpringBean生命周期之属性注入篇

注意事项

阅读本文需要有一定的基础,并且要跟着调用链走,不然会很容易懵圈。

环境

Spring Framework Version:5.3.x

Gradle Version:7.5.1

前言

内容比较干,要有点耐心哈~

源码解析

AbstractAutowireCapableBeanFactory

populateBean

  1. 如果bean实例为null,那么跳过填充属性阶段
  2. 在属性注入之前回调instantiationAware里的各种后置处理器
  3. 根据byName、byType查找属性值
  4. @Resource、@Autowired注解注入
  5. 进行set、byType、byName的属性注入(注意:最后这里才是真正的注入,前面只是查找属性值)
/**
 *
 * 属性填充
 * param beanName bean名称
 * param mbd bean定义
 * param bw bean包装器
 *
 */
@SuppressWarnings("deprecation")  // for postProcessPropertyValues
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 {
            // Skip property population phase for null instance.
            return;
        }
    }

    //在属性注入之前回调instantiationAware后置处理器
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                return;
            }
        }
    }

    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    //byName、byType注入
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // 如果适用,根据名称自动添加属性值。
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // 如果适用,根据类型自动添加属性值。
        if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        pvs = newPvs;
    }

    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

    PropertyDescriptor[] filteredPds = null;
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        //遍历后置处理器
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            //对属性进行后置处理,处理使用@Resource、@Autowired注解这种注入方式(最深层也是使用反射对Field进行set)
            PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                if (filteredPds == null) {
                    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return;
                }
            }
            pvs = pvsToUse;
        }
    }
    if (needsDepCheck) {
        if (filteredPds == null) {
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }

    if (pvs != null) {
        //真正进行set注入、byName和byType注入的地方,前面的byName和byType只是先找到bean,还没有真正的注入
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

至此,属性填充的流程就讲解完了,接下来我们一一来看他们的具体实现

讲解顺序

  1. @Resource、@Autowired注解注入
  2. byName、byType、set注入

@Resource 注入

CommonAnnotationBeanPostProcessor

postProcessProperties
  1. 查找带有@Resource注解的元数据
  2. 进行依赖注入
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    //根据resource注解查找元数据
    InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
    try {
        //进行注入
        metadata.inject(bean, beanName, pvs);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
    }
    return pvs;
}
findResourceMetadata
  1. 从缓存获取
    1. 缓存命中
      1. 返回元数据
    2. 缓存未命中
      1. 构建元数据
      2. 返回元数据
/**
 * 容器第一次启动在AbstractAutowireCapableBeanFactory类中的applyMergedBeanDefinitionPostProcessors方法中调用
 * 查询需要进行依赖注入的元数据,这块主要针对@Resource注解
 */
private InjectionMetadata findResourceMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    //使用类名作为缓存键,以便与自定义调用程序向后兼容。
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    // Quick check on the concurrent map first, with minimal locking.
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    //这里使用了一个双检锁来判断元数据是否需要刷新(第一次启动容器都需要去构建元数据,并放入缓存中)
    // 这一块的数据一般由applyMergedBeanDefinitionPostProcessors处理,属性填充时缓存直接从缓存中获取即可
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        synchronized (this.injectionMetadataCache) {
            metadata = this.injectionMetadataCache.get(cacheKey);
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    metadata.clear(pvs);
                }
                //主要构建@Resource注解元数据,如果属性上没有@Resource注解,那么也会构建元数据对象,但是注入元素为0
                metadata = buildResourceMetadata(clazz);
                this.injectionMetadataCache.put(cacheKey, metadata);
            }
        }
    }
    return metadata;
}
buildResourceMetadata

该方法主要构建Resource元数据,流程如下:

  1. 检查属性上是否有WegServiceRef、EJB、Resource等注解
    1. 检查是否是静态属性
      1. 抛异常
      2. 添加到currElements中
  2. 检查方法上是否有WegServiceRef、EJB、Resource等注解
    1. 检查是否是静态方法
      1. 抛异常
      2. 添加到currElements中
  3. 把currElements添加到elements中
  4. 构建元数据并返回
private InjectionMetadata buildResourceMetadata(Class<?> clazz) {
    if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
        return InjectionMetadata.EMPTY;
    }
    //存储带有对应注解的属性或方法,用于构建InjectionMetadata
    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;
    do {
        //用于存储带有对应注解的属性或方法,最后添加到elements中
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
        //检查属性上是否有WegServiceRef、EJB、Resource等注解,如果有,检查是否是静态属性,是的话抛异常,否则添加到currElements中
        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
                if (Modifier.isStatic(field.getModifiers())) {
                    throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
                }
                currElements.add(new WebServiceRefElement(field, field, null));
            }
            else if (ejbClass != null && field.isAnnotationPresent(ejbClass)) {
                if (Modifier.isStatic(field.getModifiers())) {
                    throw new IllegalStateException("@EJB annotation is not supported on static fields");
                }
                currElements.add(new EjbRefElement(field, field, null));
            }
            else if (field.isAnnotationPresent(Resource.class)) {
                if (Modifier.isStatic(field.getModifiers())) {
                    throw new IllegalStateException("@Resource annotation is not supported on static fields");
                }
                if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
                    currElements.add(new ResourceElement(field, field, null));
                }
            }
        });
        //检查方法上是否有WegServiceRef、EJB、Resource等注解,如果有,检查是否是静态方法,是的话抛异常,否则添加到currElements中
        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                return;
            }
            if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
                    if (Modifier.isStatic(method.getModifiers())) {
                        throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
                    }
                    if (method.getParameterCount() != 1) {
                        throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
                    }
                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                    currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
                }
                else if (ejbClass != null && bridgedMethod.isAnnotationPresent(ejbClass)) {
                    if (Modifier.isStatic(method.getModifiers())) {
                        throw new IllegalStateException("@EJB annotation is not supported on static methods");
                    }
                    if (method.getParameterCount() != 1) {
                        throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
                    }
                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                    currElements.add(new EjbRefElement(method, bridgedMethod, pd));
                }
                else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
                    if (Modifier.isStatic(method.getModifiers())) {
                        throw new IllegalStateException("@Resource annotation is not supported on static methods");
                    }
                    Class<?>[] paramTypes = method.getParameterTypes();
                    if (paramTypes.length != 1) {
                        throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
                    }
                    if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
                        PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                        currElements.add(new ResourceElement(method, bridgedMethod, pd));
                    }
                }
            }
        });

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

    //创建元数据并返回
    return InjectionMetadata.forElements(elements, clazz);
}
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) {
            //进行注入,inject是个方法重载
            element.inject(target, beanName, pvs);
        }
    }
}
inject(方法重载)
  1. 判断是否是属性注入
    1. 检查访问权限
    2. 通过反射设置属性值
  2. 方法注入
    1. 验证是否需要跳过属性注入
    2. 检查访问权限
    3. 通过反射invoke method
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
				throws Throwable {
    //判断是否是属性注入,如果不是那就进行方法注入
    if (this.isField) {
        Field field = (Field) this.member;
        //检查访问权限
        ReflectionUtils.makeAccessible(field);
        //通过反射设置属性值
        field.set(target, getResourceToInject(target, requestingBeanName));
    }
    else {
        //验证属性
        if (checkPropertySkipping(pvs)) {
            return;
        }
        try {
            Method method = (Method) this.member;
            //检查访问权限
            ReflectionUtils.makeAccessible(method);
            //通过反射invoke method,注意getResourceToInject方法,
            method.invoke(target, getResourceToInject(target, requestingBeanName));
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }
}
getResourceToInject

这块的源码就不带着去看了,感兴趣的同学可自行debug调试,我大概说一下核心流程

  1. 根据bean名称解析bean(getBean)
  2. 注册依赖bean

@Autowired 注入

AutowiredAnnotationBeanPostProcessor

postProcessProperties
  1. 查找带有@Autowired注解的元数据
  2. 属性注入
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    //查找自动注入元数据
    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;
}
findAutowiringMetadata
  1. 从缓存获取
    1. 缓存命中
      1. 返回元数据
    2. 缓存未命中
      1. 构建元数据
      2. 返回元数据
/**
 * 容器第一次启动在AbstractAutowireCapableBeanFactory类中的applyMergedBeanDefinitionPostProcessors方法中调用
 * 查询需要进行依赖注入的元数据,这块主要针对@Autowired注解
 */
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    // 使用类名作为缓存键,以便与自定义调用程序向后兼容。
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    // Quick check on the concurrent map first, with minimal locking.
    //先从缓存中获取,如果为null,那么则需要构建InjectionMetadata
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    //这里使用了一个双检锁来判断元数据是否需要刷新(第一次启动容器都需要去构建元数据,并放入缓存中)
    // 这一块的数据一般由applyMergedBeanDefinitionPostProcessors处理,属性填充时缓存直接从缓存中获取即可
    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;
}
buildAutowiringMetadata

该方法主要构建@Autowired注解元数据,流程如下:

  1. 查询属性上是否有@Autowired注解
    1. 检查是否是静态属性
      1. 日志输出,跳过构建
      2. 添加到currElements中
  2. 检查方法上是否有WegServiceRef、EJB、Resource等注解
    1. 检查是否是静态方法
      1. 日志输出,跳过构建
      2. 添加到currElements中
  3. 把currElements添加到elements中
  4. 构建元数据并返回
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
    if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
        return InjectionMetadata.EMPTY;
    }
    //存储带有对应注解的属性或方法,用于构建InjectionMetadata
    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;

    do {
        //用于存储带有对应注解的属性或方法,最后添加到elements中
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

        //查询属性上是否有@Autowired注解,如果有并且不是静态属性,那么添加到currElements中
        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;
                }
                boolean required = determineRequiredStatus(ann);
                currElements.add(new AutowiredFieldElement(field, required));
            }
        });

        //查询方法上是否有@Autowired注解,如果有 并且不是静态方法,那么添加到currElements中
        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;
                }
                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);
}
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) {
            //看这里
            element.inject(target, beanName, pvs);
        }
    }
}
inject(方法重载)
  1. 检查缓存
    1. 缓存命中
      1. 解析缓存参数值
    2. 缓存未命中
      1. 解析字段值
  2. 解析出来的值不为null
    1. 检查访问权限并设置
    2. 反射填充属性
@Override
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 = resolvedCachedArgument(beanName, this.cachedFieldValue);
        }
        catch (NoSuchBeanDefinitionException ex) {
            // Unexpected removal of target bean for cached argument -> re-resolve
            value = resolveFieldValue(field, bean, beanName);
        }
    }
    else {
        //解析字段值
        value = resolveFieldValue(field, bean, beanName);
    }
    if (value != null) {
        //给属性做一系列检查,满足条件就设置可访问,否则不做任何设置
        ReflectionUtils.makeAccessible(field);
        //使用反射动态给字段填充属性
        field.se
            t(bean, value);
    }
} 
resolveFieldValue

这块的源码就不带着去看了,嵌套的层级较深,我简单讲解下大概做了哪些事(核心功能),如果感兴趣的同学在调试的时候可以自行查看

  1. 处理@Value注解

  2. 根据类型查询候选者

    三种匹配候选者方式

    1. @Qualifier注解
    2. 泛型
    3. AbstractBeanDefinition的autowireCandidate属性
  3. 解析候选者(getBean)

byName

这块比较简单,就几个步骤,因为这里只是把值添加到PropertyValues中,后续需要进行注入

  1. 检查bean是否包含属性
  2. getBean
  3. add PropertyValues
  4. 注册bean依赖
protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        //检查bean是否包含属性
        if (containsBean(propertyName)) {
            //getBean
            Object bean = getBean(propertyName);
            //添加到PropertyValues中,用于后续的反射注入
            pvs.add(propertyName, bean);
            //注册bean依赖,在当前bean销毁前销毁
            registerDependentBean(propertyName, beanName);
            if (logger.isTraceEnabled()) {
                logger.trace("Added autowiring by name from bean name '" + beanName +
                             "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
            }
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
                             "' by name: no matching bean found");
            }
        }
    }
}

byType

  1. 获取自定义类型转换器
  2. 排除依赖项、是否有set方法
  3. 获取写入的方法参数
  4. 解析依赖(重点)
  5. 如果参数不为null,则添加到PropertyValues中
  6. 注册依赖bean
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    //获取自定义类型转换器
    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }

    Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
    //检查排除依赖项、是否有set方法等
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        try {
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            // Don't try autowiring by type for type Object: never makes sense,
            // even if it technically is an unsatisfied, non-simple property.
            if (Object.class != pd.getPropertyType()) {
                //获取写入的方法参数
                MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                // Do not allow eager init for type matching in case of a prioritized post-processor.
                boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
                DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                //解析依赖
                Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                //如果参数不为null,则添加到PropertyValues中
                if (autowiredArgument != null) {
                    pvs.add(propertyName, autowiredArgument);
                }
                for (String autowiredBeanName : autowiredBeanNames) {
                    registerDependentBean(autowiredBeanName, beanName); //注册依赖bean
                    if (logger.isTraceEnabled()) {
                        logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
                                     propertyName + "' to bean named '" + autowiredBeanName + "'");
                    }
                }
                //清空bean名称
                autowiredBeanNames.clear();
            }
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
        }
    }
}
resolveDependency
  1. 初始化参数名称
  2. 判断各种依赖类型,做对应的处理
  3. 如果都没匹配上,那么再进行依赖解析
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
                                @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    //初始化参数名称
    descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
    //判断各种依赖类型
    if (Optional.class == descriptor.getDependencyType()) {
        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 {
        //如果没有,最终会走到这里
        //如果有必要,使用延迟解析代理
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
            descriptor, requestingBeanName);
        if (result == null) {
            //真正解析依赖的地方
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
    }
}
doResolveDependency
  1. 设置当前的注入点

  2. 解析bean的快捷方式

  3. 处理@Value注解

  4. 根据类型查询候选者

    三种匹配候选者方式

    1. @Qualifier注解
    2. 泛型
    3. AbstractBeanDefinition的autowireCandidate属性
  5. 解析候选者(getBean)

@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
                 @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    //设置当前的注入点
    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    try {
        //解析bean的快捷方式
        Object shortcut = descriptor.resolveShortcut(this);
        //返回null, 因为在子类AbstractAutowireCapableBeanFactory中没有实现
        if (shortcut != null) {
            return shortcut;
        }
        //获取依赖类型
        Class<?> type = descriptor.getDependencyType();
        //获取@Value的值
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
        if (value != null) {
            if (value instanceof String) {
                String strVal = resolveEmbeddedValue((String) value);
                BeanDefinition bd = (beanName != null && containsBean(beanName) ?
                                     getMergedBeanDefinition(beanName) : null);
                value = evaluateBeanDefinitionString(strVal, bd);
            }
            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
            try {
                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()));
            }
        }
        //解析多个bean
        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
            return multipleBeans;
        }
        //查找自动候选者,其实就是查找候选者类型
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        if (matchingBeans.isEmpty()) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }

        String autowiredBeanName;
        Object instanceCandidate;

        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<String, Object> entry = matchingBeans.entrySet().iterator().next();
            autowiredBeanName = entry.getKey();
            instanceCandidate = entry.getValue();
        }

        if (autowiredBeanNames != null) {
            autowiredBeanNames.add(autowiredBeanName);
        }
        if (instanceCandidate instanceof Class) {
            //解析候选者,也就是getBean
            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);
    }
}

看完这一块,比较细心的同学就会发现,这里查找候选者的逻辑是和@Autowired是一样的,方法都是复用的,有的同学可能就会有疑问,怎么我写的方法名和这里的不一样。。。那是因为在resolveFieldValue方法内部调用了

set注入、真正的byName、byType注入

applyPropertyValues

set注入、byType、byName都是在这里面进行注入,前面的byName、byType只是查找候选者,在这里才是真正的注入

  1. 校验参数
  2. 校验pvs是否是MutablePropertyValues类型
    1. 将pvs转换为MutablePropertyValues类型
    2. 校验mpvs是否都是转换后的值
      1. 进行属性注入,注入完就结束方法
    3. 获取参数列表
  3. 校验是否是自动解析的
  4. 解析参数值(getBean)
  5. 注入属性值
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    //如果参数为空,说明不需要注入,所以直接跳过
    if (pvs.isEmpty()) {
        return;
    }

    if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
        ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
    }

    MutablePropertyValues mpvs = null;
    //原始类型
    List<PropertyValue> original;

    //校验pvs是否是MutablePropertyValues类型的
    if (pvs instanceof MutablePropertyValues) {
        //将pvs转换为MutablePropertyValues类型
        mpvs = (MutablePropertyValues) pvs;
        //如果只包含了转换后的值,返回true, 如果有些值还需要转换,返回false
        if (mpvs.isConverted()) {
            // Shortcut: use the pre-converted values as-is.
            try {
                //进行注入,注入完直接结束方法
                bw.setPropertyValues(mpvs);
                return;
            }
            catch (BeansException ex) {
                throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Error setting property values", ex);
            }
        }
        //获取参数列表
        original = mpvs.getPropertyValueList();
    }
    else {
        original = Arrays.asList(pvs.getPropertyValues());
    }
    //获取自定义类型转换
    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }
    BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

    // Create a deep copy, resolving any references for values.
    //创建一个深拷贝,解析值的所有引用。
    List<PropertyValue> deepCopy = new ArrayList<>(original.size());
    //解析标识
    boolean resolveNecessary = false;
    for (PropertyValue pv : original) {
        if (pv.isConverted()) {
            deepCopy.add(pv);
        }
        else {
            //获取属性名
            String propertyName = pv.getName();
            //获取值
            Object originalValue = pv.getValue();
            //是否是自动解析的
            if (originalValue == AutowiredPropertyMarker.INSTANCE) {
                Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
                if (writeMethod == null) {
                    throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
                }
                originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
            }
            //解析参数值(getBean)
            Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
            Object convertedValue = resolvedValue;
            //转换标识
            boolean convertible = bw.isWritableProperty(propertyName) &&
                !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
            if (convertible) {
                //转换属性
                convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
            }
            // Possibly store converted value in merged bean definition,
            // in order to avoid re-conversion for every created bean instance.
            //为了避免重新转换,进行比对校验
            if (resolvedValue == originalValue) {
                if (convertible) {
                    pv.setConvertedValue(convertedValue);
                }
                deepCopy.add(pv);
            }
            else if (convertible && originalValue instanceof TypedStringValue &&
                     !((TypedStringValue) originalValue).isDynamic() &&
                     !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
                pv.setConvertedValue(convertedValue);
                deepCopy.add(pv);
            }
            else {
                resolveNecessary = true;
                //添加到深拷贝集合中
                deepCopy.add(new PropertyValue(pv, convertedValue));
            }
        }
    }
    if (mpvs != null && !resolveNecessary) {
        mpvs.setConverted();
    }

    // Set our (possibly massaged) deep copy.
    try {
        //如果是使用的是set注入,或者byType、byName注入,这里就是真正的注入入口点
        bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    }
    catch (BeansException ex) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    }
}

AbstractPropertyAccessor

setPropertyValues
@Override
public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
    throws BeansException {

    List<PropertyAccessException> propertyAccessExceptions = null;
    //获取属性集合
    List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ?
                      ((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));

    if (ignoreUnknown) {
        this.suppressNotWritablePropertyException = true;
    }
    try {
        for (PropertyValue pv : propertyValues) {
            // setPropertyValue may throw any BeansException, which won't be caught
            // here, if there is a critical failure such as no matching field.
            // We can attempt to deal only with less serious exceptions.
            try {
                //注入属性值,主要看这里,一直往里走
                setPropertyValue(pv);
            }
            catch (NotWritablePropertyException ex) {
                if (!ignoreUnknown) {
                    throw ex;
                }
                // Otherwise, just ignore it and continue...
            }
            catch (NullValueInNestedPathException ex) {
                if (!ignoreInvalid) {
                    throw ex;
                }
                // Otherwise, just ignore it and continue...
            }
            catch (PropertyAccessException ex) {
                if (propertyAccessExceptions == null) {
                    propertyAccessExceptions = new ArrayList<>();
                }
                propertyAccessExceptions.add(ex);
            }
        }
    }
    finally {
        if (ignoreUnknown) {
            this.suppressNotWritablePropertyException = false;
        }
    }

    // If we encountered individual exceptions, throw the composite exception.
    if (propertyAccessExceptions != null) {
        PropertyAccessException[] paeArray = propertyAccessExceptions.toArray(new PropertyAccessException[0]);
        throw new PropertyBatchUpdateException(paeArray);
    }
}

AbstractNestablePropertyAccessor

setPropertyValue
  1. 获取属性路径的属性访问器
  2. 获取属性令牌
  3. 设置属性值
@Override
public void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException {
    AbstractNestablePropertyAccessor nestedPa;
    try {
        //获取属性路径的属性访问器
        nestedPa = getPropertyAccessorForPropertyPath(propertyName);
    }
    catch (NotReadablePropertyException ex) {
        throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
                                               "Nested property in path '" + propertyName + "' does not exist", ex);
    }
    //获取属性令牌
    PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
    //设置属性值
    nestedPa.setPropertyValue(tokens, new PropertyValue(propertyName, value));
}
setPropertyValue
protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
    if (tokens.keys != null) {
        //处理集合属性
        processKeyedProperty(tokens, pv);
    }
    else {
        //处理本地属性,主要看这里
        processLocalProperty(tokens, pv);
    }
}
processLocalProperty
  1. 获取属性处理器
  2. 判断属性处理器是否为null or 属性不可写
  3. 属性转换
  4. 设置属性值(重点,反射调用)
private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
    //获取属性处理器
    PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
    //判断属性处理器是否为null or 属性不可写
    if (ph == null || !ph.isWritable()) {
        //是否是Optional
        if (pv.isOptional()) {
            if (logger.isDebugEnabled()) {
                logger.debug("Ignoring optional value for property '" + tokens.actualName +
                             "' - property not found on bean class [" + getRootClass().getName() + "]");
            }
            return;
        }
        if (this.suppressNotWritablePropertyException) {
            // Optimization for common ignoreUnknown=true scenario since the
            // exception would be caught and swallowed higher up anyway...
            return;
        }
        throw createNotWritablePropertyException(tokens.canonicalName);
    }

    Object oldValue = null;
    try {
        Object originalValue = pv.getValue();
        Object valueToApply = originalValue;
        //是否需要进行转换
        if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
            //在前面转换过了不需要重复转换
            if (pv.isConverted()) {
                valueToApply = pv.getConvertedValue();
            }
            else {
                if (isExtractOldValueForEditor() && ph.isReadable()) {
                    try {
                        oldValue = ph.getValue();
                    }
                    catch (Exception ex) {
                        if (ex instanceof PrivilegedActionException) {
                            ex = ((PrivilegedActionException) ex).getException();
                        }
                        if (logger.isDebugEnabled()) {
                            logger.debug("Could not read previous value of property '" +
                                         this.nestedPath + tokens.canonicalName + "'", ex);
                        }
                    }
                }
                //属性转换
                valueToApply = convertForProperty(
                    tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor());
            }
            pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
        }
        //设置属性值
        ph.setValue(valueToApply);
    }
    catch (TypeMismatchException ex) {
        throw ex;
    }
    catch (InvocationTargetException ex) {
        PropertyChangeEvent propertyChangeEvent = new PropertyChangeEvent(
            getRootInstance(), this.nestedPath + tokens.canonicalName, oldValue, pv.getValue());
        if (ex.getTargetException() instanceof ClassCastException) {
            throw new TypeMismatchException(propertyChangeEvent, ph.getPropertyType(), ex.getTargetException());
        }
        else {
            Throwable cause = ex.getTargetException();
            if (cause instanceof UndeclaredThrowableException) {
                // May happen e.g. with Groovy-generated methods
                cause = cause.getCause();
            }
            throw new MethodInvocationException(propertyChangeEvent, cause);
        }
    }
    catch (Exception ex) {
        PropertyChangeEvent pce = new PropertyChangeEvent(
            getRootInstance(), this.nestedPath + tokens.canonicalName, oldValue, pv.getValue());
        throw new MethodInvocationException(pce, ex);
    }
}
setValue

setValue在AbstractNestablePropertyAccessor类中是一个抽象方法,由子类实现,子类有两个,分别是BeanPropertyHandler(BeanWrapperImpl的内部类)、FieldPropertyHandler(DirectFieldAccessor类的内部类),如果不是集合类属性,那么默认使用BeanPropertyHandler处理

BeanPropertyHandler

setValue
  1. 获取set方法
  2. 检查安全管理器,一般没有
  3. 检查访问权限并设置
  4. 使用反射调用set方法注入属性
@Override
public void setValue(@Nullable Object value) throws Exception {
    //获取set方法
    Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
                          ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
                          this.pd.getWriteMethod());
    //检查安全管理器,一般没有
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            ReflectionUtils.makeAccessible(writeMethod);
            return null;
        });
        try {
            AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
                                          () -> writeMethod.invoke(getWrappedInstance(), value), acc);
        }
        catch (PrivilegedActionException ex) {
            throw ex.getException();
        }
    }
    else {
        //检查访问权限
        ReflectionUtils.makeAccessible(writeMethod);
        //使用反射调用
        writeMethod.invoke(getWrappedInstance(), value);
    }
}

至此,四种属性注入方式就讲解完毕了,有同学可能会有疑惑,不是5种吗。。。其实不是,因为byName、byType属于一类(自动装配)

总结

@Resource方式注入:先根据beanName去查找候选者,如果找到了直接返回进行注入,如果没找到,那么根据类型去解析beanName,最后在getBean拿到候选者进行注入

@Autowired注入:根据类型去查找候选者,如果找到了就进行注入,找不到就进行回退策略,然后根据@Qualifier注解去匹配,匹配不上直接报错,如果该类型的bean有多个,那么就先根据@Qualifier注解去匹配,如果没用上@Qualifier注解,那么就都加入到候选者中,然后就从多个候选者中选出一个候选者进行注入,大致流程是这样的:先根据@Primary匹配,匹配不上,再根据优先级进行匹配,如果还匹配不上,那么进行回退策略,根据beanName进行匹配,匹配上了就返回,还匹配不上,直接抛异常

set注入:set注入属于显式的注入值了,所以不会存在找不到

自动装配(byName、byType):byName的话,根据名称自动装配,找不到无事发生,不会报错,但是没有装配成功,如果进行调用,那么会报空指针异常,byType一样,根据类型匹配,如果该类型的bean有多个,那么进行回退匹配,看看有没有@Qualifier注解,如果有,那么进行名称匹配,否则报错

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后端开发萌新

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值