Spring 源码解析 | populateBean 属性填充(上)

简介: 本文主要是讲 Spring 容器的启动过程主要是以题干的方式进行可能不回涉及过多的细节,希望大家阅读本文能对 Spring 源码有一个简单的了解。环境介绍:Spring 5.3.10Jdk 11

在前一篇我们一起分析了 getBean Spring 中对象创建的过程,今天我们继续分析 AbstractAutowireCapableBeanFactory#populateBean 方法 Spring 对 Bean 对象进行属性填充(其实也是我们说的自动注入的过程)


image.png


获取字段信息


获取 Bean 的字段信息


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


查找 Bean 的模式


通常查找 Bean 的模式有两种 AUTOWIRE_BY_NAME 或者 AUTOWIRE_BY_NAME


if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    // Add property values based on autowire by name if applicable.
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
        autowireByName(beanName, mbd, bw, newPvs);
    }
    // Add property values based on autowire by type if applicable.
    if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        autowireByType(beanName, mbd, bw, newPvs);
    }
    pvs = newPvs;
}


1. 通过 Bean 名称查找


通过 BeanName 进行 Bean 的查询然后添加到 pvs 中。


protected void autowireByName(
    String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    // 获取非基础类型的属性
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        // 是否存在这个 beanName 
        if (containsBean(propertyName)) {
            // 获取 bean
            Object bean = getBean(propertyName);
            pvs.add(propertyName, 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");
            }
        }
    }
}


2. 通过 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);
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        try {
            // 获取需要注入属性的 PropertyDescriptor
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            // Don't try autowiring by type for type Object: never makes sense,
            // even if it technically is a unsatisfied, non-simple property.
            // 排除 Object 类型
            if (Object.class != pd.getPropertyType()) {
                // 获取 geng 方法
                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);                
                // 解析指定 beanName 的属性所匹配的值,并把解析到的属性名称存储在 autowiredBeanNames 中
                // 当属性存在过个封装 bean 时将会找到所有匹配的 bean 并将其注入
                Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                if (autowiredArgument != null) {
                    pvs.add(propertyName, autowiredArgument);
                }
                // 循环 autowiredBeanNames
                for (String autowiredBeanName : autowiredBeanNames) {
                    registerDependentBean(autowiredBeanName, beanName);
                    if (logger.isTraceEnabled()) {
                        logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
                                     propertyName + "' to bean named '" + autowiredBeanName + "'");
                    }
                }
                autowiredBeanNames.clear();
            }
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
        }
    }
}


3. 几个重要的方法


  • unsatisfiedNonSimpleProperties


就是类型为对象类型的属性,但是这里并不是将所有的对象类型都都会找到,比如 8 个原始类型,String 类型 ,Number类型、Date类型、URL类型、URI类型等都会被忽略


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);
}


  • registerDependentBean


保存属性注入的映射关系


public void registerDependentBean(String beanName, String dependentBeanName) {
    String canonicalName = canonicalName(beanName);
    synchronized (this.dependentBeanMap) {
        Set<String> dependentBeans =
            this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
        if (!dependentBeans.add(dependentBeanName)) {
            return;
        }
    }
    synchronized (this.dependenciesForBeanMap) {
        Set<String> dependenciesForBean =
            this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
        dependenciesForBean.add(canonicalName);
    }
}


相关文章
|
2天前
|
XML Java 数据格式
深度解析 Spring 源码:从 BeanDefinition 源码探索 Bean 的本质
深度解析 Spring 源码:从 BeanDefinition 源码探索 Bean 的本质
10 3
|
1天前
|
存储 NoSQL 算法
Redis(四):del/unlink 命令源码解析
Redis(四):del/unlink 命令源码解析
|
2天前
|
XML Java 数据格式
深度解析 Spring 源码:揭秘 BeanFactory 之谜
深度解析 Spring 源码:揭秘 BeanFactory 之谜
6 1
|
7天前
|
XML Java API
IoC 之 Spring 统一资源加载策略【Spring源码】
IoC 之 Spring 统一资源加载策略【Spring源码】
18 2
|
2天前
|
Java Spring
深入解析Spring源码,揭示JDK动态代理的工作原理。
深入解析Spring源码,揭示JDK动态代理的工作原理。
7 0
|
8天前
|
安全 Java 数据安全/隐私保护
Java基础4-一文搞懂String常见面试题,从基础到实战,更有原理分析和源码解析!(二)
Java基础4-一文搞懂String常见面试题,从基础到实战,更有原理分析和源码解析!(二)
16 0
|
8天前
|
JSON 安全 Java
Java基础4-一文搞懂String常见面试题,从基础到实战,更有原理分析和源码解析!(一)
Java基础4-一文搞懂String常见面试题,从基础到实战,更有原理分析和源码解析!(一)
19 0
|
Java Spring 容器
Spring 源码解析 | populateBean 属性填充(下)
本文主要是讲 Spring 容器的启动过程主要是以题干的方式进行可能不回涉及过多的细节,希望大家阅读本文能对 Spring 源码有一个简单的了解。 环境介绍: Spring 5.3.10 Jdk 11
158 0
|
Java 数据库连接 Spring
Spring 属性填充(下)
Spring 的属性填充主要是在 Bean 被创建后,通过 populateBean 方法来完成对象属性赋值以逐步完成 Bean 的初始化工作。
162 0
|
Java Spring
Spring 属性填充(上)
Spring 的属性填充主要是在 Bean 被创建后,通过 populateBean 方法来完成对象属性赋值以逐步完成 Bean 的初始化工作。
135 0

推荐镜像

更多