• 9、Spring 源码学习 ~ Bean 的加载


    Bean 的加载

    一、整体时序图

    1、入口:

    BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beanfactory-test.xml"));
    TestBean testBean = (TestBean) beanFactory.getBean("testBean");
    
    • 1
    • 2

    其中获取 bean 的函数 beanFactory#getBean 就是我们的入口,跟踪入口,可以看到源码如下:

    AbstractBeanFactory#getBean

    @Override
    public Object getBean(String name) throws BeansException {
       
        return doGetBean(name, null, null, false);
    }
    
    protected <T> T doGetBean(
        String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
        throws BeansException {
       
    
        //提取对应的 beanName
        String beanName = transformedBeanName(name);
        Object beanInstance;
    
        // Eagerly check singleton cache for manually registered singletons.
        // 检查缓存中或者实例工厂中是否有对应的实例
        // 为什么首先会使用这段代码呢?
        // 因为在创建单例 bean 的时候,会存在依赖注入的情况,而创建依赖的时候,为了避免循环依赖
        // Spring 创建 bean 的原则是不等 bean 创建完成,就会将创建 bean 的 ObjectFactory 提早曝光
        // 也就是将 ObjectFactory 加入到缓存中,一旦下个 bean 创建的时候,需要依赖上个 bean 则直接使用 ObjectFactory
        // 下面代码是尝试直接从缓存中获取或者 singletonFactories 中的 ObjectFactory 中获取
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
       
            if (logger.isTraceEnabled()) {
       
                if (isSingletonCurrentlyInCreation(beanName)) {
       
                    logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                                 "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
       
                    logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            //返回对应的实例,有时候存在诸如 BeanFactory 的情况,并不是直接返回实例本身,而是返回指定方法返回的实例
            beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
    
        else {
       
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            //只有单例情况下,才会尝试解决循环依赖.
            //如果存在 A 中有属性 B,B 中又有属性 A,那么当依赖注入的时候,
            //就会产生当 A 还未创建完成的时候,由于创建 A 需要先创建 B,而创建 B 又需要先创建 A,
            //就造成了循环依赖,也就是下面 isPrototypeCurrentlyInCreation(beanName) 为 true
            if (isPrototypeCurrentlyInCreation(beanName)) {
       
                throw new BeanCurrentlyInCreationException(beanName);
            }
    
            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            //如果 beanDefinitionMap 中(即所有已加载的类中)不包括 beanName,
            //则尝试从 parentBeanFactory 中检测
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
       
                // Not found -> check parent.
                //递归到 BeanFactory 中寻找
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
       
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
       
                    //有参,委托给父级
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else if (requiredType != null) 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
  • 相关阅读:
    pycharm运行R语言脚本(win10环境下安装)
    SpringSecurity Oauth2实战 - 10 自定义SpEL权限表达式配置白名单url不需要token认证和鉴权
    傅里叶分析(2)
    【STM32】LCD液晶显示
    ios的info.plist 配置
    LNMP架构&部署Discuz论坛系统
    怎么把电影中的声音保存下来?
    分享68个ASP.NET源码总有一个是你想要的
    微信小程序——简易复制文本
    【JavaScript】关键字function的点滴
  • 原文地址:https://blog.csdn.net/lxz352907839/article/details/127560881