前言

从前面的章节得知,AbstractAutowireCapableBeanFactory类的createBean方法是创建bean的核心方法,它会调用一个内部方法doCreateBean,该方法的主要流程是这样的:

image

前面花了多篇文章给介绍,在Spring中bean实例是如何创建的,今天这篇文章,主要给大家介绍一下,bean实例创建完之后,是如何进行依赖注入的。

1 populateBean方法

Spring中的核心功能之一:依赖注入,到底是在哪里完成的?

在doCreateBean方法中,通过createBeanInstance方法创建了bean实例之后,再通过populateBean方法完成的依赖注入。

image

今天重点看看populateBean方法有哪些功能:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    //如果bean为空
    if (bw == null) {
        //但是有属性,则抛异常
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        } else {
            //如果没有属性,则直接返回
            return;
        }
    }


    //用户可以自定义InstantiationAwareBeanPostProcessor
    //可以向bean的成员变量上中注入自定义的信息
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                return;
            }
        }
    }


    //获取bean的属性
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    //获取注入类型
    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    //如果是按名称注入或者按类型注入
    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) {
            //用户可以自定义InstantiationAwareBeanPostProcessor,对属性进行后置处理。
            //主要是对@Resource,@Autowired,@Value,@Inject等注解进行注入
            PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                if (filteredPds == null) {
                    /**
                     * 对属性进行过滤,主要过滤三种属性:
                     * 1. 使用CGLib进行代理的属性
                     * 2. 需要忽略掉的类型,比如:String
                     * 3. 需要忽略掉的接口类型,比如:Aware接口
                     */
                    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) {
        //填充属性
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

下面用一张图总结一下populateBean方法的主要流程:

image

我们重点看看autowireByName、autowireByType、postProcessProperties、filterPropertyDescriptorsForDependencyCheck和applyPropertyValues方法。

2 autowireByName方法

接下来,我们一起看看按名称注册的方法autowireByName,包含了哪些逻辑。

protected void autowireByName(
        String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    //获取非简单属性名称数组
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    //遍历属性名称数组
    for (String propertyName : propertyNames) {
        //判断容器中是否包含该bean属性名称
        if (containsBean(propertyName)) {
            //根据名称从容器中获取bean实例
            Object bean = getBean(propertyName);
            //将名称和bean实例保存到集合中
            pvs.add(propertyName, bean);
            //将bean的依赖关系注册到Spring容器
            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");
            }
        }
    }
}

我们可以看到整个autowireByName方法的逻辑是非常简单的。

用一张图总结一下它的主要流程:

image

接下来,重点看看unsatisfiedNonSimpleProperties方法:

protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
    Set<String> result = new TreeSet<>();
    PropertyValues pvs = mbd.getPropertyValues();
    PropertyDescriptor[] pds = bw.getPropertyDescriptors();
    for (PropertyDescriptor pd : pds) {
        if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
                !BeanUtils.isSimpleProperty(pd.getPropertyType())) {
            result.add(pd.getName());
        }
    }
    return StringUtils.toStringArray(result);
}

该方法主要是遍历所有属性,返回未满足要求的非简单bean属性数组。

属性要满足如下4个条件:

  1. setter方法不为空。
  2. 属性被排除在依赖性检查之外,这里主要是判断是否是CGLIB代理的属性,是否在忽略依赖类型里面,是否是指定的忽略依赖接口。
  3. 属性填充值里面不包含对应的属性名称。
  4. 属性不是简单类型的属性。

看看isSimpleProperty方法是如何判断简单属性的:

public static boolean isSimpleProperty(Class<?> type) {
    Assert.notNull(type, "'type' must not be null");
    return isSimpleValueType(type) || (type.isArray() && isSimpleValueType(type.getComponentType()));
}

调用了isSimpleValueType方法,并且不是数组。

重点看看isSimpleValueType方法:

public static boolean isSimpleValueType(Class<?> type) {
return (Void.class != type && void.class != type &&
        (ClassUtils.isPrimitiveOrWrapper(type) ||
        Enum.class.isAssignableFrom(type) ||
        CharSequence.class.isAssignableFrom(type) ||
        Number.class.isAssignableFrom(type) ||
        Date.class.isAssignableFrom(type) ||
        Temporal.class.isAssignableFrom(type) ||
        URI.class == type ||
        URL.class == type ||
        Locale.class == type ||
        Class.class == type));
}

非Void类型,Java中的原生类型,原生类型的包装类型,Enum、CharSequence、Number、Date、Temporal、URI、URL、Locale和Class都是简单类型。

不是这些类型,就可能是Java中的引用类型了,需要获取bean实例的。

3 autowireByType方法

上面已经介绍了autowireByName方法的主要流程,下面重点看看autowireByType方法。

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);
    //获取非简单属性名称数组
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    //遍历非简单属性名称数组
    for (String propertyName : propertyNames) {
        try {
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            //排除Object对象类型的属性,意义不大
            if (Object.class != pd.getPropertyType()) {
                //获取指定的setter方法
                MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
                DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                //根据类型解析指定beanName的属性所匹配的值,
                //并把解析到的属性名存储在autowiredBeanNames中。         
                //当属性存在多个封装bean时,如 @Autowired List<Bean> beans,会找到所有的匹配Bean 类型的bean并将其注入。
                Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                if (autowiredArgument != null) {
                    //将属性名称和bean实例添加到集合中
                    pvs.add(propertyName, autowiredArgument);
                }
                //遍历autowiredBeanNames集合
                for (String autowiredBeanName : autowiredBeanNames) {       
                    //将bean的依赖关系注册到Spring容器
                    registerDependentBean(autowiredBeanName, beanName);
                    if (logger.isTraceEnabled()) {
                        logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
                                propertyName + "' to bean named '" + autowiredBeanName + "'");
                    }
                }
                //清空autowiredBeanNames集合
                autowiredBeanNames.clear();
            }
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
        }
    }
}

autowireByType方法的主要流程如下:

image

autowireByType方法中通过getCustomTypeConverter方法,可以获取到用户自定义的类型转换器。

通过resolveDependency方法,根据类型找到相对应的bean实例集合,然后将bean的依赖关系注册到Spring容器。

其中resolveDependency方法的逻辑非常复杂,在这里就不过多展开了,感兴趣的小伙伴,可以找我私聊。

4. postProcessProperties方法

接下来,看看第1章中提到的InstantiationAwareBeanPostProcessor接口的postProcessProperties方法。

目前有不少类实现了InstantiationAwareBeanPostProcessor接口:

image

其中有我们耳熟能详的AutowiredAnnotationBeanPostProcessor类。

@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方法获取@Autowired注解定义的元数据。

而后通过inject方法,将bean实例注入到对应的属性上。

protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
        throws Throwable {
    //如果元数据是字段
    if (this.isField) {
        Field field = (Field) this.member;
        ReflectionUtils.makeAccessible(field);
        //直接通set方法注入bean
        field.set(target, getResourceToInject(target, requestingBeanName));
    }
    else {
        if (checkPropertySkipping(pvs)) {
            return;
        }
        try {
            //如果元数据是方法,比如setter方法
            Method method = (Method) this.member;
            ReflectionUtils.makeAccessible(method);
            //调用比如setter方法注入bean
            method.invoke(target, getResourceToInject(target, requestingBeanName));
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }
}

后面会有@Autowired注解原理的专题,敬请期待。

未完待续。。。

最后修改:2026 年 06 月 05 日
如果觉得我的文章对你有用,请随意赞赏