专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

Spring源码学习(三)炒鸡丁与populateBean没区别

逻辑说明

populateBean的流程 炒鸡丁的流程
1.执行InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation(在设置属性前去修改Bean的状态,也可以控制是否继续填充Bean) 作为一个已婚男人炒菜之前,请示老婆,这很重要。 我:“我炒宫爆鸡丁了,有特殊要求吗?” 老婆大人:“没有要求,炒吧”。
2.注入属性到PropertyValues中(autowireByName/autowireByType) 初步准备食材 准备鸡肉,郫县豆瓣酱,花生米,黄瓜
3.执行InstantiationAwareBeanPostProcessor的postProcessPropertyValues,对解析完但未设置的属性再进行处理 切菜 鸡肉切丁,黄瓜切小块。
4.对dependency-check属性的支持,默认是不校验
5.将PropertyValues中的属性值设置到BeanWrapper中 下锅,炒熟出锅

autowirebyType的大致逻辑

看了源码总结如下:

1、 不处理简单属性,即不处理:Enum,CharSequence,Number,Date,URI,Locale等。(具体可以查看org.springframework.beans.BeanUtils#isSimpleProperty这个方法。)
2、 不对Object类型的属性进行自动注入, 没有意义,技术无法实现
3、 解析依赖resolveDependency并设置到pvs中
4、 registerDependentBean 注册当前依赖。

autowiredByType的源码注释

/**
     * Abstract method defining "autowire by type" (bean properties by type) behavior.
     * 抽象方法 定义 按类型注入
     * <p>This is like PicoContainer default, in which there must be exactly one bean
     * of the property type in the bean factory. This makes bean factories simple to
     * configure for small namespaces, but doesn't work as well as standard Spring
     * behavior for bigger applications.
     * 类似PicoContainer(非常轻量级的Ioc容器),beanFactory中一个属性类型必须有一个确切对应的bean
     * bean工厂很容易配置小的命名空间.
     * @param beanName the name of the bean to autowire by type  需要按类型注入的BeanName
     * @param mbd the merged bean definition to update through autowiring   合并后的BeanDefinition
     * @param bw the BeanWrapper from which we can obtain information about the bean  BeanWrapper对象
     * @param pvs the PropertyValues to register wired objects with 注册属性的属性值
     */
    protected void autowireByType(
            String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
        //获取类型转换器
        TypeConverter converter = getCustomTypeConverter();
        if (converter == null) {
            converter = bw;
        }
        //获取需要 注入的 非简单类型
        /**
         * 简单类型,详见
         * @see org.springframework.beans.BeanUtils#isSimpleProperty
         */
        Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
        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 a unsatisfied, non-simple property.
                // 不对Object类型的属性进行自动注入, 没有意义,技术无法实现
                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.
                    // 假如实现了prioritized post-processor ,在进行类型匹配时,是不允许,eager初始化(热加载)的
                    boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
                    DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                    //解析依赖
                    Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                    if (autowiredArgument != null) {
                        pvs.add(propertyName, autowiredArgument);
                    }
                    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);
            }
        }
    }

下回写resolveDependency的逻辑。

一图胜千言

68_1.png

源码注释


/** * Populate the bean instance in the given BeanWrapper with the property values * from the bean definition. * 填充bean的属性 * @param beanName the name of the bean bean的名称 * @param mbd the bean definition for the bean 合并后的Bean的定义 * @param bw the BeanWrapper with bean instance beanWrapper的对象 */ @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. // 跳过没有属性,null实例 return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. //给任何InstantiationWareBeanPostProcessors在设置属性之前修改bean的状态的机会。 // 例如,这可用于支持属性注入 boolean continueWithPropertyPopulation = true; //InstantiationWareBeanPostProcessors 可以控制是否继续填充bean if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { //根据名称自动注入 autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == 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) { //有InstantiationAwareBeanPostProcessors 对象 if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } //检查依赖Dependency-check checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { //将属性值设置到Bean中 applyPropertyValues(beanName, mbd, bw, pvs); } }

下一篇resolveDependency 预计10月7号前

文章永久链接:https://tech.souyunku.com/35820

未经允许不得转载:搜云库技术团队 » Spring源码学习(三)炒鸡丁与populateBean没区别

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们