spring高质量系列-IOC (五)

本章节开始分析bean是何时以及如何加载bean的,同时也会留有之前@propertySource生效的问题.
1.后期还会解析其内嵌式tomcat如何运作
2.AOP的整理比如采用了哪些方式来调用jdk或者cglib的动态代理
3.解析整个整个spring容器的运转流程
4.总结整个springboot启动流程的总结
5.用processon画上面的流程图

首先spring启动的时候会将单例且非懒加载的bean实例存放在singleObjects(concurrentHashMap) key是beanName value 就是具体的对象实例,
同时还存储了其他的比如class和beanName之间的concurrentHashMap,用来提供多种查询方式。

我们主要关注AbstractApplicationContext的finishBeanFactoryInitialization方法
该方法的作用是:初始化其他非懒加载的实例,也就是说我们的bean会在这边被实例化并初始化,其源码如下:

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // Initialize conversion service for this context.
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        // Register a default embedded value resolver if no bean post-processor
        // (such as a PropertyPlaceholderConfigurer bean) registered any before:
        // at this point, primarily for resolution in annotation attribute values.
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }

        // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        // Stop using the temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(null);

        // Allow for caching all bean definition metadata, not expecting further changes.
        beanFactory.freezeConfiguration();

        // Instantiate all remaining (non-lazy-init) singletons.
        beanFactory.preInstantiateSingletons();
    }

  • 1.首先检测ConversionService是否存在,如果存在就给beanFactory设置该属性,ConversionService的作用就是作为一个内部的bean的属性编辑器,编辑bean的属性
  • 2.查找的方式就是先检测其是否携带&然后根据真实的名字或者最终的别名,然后根据别名去查找,如果不存在且父类beanFactory存在就去父类找
    1. 如果不存在 value resolver就注册一个默认的embedded value resolver的beanPostProcessor
  • 4.初始化LoadTimeWeaverAware
  • 5.不在使用mporary ClassLoader 进行类型比较
  • 6.不在允许修改beanDefinition,把beanDefinitionNames的放入到frozenBeanDefinitionNames,但是可以新增beanDefinition
  • 7.进行所有的剩余非懒加载bean的初始化
    最终初始化bean的源码如下
    @Override
    public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Pre-instantiating singletons in " + this);
        }

        // Iterate over a copy to allow for init methods which in turn register new bean definitions.
        // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

        // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                if (isFactoryBean(beanName)) {
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                    if (bean instanceof FactoryBean) {
                        final FactoryBean<?> factory = (FactoryBean<?>) bean;
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                            ((SmartFactoryBean<?>) factory)::isEagerInit,
                                    getAccessControlContext());
                        }
                        else {
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean<?>) factory).isEagerInit());
                        }
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
                }
                else {
                    getBean(beanName);
                }
            }
        }

        // Trigger post-initialization callback for all applicable beans...
        for (String beanName : beanNames) {
            Object singletonInstance = getSingleton(beanName);
            if (singletonInstance instanceof SmartInitializingSingleton) {
                final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }, getAccessControlContext());
                }
                else {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }
  • 1.迭代的是副本,这样在生成bean的时候,还有可能注册新的beanDefinition
    1. 2个for循环,第一个是调用判断是否要获取factorybean,如果是调用getBean,然后判断factory是否继承了SmartFactoryBean,若是则看isEagerInit方法返回true还是false,true表示现在就需要调用getObject方法。
      第二个是调用实例化成功的bean(实现SmartInitializingSingleton)的afterSingletonsInstantiated
  • 3.RootBeanDefinition 和 ChildBeanDefinition 的关系目前只能通过xml配置的形式,通过设置bean标签的parent属性。这样的好处是当我们设置好了父类的bean标签 我们子类只要指定parent,其大部分属性都会继承父类,当然子BeanDefinition也可以覆盖或者新增一些新的配置信息
  • 4.子BeanDefinition继承父BeanDefinition的scope、constructor 、property 、method overrides,并添加新配置。子BeanDefinition会覆盖父子BeanDefinition的配置有:initialization method、destroy method、static factory method settings
    1. 子BeanDefinition有些配置始终不会继承父BeanDefinition:depends on、autowire mode、dependency check、singleton、lazy init。
    1. 如果子类的bean 没有定义class 属性会默认使用父类,子bean的class必须要和父bean的class兼容,也就是说能够接受父bean的配置。

具体的代码解析

  • 1.首先获取getMergedLocalBeanDefinition,该方法就是对于获取childbean的时候,先去获取parentbean,然后先将子类的大部分属性都设置为父类,然后在检测子类自身非beandefinition,看看如果有的属性子类已经设置过了,就使用子类的。
  • 2.然后只有不是抽象类且是单例并非懒加载的才可以加载
    isFactoryBean(beanName)分为三个部分
获取单例,如果不存在也不创建他
Object beanInstance = getSingleton(beanName, false);
        if (beanInstance != null) {
            return (beanInstance instanceof FactoryBean);
        }
  如果bean实例不存在 但是beanDefinition存在且其父beanFactory是ConfigurableBeanFactory,则调用父亲的isFactoryBean方法
        // No singleton instance found -> check bean definition.
        if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
            // No bean definition found in this factory -> delegate to parent.
            return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
        }
  //如果bean和beanDefinition都不存在 在调用 isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));方法判断
        return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));

第一部分:

  • 1.去singletonObjects尝试获取,当获取不到且当前bean正在创建中(即singletonsCurrentlyInCreation中包含当前beanName)
  • 2.再去earlySingletonObjects获取,如果获取不到且allowEarlyReference=true 即允许提前创建bean,则会从singletonFactories获取ObjectFactory
  • 3.如果ObjectFactory存在,通过getObject方法获取真正的对象,并把这个对象放入earlySingletonObjects并从singletonFactories删除ObjectFactory

第二部分:

  • 1.当变化后的beanDefinition不存在,但是父beanfactory存在 则使用原始的name去查看实例是否存在并判断是否factoryBean

第三部分:

  • 1.当转化后得到的beanName 如果存在beanDefinition,我们在获取mergedbean,然后预判断该bean未来是否是factoryBean
    1. 首先尝试获取mergedbean的targetType,如果存在就用他判断是否factoryBean
    1. 然后在判断factorymethodname是否存在,如果存在就不是factroyBean,如果这个也不存在 就进行下一步
    1. 然后在判断mergedbean的beanClass类型,如果这个也不存在就根据getBeanClassName判断bean的类型

回到preInstantiateSingletons这个方法

  • 1.如果是factoryBean 则先获取工厂的bean,然后判断该工厂是否继承了smartFactoryBean ,该smartFactoryBean 的isEagerInit 默认为false表示真正的getOject中的bean对象现在不需要实例化,true为需要立即实例化
  • 2.然后调用getBean方法
  • 3.然后最后一个for循环循环调用实现SmartInitializingSingleton接口的afterSingletonsInstantiated方法

下一章节我们仔细分析getBean方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,688评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,559评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,749评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,581评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,741评论 3 271
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,684评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,122评论 2 292
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,847评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,441评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,939评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,333评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,783评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,275评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,830评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,444评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,553评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,618评论 2 249

推荐阅读更多精彩内容

  • 1.1 Spring IoC容器和bean简介 本章介绍了Spring Framework实现的控制反转(IoC)...
    起名真是难阅读 2,524评论 0 8
  • 1.1 spring IoC容器和beans的简介 Spring 框架的最核心基础的功能是IoC(控制反转)容器,...
    simoscode阅读 6,621评论 2 22
  • 2.1 我们的理念是:让别人为你服务 IoC是随着近年来轻量级容器(Lightweight Container)的...
    好好学习Sun阅读 2,620评论 0 11
  • 今天儿子在幼儿园模拟了幼升小学的一次考试,晚上回家他把试卷交给了我,我给看了一遍,细心和粗心都具备了,我让他把每道...
    李硕爸爸阅读 242评论 0 0
  • 像这样静静地聆听,在风陵渡凝神倾听水的一头像这样深深地嗅,嗅河床边的丛花,直到知觉化为乌有像这样,在皎洁的月色中把...
    安若胡阅读 230评论 0 0