Spring源码分析——容器创建

本文详细分析了Spring容器的创建过程,分为三个阶段:容器创建及准备工作、容器初始化和组件注册、容器初始化完毕后的逻辑。重点介绍了prepareRefresh、obtainFreshBeanFactory、prepareBeanFactory等方法的作用,以及BeanFactoryPostProcessor、BeanPostProcessor、messageSource和事件多播器的注册与初始化。文章揭示了Spring Ioc容器如何一步步构建,帮助读者深入了解Spring的内部机制。
摘要由CSDN通过智能技术生成

熟悉Spring的朋友可能都知道,Spring容器,是Spring框架实现其两大核心思想,IOCAOP的基础,平时我们可能只是会享受容器带给我们的便利,确对容器的了解知之甚少,今天,我们就来通过Spring底层源码来分析Spring容器的构造过程,这将使我们对Spring的认识再上一个台阶,让我们更加了解我们的“对象”。

 

容我再哔哔一句,在我看来:

Ioc的实现,可以说一大部分功劳是Spring容器的。

而AOP的实现,可以说一小部分功劳是Spring容器的,但是也是不可或缺的。

 

下面就让我们进入Spring容器创建的源码分析环节!

 

 

首先,我们来看看我们如何触发Spring容器的创建:

 

    @Test
    public void fun1(){
        //使用配置文件,创建容器
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(extConfig.class);
        
        //关闭容器
        ((AnnotationConfigApplicationContext) applicationContext).close();
    }

可以看出来,我们使用的是带有参数的AnnotationConfigApplicationContext("配置类.class")。那么我们通过Debug跟踪容器的创建过程。会发现其实其底层调用了三个方法:

下面这段是Spring的源码截取出来的:

    public AnnotationConfigApplicationContext(Class... annotatedClasses) {
        //调用容器的无参构造器,创建容器
        this();
        //向容器中注册配置类
        this.register(annotatedClasses);
        //调用refresh()方法,该方法执行完毕则Spring容器的创建和初始化就已经完成了
        this.refresh();
    }

我们只需要关注refresh()方法即可,点进refresh()方法,会看到如下的逻辑:

 今天我们的主要任务就是要研究研究这些方法背后的逻辑,搞清楚它们背后的逻辑,也就掌握了Spring容器的创建和初始化。

 

 

第一阶段——Spring容器创建的第一阶段就是容器的创建及一些准备工作。该阶段包含以下四个方法。

 

1.prepareRefresh()方法的执行【为beanFactory的刷新做前置准备】。

 

  1. initPropertySources()方法的执行【设置一些容器的初始化参数】:点进去后我们会发现,这个方法是空的,在我看来这种方法就是留给后来人增强某些特定功能用的,通过继承当前类,对该方法进行重写,然后达到增强容器功能的目的。
  2. getEnvironment().validateRequiredProperties();【校验自己设置的这些容器初始化参数的设置是否符合要求】:因为前面的设置初始化参数方法都是空的,所以这里的校验也是虚的,因为根本就不能设置容器的初始化参数。
  3. earlyApplicationEvents = new LinkedHashSet();【创建一个集合来保存容器创建早期的一些事件,以便待容器创建完毕后多播器将这些事件派发出去】

 

2.ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();【获得刷新后的beanFactory】。

 

1>refreshBeanFactory()[GenericApplicationContext.class的该方法];【刷新beanFactory容器】

       1)点进去后会发现,在构造函数中,存在如下代码,this.beanFactory = new DefaultListableBeanFactory();【创建容 器】。

       2)给容器设置一个序列化过的id,然后返回刚刚创建成功的这个容器。

 

3.prepareBeanFactory(beanFactory);【为创建新创建的好的beanFactory设置一些它作为一个容器应该拥有的东西】。

 

1>设置几个东西

     1)设置类加载器。

     2)设置标准的Bean表达式解析器

2>添加一个组件【一个Bean后处理器】。

3>禁用几个接口实现类的自动注入功能。

     1)EnvironmentAware

     2)ApplicationEventPublisherAware

     3)ApplicationContextAware

     4)ResourceLoaderAware

4>添加一些接口实现类的自动注入功能

     1)BeanFactory

     2)ResourceLoader

     3)ApplicationContext

     4)ApplicationEventPublisher

5>在向容器中添加一个组件【一个Bean后处理器】。

    1)ApplicationListenerDetector

6>如果容器中不包含下面几种组件,就向容器中添加它们。

    1)loadTimeWeaver

    2)environment

    3)systemProperties系统参数【Map<>类型的】

    4)systemEnvironment系统环境【Map<>类型的】

 

4.postProcessBeanFactory()方法,点进去还是空的,留作后面扩展用吧。

 

 

 

第二阶段,容器初始化,开始向容器中注册各个组件。

 

1.invokeBeanFactoryPostProcessors(beanFactory):该方法中迭代的找出所有实现了BeanFactoryPostProcessor接口的实现类,然后一般会出现以下两种情况:

 

在遍历拿到所有的实现了BeanFactoryPostProcessor接口的实现类后,我们会将它们按照执行顺序存在6个集合中:

1.实现了priority order接口且实现类BeanDefinitionRegistryPostProcessor接口的后置处理器

2.实现了order接口且实现类BeanDefinitionRegistryPostProcessor接口的后置处理器。

3.实现了BeanDefinitionRegistryPostProcessor接口的后置处理器。

4.实现了priority order接口且实现类BeanFactoryPostProcessor接口的后置处理器。

5.实现了 order接口且实现类BeanFactoryPostProcessor接口的后置处理器。

6.实现了BeanFactoryPostProcessor接口的后置处理器。

然后按照顺序循环遍历这6个集合,前三个调用它们的

postProcessBeanDefinitionRegistry()方法

后三个调用它们的

postProcessBeanFactory()方法

 

2.registerBeanPostProcessors()方法将容器中已经定义的实现了BeanPostProcessor接口的实现类按照特定的顺序注册到容器中,对后续进行的普通Bean实例的注册进行拦截。一些继承了BeanPostProcessor接口的接口,其执行时机各相同,大概有以下几种:

 

首先,我们来区别两个过程

1、实例化——实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中

2、初始化——初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性

1>实现了BeanPostProceeor:

在bean对象的初始化前后执行。

2>InstantiationAwareBeanPostProcessor:

在bean对象实例化前后执行。

3>DestructionAwareBeanPostProcessor:

关于处理对象销毁的前置回调

4>SmartInstantiationAwareBeanPostProcessor

用来返回目标对象的类型(比如代理对象通过raw class获取proxy type 用于类型匹配),一般用在框架内部,不向外暴露

5>MergedBeanDefinitionPostProcessor

在bean实例化完毕后调用 可以用来修改merged BeanDefinition的一些properties 或者用来给后续回调中缓存一些meta信息使用

 

需要强调的一点就是这里各个bean后处理器的注册也是有顺序的实现了priority order接口的>实现order接口的>什么接口都没有实现的。

 

3.initMessageSource(),初始化messageSource组件【MessageSource用来做国际化,消息绑定,消息解析】。

1>查看容器中是否存在名称为messageSource的组件,如果有,直接拿来用。如果没有,则创建一个DelegatingMessageSource类型的messageSource【messageSource可以从国际化配置文件中取出某个key的值,并且可以按照区域获取信息】。

2>把创建好的messageSource注册回容器中,以便下一次直获取国际化配置文件的时候直接自动注入messageSource。

 

 

4.initApplicationEventMulticaster(),向容器中注册基于事件开发的事件多播器对象。

 

1>看容器中是否有一个名称为“applicationEventMulticaster”的组件,如果有的话,那么就直接获取它。

2>如果没有,就创建一个类型为SimpleApplicationEventMulticaster(beanFactory)的事件多播器对象。

3>将上一步创建的事件多播器对象以“applicationEventMulticaster”的名称注册到容器中。

 

5.onrefresh(),留给子类继承实现个性换配置的。

 

 

6.registerListeners(),将所有的监听器对象添加到多播器对象中,以便后续对事件的派发。

1>迭代拿到容器中所有的事件监听器

2>将所有的事件监听器都添加到多播器中,以方便后续的事件派发

3>拿到事件多播器还没有创建之前就发生的事件,然后派发出去。【earlyApplicationEvents这是一个集合,保存了容器创建早期所发生的事件】

 

 

7.finishBeanFactoryInitialization(beanFactory)方法,创建剩下的所有以定义的普通Bean对象,并注册到容器中。

 

1>beanFactory.preInstantiateSingletons();关注这个方法,这个方法可以帮我们完成剩下所有的普通Bean对象的创建。

 
 

 

preInstantiateSingletons()方法源码如下,本人增加了部分必要的标注:

    public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Pre-instantiating singletons in " + this);
        }
        
        //拿到所有的容器中定义的普通bean信息
        List<String> beanNames = new ArrayList(this.beanDefinitionNames);
        Iterator var2 = beanNames.iterator();
        
        //通过while循环,过滤掉一些不应该被创建的bean
        while(true) {
            while(true) {
                String beanName;
                RootBeanDefinition bd;
                do {
                    do {
                        do {
                            if (!var2.hasNext()) {
                                var2 = beanNames.iterator();

                                while(var2.hasNext()) {
                                    beanName = (String)var2.next();
                                    Object singletonInstance = this.getSingleton(beanName);
                                    if (singletonInstance instanceof SmartInitializingSingleton) {
                                        final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
                                        if (System.getSecurityManager() != null) {
                                            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                                                public Object run() {
                                                    smartSingleton.afterSingletonsInstantiated();
                                                    return null;
                                                }
                                            }, this.getAccessControlContext());
                                        } else {
                                            smartSingleton.afterSingletonsInstantiated();
                                        }
                                    }
                                }

                                return;
                            }

                            beanName = (String)var2.next();
                            bd = this.getMergedLocalBeanDefinition(beanName);
                        } while(bd.isAbstract());//剔除抽象bean
                    } while(!bd.isSingleton());//剔除非单实例bean
                } while(bd.isLazyInit());//剔除设置了懒加载的bean

                //看看当前bean是不是工厂bean,如果是工厂bean那就调用工厂方法创建
                if (this.isFactoryBean(beanName)) {
                    final FactoryBean<?> factory = (FactoryBean)this.getBean("&" + beanName);
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = (Boolean)AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                            public Boolean run() {
                                return ((SmartFactoryBean)factory).isEagerInit();
                            }
                        }, this.getAccessControlContext());
                    } else {
                        isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
                    }

                    if (isEagerInit) {
                        this.getBean(beanName);
                    }
                //如果不是工厂bean,那就调用下面这个方法,进入我们的创建流程    
                } else {
                    this.getBean(beanName);
                }
            }
        }
    }

 

需要对getBean方法做以下说明:

需要说明的一点就是这个getBean(beanName)方法就是我们applicationContext.getBean(beanName)方法【也就是从容器中根据bean名称获取bean实例的那个方法,不过你第一次调用这个方法的时候,就是创建当前获取的Bean对象实例了】

 

可以看出,该方法主要包含了下面五个逻辑步骤。

1)首先会拿到容器中所有普通Bean的定义信息。while循环遍历。

2)使用do-while()判断隔离掉,抽象bean,非单实例bean,和设置懒加载的Bean。

3)判断当前Bean对象是否是FactoryBean,如果是工厂Bean的话,创建方式就和普通Bean有所不同,直接调用对应工厂 的getBean()方法就可以完成当前Bean的创建,也就是说在这一步判断中,完成了工厂Bean的创建和向容器中的注册。

4)如果不是工厂Bean你就采用我们的getBean(beanName)方法创建。

5)当容器中所有的bean都创建完成后,迭代拿到容器中所有的bean对象,寻找实现了SmartInitializingSingleton接口的类并执行其afterSingletonsInstantiated()方法。

 

 

下面是对上面3)步骤的进一步跟进:

getBean(beanName)   调用  doGetBean(beanName...)  调用  getSingleton(beanName)方法。

 

getSingleton(beanName)的主要执行逻辑如下:

1>首先会从从缓存中获取【Map<String, Object> singletonObjects = new ConcurrentHashMap(256);这个就是保存所有spring容器中bean实例的地方,我们把它叫做缓存】。

2>如果拿到了,直接返回。getBean()方法结束。

3>如果拿不到,那就进入当前Bean实例的创建流程

 

下面是对实例创建流程(上面的3>)的逻辑描述

1.标记当前bean已经被创建【markBeanAsCreated(beanName)防止多线程环境下,多个线程同时创建名称相同的bean对象】。

2.获取bean的定义信息【getMergedLocalBeanDefinition(beanName)】。

3.获取当前bean依赖的其它bean【例如:<bean id="YAAG" class="com.ext.Entity.YAAG" depends-on="这里写当前bean创建所需要依赖的bean的名称"></bean>】,如果有依赖的bean且当前依赖的bean未创建,我们还是按照getBean(所依赖的bean的名称)创建该依赖bean,等依赖创建完成后,在转过头来创建当前bean。

4.如果当前bean实例为单实例bean,那么就会调用【createBean(beanName)】创建bean的实例。

1>createBean()方法会首先调用resolveBeforeInstantiation(beanName, mbdToUse);【给beanPostProcessor一个机会返回一个bean实例,一般该bean如果是被AOP增强过的话,就会返回一个代理bean对象】

  1. )该方法内部会拿到当前bean所持有的所有bean后处理器,判断,当前bean需要执行的bean后处理器是否有InstantiationAwareBeanPostProcessors()类型的bean后处理器,如果有则执行下面的操作。

                1-首先触发postProcessBeforeInstantiation()方法。【该方法可能返回一个代理对象或者null】。

                2-如果postProcessBeforeInstantiation()方法有返回值,则会触发postProcessAfterInstantiation()方法。

2>如果没有返回代理对象,或者没有InstantiationAwareBeanPostProcessors()类型的处理器对象,那么就会执行doCreateBean(beanName, mbdToUse, args)方法。

1)调用createBeanInstance(beanName, mbd, args),当这个方法执行完,我们当前bean的实例也就创建出来了【利用工厂方法或者对象的构造器】

2)进入一个同步块,该同步块允许修改创建好的bean实例【bean实例创建好后空空如野,与其说是修改,不如说是装饰】。这个同步块中,拿到所有的bean后处理器,如果存在MergedBeanDefinitionPostProcessor则调用其postProcessMergedBeanDefinition()方法

3)为bean的属性赋值populateBean(beanName, mbd, instanceWrapper),该方法得执行流程如下;

 

1-该方法中会执行postProcessAfterInstantiation(bw.getWrappedInstance(), beanName),也就是InstantionAwareBeanPostProcessor的后置方法。

 

2-再次得到所有的bean后处理器,遍历找到InstantionAwareBeanPostProcessor类型的bean后处理器,执行其postProcessPropertyValues()方法。

 

3-最后调用applyPropertyValues()放啊,利用反射为我们的bean实例的各个属性赋值【setter】。

此时可以说初始化bean得初始化完成!

 

4-执行bean的初始化initializeBean(beanName, exposedObject, mbd);跟进这个方法,该方法得执行流程如下:

1~invokeAwareMethods(beanName, bean);如果你实现了BeanNameAware/BeanClassLoaderAware/BeanFactoryAware那么就会回调这些接口指定的setXXX()方法,将特定的组件注入到指定组件中。

2~调用applyBeanPostProcessorsBeforeInitialization()方法,该方法获取到所有的Bean后处理器对象那个,调用其beanProcessor.postProcessBeforeInitialization(result, beanName)方法。

 

3~调用当前实例上设置的初始化方法【就类似于@Bean(init-method=xxx)】就是执行xxx这个方法。

补充一下三种指定初始化方法的方式:

1.在@Bean注解中执行

2.在实例方法上添加注解@PostConstruct

3.实现InitializingBean接口

 

4~调用applyBeanPostProcessorsAfterInitialization()方法,该方法获取到所有的Bean后处理器对象那个,调用其beanProcessor.postProcessAfterInitialization(result, beanName)方法。

5~注册bean的销毁方法【registerDisposableBeanIfNecessary(beanName, bean, mbd)】。

 

 

 

 

5.将创建好的bean实例保存到SingletonObject集合中,该集合是一个map【addSingleton(beanName, singletonObject);】。

 感悟:

所以说,我们的Ioc容器其实就是很多个map集合拼凑起来的,这些map有的保存我们的单实例bean,有的保存我们的环境信息等等

 

 

第三阶段,容器初始化完毕之后需要完成一些逻辑:

 

1.finishRefresh()方法的执行:

1.initLifecycleProcessor()方法【初始化和生命周期有关的bean后处理器】允许我们写一个LifecycleProcessor接口的实现类,可以在beanFactory的特定阶段,如容器刷新完毕,就会调回调该接口的onrefresh()方法,如果是容器关闭,那就会调用该接口的onclose()方法【默认从容器中找是否存在是实现了LifecycleProcessor接口的组件,如果我们没有自定义,那么会使用容器中默认创建的实现了LifecycleProcessor接口的实现类】。

2.getLifecycleProcessor().onRefresh()【拿到前面定义的生命周期处理器,回调onRefresh()方法】。

3.publishEvent()【该方法发布容器刷新完成事件】。

4.LiveBeansView.registerApplicationContext(this)【不关心!】。

 

 

至此,Spring创建初始化完成!

 

 

四.分析Spring容器创建步骤的一些感悟:

1.Spring容器在启动的时候,先会保存所有定义进来的bean的信息,这些信息的来源有两种:

1.xml文件中的<bean>标签。

2.注解方式完成bean的定义,如:@Bean,@Componenet,@Import等等。

2.Spring容器会在合适的时机创建这些bean,一般会有两个时机

1.Spring容器初始化的时候,创建所有的bean后处理器和单实例非懒加载,非抽象类bean实例。

2.在使用getBean()方法的时候创建多实例bean对象,懒加载的bean对象等等。

3.Bean后处理器(BeanPostProcessor):每一个Bean实例的创建完成前后,都会有很多的bean后处理器对其进行处理,与其说是拦截bean的创建,不如说的增强bean的功能。

4.事件驱动模型

1.ApplicationListener事件监听。

2.ApplicationEventMulticaster事件派发【多播器】。

 

 

 

以上均是本人手工敲出,截图,如有不妥,还望指教,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值