spring容器初始化过程(IOC容器源码分析)

引言

image.png

词语解释

BeanDefinition #(后面简称BD) spring当中用来描述bean的一个接口,包括作用域,属性值,构造函数等信息。通过它就可以完成一个bean的实例化
BeanDefinitionHolder #对BeanDefinition做了一次封装
BeanDefinitionRegistry #用来管理BeanDefinition,提供了向容器注册,删除,获取BeanDefinition对象的方法
AnnotatedBeanDefinitionReader #读取一个被加了注解的类,转成BeanDefinition
ClassPathBeanDefinitionScanner #扫描制定包下的类,并且转换成BeanDefinition
BeanPostProcessor #后置处理器,在Bean初始化前后会回调它的两个方法,(可以插手干预Bean实例化过程,在init()前后执行,对所有bean进行处理)
BeanFactoryPostProcessor #后置处理器 容器级别的后置处理器 可以对BeanDefinition进行修改。相比BeanPostProcessor触发更靠前,处理级别更高

开始

1.先看下最基本的启动 Spring 容器的例子:(基于spring 5.0.x)

public static void main(String[] args) {
    AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Appconfig.class);
    annotationConfigApplicationContext.getBean(IndexService.class);
}
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
    //把配置类注册到容器中(配置类-> BeanDefinition-> 放到BeanDefinition Map 这个map可以暂时狭隘的理解为ioc容器)
    register(annotatedClasses);
    //刷新上下文 容器启动核心方法
    refresh();
}

注意 this()中初始化了AnnotatedBeanDefinitionReader,这个类也比较重要,里面定义了很多BeanPostProcessor(上面名词解释有),我们常用的注解@Autowired等 都依赖这里创建的各种BeanPostProcessor

2.register()方法重点完成了对配置类本身的解析和注册

方法中主要实现了下面几个逻辑,具体代码就不放了,需要详细注释的可以留言
1.根据指定的bean创建一个AnnotatedGenericBeanDefinition(继承自
BeanDefinition)
2.解析bean作用域,如果有@Scope注解,则解析@Scope,没有则默认为singleton,将作用域回写到bd中
3.处理通用注解(主要处理 Lazy DependsOn Primary Role 等)处理完成后回写到bd中
4.生成definitionHolder(其实就是封装了beanName和bd)
5.将bean注册到容器中(可狭隘的理解为将bd放到了beanDefinitionMap中)

3.refresh()刷新上下文
refresh()方法的作用加载或者刷新当前的配置信息,如果已经存在spring容器,则先销毁之前的容器,重新创建spring容器,载入bean定义,完成容器初始化工作。refesh()方法及功能如下:


image.png

具体分析refresh中的函数逻辑:

1.刷新预处理:prepareRefresh()

AbstractApplicationContext. prepareRefresh ()方法

protected void prepareRefresh() {
        //设置容器启动时间
        this.startupDate = System.currentTimeMillis();
        //是否激活标识位
        this.closed.set(false);
        this.active.set(true);

        if (logger.isInfoEnabled()) {
            logger.info("Refreshing " + this);
        }
        //空方法,可能用于后期扩展
        initPropertySources();
        //校验属性的合法性等
        getEnvironment().validateRequiredProperties();
        this.earlyApplicationEvents = new LinkedHashSet<>();
    }

2.获取bean工厂:obtainFreshBeanFactory()

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
     /**
     这个方法在不同的实现容器中有区别,
        如果是xml方式配置,会使用AbstractRefreshableApplicationContext中的实现,并且解析xml配置文件转成beanDefinition
        如果是注解方式,并没有解析包下的注解,而是通过第5步(invokeBeanFactoryPostProcessors())执行的后置处理器完成对bean的加载
        这里我们用的是注解的方式启动所以这里只返回一个bean工厂
     **/
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}

3.准备bean工厂:prepareBeanFactory()

prepareBeanFactory主要完成beanFactory的一些属性设置

4.postProcessBeanFactory() 空方法 可能后期扩展

5.执行bean工厂后置处理器: invokeBeanFactoryPostProcessors()

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    /**
     * invokeBeanFactoryPostProcessors内部维护了List<BeanFactoryPostProcessor>,List<BeanDefinitionRegistryPostProcessor>
     * 先执行实现了BeanDefinitionRegistryPostProcessor接口的PostProcessor,按优先级执行
     * 再执行实现了BeanFactoryPostProcessor接口的postProcessor
     *
     * 在处理BeanDefinitionRegistryPostProcessor的时候有一个非常重要的过程:
     * 在AnnotationConfigApplicationContext构造函数中初始化reader(AnnotatedBeanDefinitionReader)时 添加了一个spring自己的ConfigurationClassPostProcessor组件
     * ConfigurationClassPostProcessor这个组件在这里执行用来处理添加@Configuration注解的类,并将Bean定义注册到BeanFactory中。
     * 到这里加了@Configuration和加了@Bean和@ComponentScan("com.test")包下的bean被放到了容器中
     * 里面的代码太多就不展开了
     **/
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

        // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
        // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

6.注册BeanPostProcessor,拦截bean初始化过程:registerBeanPostProcessors()

大致逻辑是:
1.获取所有的beanPostProcessor
2.根据接口类型分出4种后置处理器类型(PriorityOrdered,Order, MergedBeanDefinitionPostProcessor, 普通类型)
3.依次注册到容器中

public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

        // 获取BeanFactory中注册的类型为BeanPostProcessor.class的bean名称。一般获取到的是实现了BeanPostProcessor接口的Bean
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

        // Register BeanPostProcessorChecker that logs an info message when
        // a bean is created during BeanPostProcessor instantiation, i.e. when
        // a bean is not eligible for getting processed by all BeanPostProcessors.
        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
        beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

        // Separate between BeanPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        //按优先级分类
        // 将BeanPostProcessors分为实现了PriorityOrdered,Ordered等类型
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }
        priorityOrderedPostProcessors.remove(1);
        // First, register the BeanPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        //先注册实现PriorityOrdered接口的处理器,添加到beanfactory容器中
        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

        // Next, register the BeanPostProcessors that implement Ordered.
        // 然后,注册实现了Ordered的BeanPostProcessors
        List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
        for (String ppName : orderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            orderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);

        // Now, register all regular BeanPostProcessors.
        // 现在注册所有常规的BeanPostProcessors
        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
        for (String ppName : nonOrderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

        // Finally, re-register all internal BeanPostProcessors.
        internalPostProcessors.remove(1);
        //最后,重新注册所有internal BeanPostProcessors(实现MergedBeanDefinitionPostProcessor接口的后置处理器)
        sortPostProcessors(internalPostProcessors, beanFactory);

        registerBeanPostProcessors(beanFactory, internalPostProcessors);

        // Re-register post-processor for detecting inner beans as ApplicationListeners,
        // moving it to the end of the processor chain (for picking up proxies etc).
        //注册ApplicationListenerDetector,用于Bean创建完时检查是否是ApplicationListener
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }

7.初始化所有剩下的单例bean,单例bean在初始化容器时创建,原型bean在getbean()时创建

DefaultListableBeanFactory. preInstantiateSingletons()

public void preInstantiateSingletons() throws BeansException {
        if (logger.isDebugEnabled()) {
            logger.debug("Pre-instantiating singletons in " + this);
        }
        //获取容器中所有bean的名字
        // 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...
        // 触发所有非延迟加载单例beans的初始化,主要步骤为调用getBean
        for (String beanName : beanNames) {
            //获取BeanDefinition  合并父 Bean 中的配置,<bean id="" class="" parent="" /> 中的 parent
            //类似继承  继承父bean的信息,也可以覆盖一些信息,也可以增加一些信息
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            //非抽象,单例,非延时加载的
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                //是不是factoryBean
                if (isFactoryBean(beanName)) {
                    //如果是FactoryBean则加上&  FactoryBean(会返回两个对象 一个是getObject中返回的  一个是他自己 &+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 {
                    //对于普通的 Bean,只要调用 getBean(beanName) 这个方法就可以进行初始化了
                    getBean(beanName);
                }
            }
        }
        // 到这里说明所有的非懒加载的 单例 bean 已经完成了初始化

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

8.finishRefresh()完成BeanFactory的初始化创建工作,IOC容器就创建完成

protected void finishRefresh() {
        // Clear context-level resource caches (such as ASM metadata from scanning).
        //1. 初始化生命周期有关的后置处理器,BeanFactory创建完成后刷新相关的工作
        //默认从容器中找是否有lifecycleProcessor的组件【LifecycleProcessor】;如果没有new DefaultLifecycleProcessor();加入到容器;
        clearResourceCaches();

        // Initialize lifecycle processor for this context.
        //1. 初始化生命周期有关的后置处理器,BeanFactory创建完成后刷新相关的工作
        //默认从容器中找是否有lifecycleProcessor的组件【LifecycleProcessor】;如果没有new DefaultLifecycleProcessor();加入到容器;
        initLifecycleProcessor();

        // Propagate refresh to lifecycle processor first.
        //2. 拿到前面定义的生命周期处理器(LifecycleProcessor);回调onRefresh();
        getLifecycleProcessor().onRefresh();

        // Publish the final event.
        //3. 发布容器刷新完成事件;
        publishEvent(new ContextRefreshedEvent(this));

        // Participate in LiveBeansView MBean, if active.
        LiveBeansView.registerApplicationContext(this);
    }

结尾

以上基本大致分析了AnnotationConfigApplicationContext容器的初始化过程,容器启动过程中会先保存bean定义信息,然后容器根据条件创建bean实例,创建实例后会使用多种后置处理器增强bean的功能,比如处理aop等。
简单来说就是分为两部分 一个是将配置转化成BeanDefinition然后注册到容器中(就是放到了map中) 第二是将map中的bean初始化(单例的在启动初始化,原型在getBean初始化)。

文章比较粗糙,很多方法没有一步步展开,如果发现错误和问题 欢迎大佬指正

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

推荐阅读更多精彩内容