欢迎访问shiker.tech

请允许在我们的网站上展示广告

您似乎使用了广告拦截器,请关闭广告拦截器。我们的网站依靠广告获取资金。

bean获取&bean工厂职责梳理
(last modified Apr 22, 2023, 6:24 PM )
by
侧边栏壁纸
  • 累计撰写 190 篇文章
  • 累计创建 65 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

bean获取&bean工厂职责梳理

橙序员
2023-04-16 / 0 评论 / 0 点赞 / 436 阅读 / 1,692 字 / 正在检测百度是否收录... 正在检测必应是否收录...
文章摘要(AI生成)

内部类实现流程测试用例我们测试用例如下:public class A { @Setter private String c; @Setter private B b; @NoArgsConstructor class B { @Setter

内部类实现流程

测试用例

我们测试用例如下:

public class A {

    @Setter
    private String c;

    @Setter
    private B b;

    @NoArgsConstructor
    class B {

        @Setter
        private String s;
    }
}

spring配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="a" class="org.jdbc.demo.A" >
        <property name="c" value="1232"/>
        <property name="b">
            <bean class="org.jdbc.demo.A.B">
                <constructor-arg ref="a"/>
                <property name="s" value="hello"/>
            </bean>
        </property>
    </bean>
</beans>

内部实现过程

首先我们debug,发现bean定义中的属性b会嵌套一层bean定义,结构如下:
image-20230416141815884

在属性赋值时,我们会判断如果属性类型为BeanDefinitionHolder或者BeanDefinition,就执行内部bean的处理逻辑,本质上又再次调用对应的getBean()方法处理内部bean对应的依赖bean对象和内部bean对象。

对应的内部bean处理代码为:

    @Nullable
    public Object resolveValueIfNecessary(Object argName, @Nullable Object value) { 
        //省略代码--其他类型的属性赋值
        else if (value instanceof BeanDefinitionHolder) {
            // Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
            BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
            return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
        }
        else if (value instanceof BeanDefinition) {
            // Resolve plain BeanDefinition, without contained name: use dummy name.
            BeanDefinition bd = (BeanDefinition) value;
            String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
                    ObjectUtils.getIdentityHexString(bd);
            return resolveInnerBean(argName, innerBeanName, bd);
        }
        
    }

    @Nullable
    private Object resolveInnerBean(Object argName, String innerBeanName, BeanDefinition innerBd) {
        RootBeanDefinition mbd = null;
        try {
            // 获取内部bean的bean定义
            mbd = this.beanFactory.getMergedBeanDefinition(innerBeanName, innerBd, this.beanDefinition);
            // 检查给定的 bean 名称是否唯一。 如果还不是唯一的,添加计数器 - 增加计数器直到名称是唯一的。
            String actualInnerBeanName = innerBeanName;
            if (mbd.isSingleton()) {
                actualInnerBeanName = adaptInnerBeanName(innerBeanName);
            }
            this.beanFactory.registerContainedBean(actualInnerBeanName, this.beanName);
            // 保证内部 bean 所依赖的 bean 的初始化。
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dependsOnBean : dependsOn) {
                    this.beanFactory.registerDependentBean(dependsOnBean, actualInnerBeanName);
                    this.beanFactory.getBean(dependsOnBean);
                }
            }
            // 现在实际创建内部 bean 实例
            Object innerBean = this.beanFactory.createBean(actualInnerBeanName, mbd, null);
            if (innerBean instanceof FactoryBean) {
                boolean synthetic = mbd.isSynthetic();
                innerBean = this.beanFactory.getObjectFromFactoryBean(
                        (FactoryBean<?>) innerBean, actualInnerBeanName, !synthetic);
            }
            if (innerBean instanceof NullBean) {
                innerBean = null;
            }
            return innerBean;
        }
        catch (BeansException ex) {
            throw new BeanCreationException(
                    this.beanDefinition.getResourceDescription(), this.beanName,
                    "Cannot create inner bean '" + innerBeanName + "' " +
                    (mbd != null && mbd.getBeanClassName() != null ? "of type [" + mbd.getBeanClassName() + "] " : "") +
                    "while setting " + argName, ex);
        }
    }

继承类实现流程

测试用例

我们的测试用例如下:

public class Parent {
    @Setter
    private String s;
}

public class Son extends Parent{

    @Setter
    private String c;
}

对应的spring配置为:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="a" class="org.jdbc.demo.Parent">
        <property name="s" value="1232"/>
    </bean>
    <bean id="b" class="org.jdbc.demo.Son" parent="a">
        <property name="c" value="1234"/>
    </bean>
</beans>

内部实现流程

走读代码,我们发现在获取bean之前,合并bean定义的流程中如果父bean存在会递归获取对应的父bean定义,通过mbd.overrideFrom(bd)将属性进行合并最后返回:

    protected RootBeanDefinition getMergedBeanDefinition(
            String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
            throws BeanDefinitionStoreException {

        synchronized (this.mergedBeanDefinitions) {
            RootBeanDefinition mbd = null;

            // 现在检查完全锁定以强制执行相同的合并实例。
            if (containingBd == null) {
                mbd = this.mergedBeanDefinitions.get(beanName);
            }

            if (mbd == null) {
                //对应bean的父bean为空
                if (bd.getParentName() == null) {
                    //使用给定根 bean 定义的副本。
                    if (bd instanceof RootBeanDefinition) {
                        mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                    }
                    else {
                        mbd = new RootBeanDefinition(bd);
                    }
                }
                else {
                    // 如果父bean不为空,则子 bean 定义需要与父 bean 合并。
                    BeanDefinition pbd;
                    try {
                        //根据父beanid找到父bean名称
                        String parentBeanName = transformedBeanName(bd.getParentName());
                        //如果要查找的bean和父bean名称不相等
                        if (!beanName.equals(parentBeanName)) {
                            //递归查找对应的父bean定义
                            pbd = getMergedBeanDefinition(parentBeanName);
                        }
                        //如果要查找的bean和父bean为同一个bean名称
                        else {
                            //获取对应的父bean工厂,并尝试获取合并后的bean定义
                            BeanFactory parent = getParentBeanFactory();
                            if (parent instanceof ConfigurableBeanFactory) {
                                pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                            }
                            else {
                                throw new NoSuchBeanDefinitionException(parentBeanName,
                                        "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                                        "': cannot be resolved without an AbstractBeanFactory parent");
                            }
                        }
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                                "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                    }
                    //具有覆盖值的深拷贝。
                    mbd = new RootBeanDefinition(pbd);
                    //将子bean的属性值添加到父bean属性集合中
                    mbd.overrideFrom(bd);
                }

                // 如果之前未配置,则设置默认单例范围。
                if (!StringUtils.hasLength(mbd.getScope())) {
                    mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
                }

                //包含在非单例 bean 中的 bean 本身不能是单例。让我们在这里即时纠正这个问题,因为这可能是外部 bean 的父子合并的结果,在这种情况下,原始的内部 bean 定义将不会继承合并的外部 bean 的单例状态。
                if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                    mbd.setScope(containingBd.getScope());
                }

                //暂时缓存合并的 bean 定义(它可能稍后仍会重新合并以获取元数据更改)
                if (containingBd == null && isCacheBeanMetadata()) {
                    this.mergedBeanDefinitions.put(beanName, mbd);
                }
            }
            //返回的是对应bean名称的合并bean定义集合
            return mbd;
        }
    }

从返回的bean定义中我们可以看到,属性集合中已经包含子类和父类的全部属性:

image-20230416151351692

获取bean的流程

从前几篇文章和本文的梳理中,我们已经能够很准确的梳理出bean获取的流程了,如下:

spring-bean创建流程图

bean获取的入口在AbstractBeanFactory中,bean创建和属性填充的过程在AbstractAutowireCapableBeanFactory中,而内部bean和依赖bean的获取则交由BeanDefinitionValueResolver进行统一处理后,再由AbstractNestablePropertyAccessor调用PropertyHandler(由BeanWrapperImpl实现setValue()方法)完成属性填充。

BeanFactory解析

综上,我们也能结合源码,捋清楚bean工厂的类关系和类职责:

image-20230416165345199

由上图,我们可以知道bean工厂定义类了三类操作:

  • 第一类:对bean工厂中bean定义相关的操作,对应接口ListableBeanFactory

  • 第二类:对bean工厂中bean对象的初始化操作,对应接口AutowireCapableBeanFactory

  • 第三类:对bean工厂本身的操作,对应接口HierarchicalBeanFactory

基于上述三类,由衍生出:

  • 对bean定义进行解析和获取bean操作,对应接口ConfigurableBeanFactory

  • 读取bean定义并进行bean初始化的操作,对应接口ConfigurableListableBeanFactory

然后分别由以下类进行实现:

  • Bean定义的解析和Bean的获取,由AbstractBeanFactory负责完成

  • Bean的初始化,由AbstractAutowireCapableBeanFactory负责完成

  • 获取Bean定义以及依赖bean定义获取bean的操作,由DefaultListableBeanFactory负责完成

0

评论区