1)创建xml容器
new ClassPathXmlApplicationContext,其中会调用refresh方法;
2)进入refresh方法AbstractApplicationContext#refresh
3)实例化非懒加载状态的单实例,
AbstractApplicationContext#finishBeanFactoryInitialization(beanFactory)
4)预初始化非懒加载状态的单实例,
DefaultListableBeanFactory#preInstantiateSingletons,遍历所有的beanNames;
5)若不是FactoryBean则直接调用AbstractBeanFactory# getBean(beanName)方法,否则加在beanName前加前缀&提前调用,这个地方感觉写得有些重复。
6)调用getSingleton(beanName)方法,尝试从缓存中获取共享单实例。
6.1)执行this.singletonObjects.get(beanName),从一级缓存中拿,若为null,则表示尚未创建或正在创建,若此时singletonsCurrentlyInCreation集合中也没有该beanName,则表明该beanName实例是尚未创建,否则是正在创建;若当前beanName实例尚未创建则当前getSingleton方法直接返回null,在getBean方法中继续往下执行,创建beanName的早期实例加入到三级缓存;
6.2)若当前beanName实例正在创建中,则一定是循环依赖导致的再次进入到当前getSingleton(beanName)方法,此时会继续判断一级,二级,三级缓存,这里用到了单例模式的double check;
6.3)若一级,二级缓存中有当前beanName实例,则返回,否则去在三级缓存中找;此时执行singletonFactories.get(beanName)返回ObjectFactory实例singletonFactory一定不为null;
6.4)接着执行singletonFactory.getObject方法,会回调当前beanName在三级缓存中对应方法getEarlyBeanReference方法;此时会调用smartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法,该方法主要是为了判断beanName的早期实例是否需要被增强,若需要则返回增强后的;beanName和getEarlyBeanReference方法是在beanName早期实例刚创建后的第一时间被加入进三级缓存的,其中beanName的早期实例作为getEarlyBeanReference方法的入参;
6.5)接着将beanName和早期实例加入到二级缓存,从三级缓存中删除早期实例;
7)若getSingleton(beanName)返回null,我们应该自己创建了;
原型依赖直接报错BeanCurrentlyInCreationException
<bean name=“A” depends-on=“B” … />与<bean name=“B” depends-on=“A” …/>依赖直接报错
8)若bean为单实例bean,则执行Object sharedInstance = getSingleton(beanName, () -> {try { return createBean(beanName, mbd, args);}方法,第二个参数是ObjectFactory类型;
8.1)该方法中首先执行beforeSingletonCreation方法,往正在创建的集合中添加当前beanName,起到了检查是否由有参构造方法造成的循环依赖的作用,由于有参构造方法导致的循环不会创建beanName的早期实例,导致步骤6)每次都返回null,从而代码每次都要执行到步骤8),所以当getBean(A)时,先会将A加到正在创建的集合中,接着发现构造方法入参有B,此时还没来得及创建A的早期实例,就要执行getBean(B),此时又会将B加到正在创建的集合中,接着又发现B的构造方法入参中有A,还没来得及创建B的早期实例,又要调用getBean(A),此时执行上述步骤6)返回null,再次会来到步骤8),而field和setter注入方式下的的循环依赖由于会创建早期实例,所以执行第二次getBean(A)的时候,就会从三级缓存中拿到早期实例,而不会走到步骤8);所以走到步骤8)的一定是有参构造下的循环依赖导致的,判断方法就是正在创建的集合中是否含有当前beanName,有的话就报异常;
8.2)接着执行singletonObject = singletonFactory.getObject()方法,此处的singletonFactory是当前getSingleton方法的第二个入参,此时会执行createBean方法;
8.3)执行afterSingletonCreation(beanName)将当前实例从正在创建的集合中移除;
8.4)执行addSingleton(beanName, singletonObject)方法,将初始化后的实例即完全创建好的实例加入到一级缓存,删除三级缓存中bean对应的ObjectFactory实例,删除二级缓存中bean对应的早期实例,最后将beanName加入到已注册集合中表示当前完整的一个bean实例已创建好了;
9)上述getSingleton方法执行结束后返回完全创建好的beanName实例sharedInstance,会执行beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd)
方法;
9.1)若name带有&且beanInstance为factoryBean类型,则返回FactoryBean实现类对象;
9.2)若name不带&且beanInstance不为FactoryBean类型,则返回普通单实例;
9.3)若name不带&且beanInstance为FactoryBean类型,则返回FactoryBean实现类内部管理的beanName实例,通过factoryBean的getObject方法可以拿到其内部管理的beanName实例;
以下是AbstractAutowireCapableBeanFactory#createBean方法的部分,主要完成bean实例化,bean依赖注入,初始化,以及各种bean的生命周期的后处理器使用。
接着上边8.2)开始;
8.2.1)其中会执行spring生命周期第一个后处理器应有Object bean = resolveBeforeInstantiation(beanName, mbdToUse),其中调用了postProcessBeforeInstantiation方法,在实际应用中,我们可以实现InstantiationAwareBeanPostProcess接口,重写postProcessBeforeInstantiation方法,方法中自定义逻辑,返回一个我们需要的bean代替原本bean,则后续只有postProcessAfterInitialization会被调用,其他方法不再调用。
8.2.2)AbstractAutowireCapableBeanFactory#createBean #doCreateBean,其中createBeanInstance方法是实例化bean得到早期实例;
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))是将早期实例加到三级缓存中;populateBean方法执行依赖注入;initializeBean方法初始化bean;
8.2.2.1)createBeanInstance方法中有如下三个重要方法:
a)当@Autowired 注解打在了 构造器方法上,会使用如下方法收集相关构造方法
AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors,此方法的含义是解析Bean类里构造函数上的@Autowired注解。这里调用了spring生命周期第二个后置处理SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors方法。
b)AbstractAutowireCapableBeanFactory#autowireConstructor,其中会调用ConstructorResolver#autowireConstructor#resolvePreparedArguments方法将构造器依赖的bean进行初始化,如果有合适的标识了@Autowired的构造函数,则在实例化此Bean时会使用此构造函数。
AutowiredAnnotationBeanPostProcessor筛选@Autowired标识的构造函数,筛选出这些构造函数之后,Spring使用ConstructorResolver这个类来择取合适的构造函数,流程如下:
b.1)首先对这些构造函数按修饰符优先public排序,修饰符相同再按参数的长短排序,最先解析参数最长的public修饰的构造函数,其优先级最高.
b.2)如果每一个参数均能从Spring容器中找到合适的Bean,则此将此构造函数作为最优解,如果容器内Bean不能满足所有参数,则解析下一个构造函数。
b.3)如果存在两个参数长度相同的构造函数,且容器内Bean均能满足参数解析,则按参数类型和Bean类型的差异性求取参数的差异权重,比如参数是接口,Bean是实现类,则差异加2,参数是集合,Bean是单个类,则转换成集合,差异加2等等,比较两个构造函数的差异权重大小,差异小的那个作为最优解。如果两个差异权重相等,则抛出含有模棱两可的构造函数的BeanCreationException。
b.4)当有了最优解的构造函数后,如果下一个构造函数的参数长度等于最优解,则解析此构造函数,如果参数长度小于最优解,则不再解析,直接忽略之后的所有构造函数。
b.5)当得到了构造函数最优解之后,将此构造函数存入此Bean的BeanDefinition中,以备下次复用,就是说只对构造函数候选者集合解析一次,下次实例化Bean的时候可以直接得到这个最优解。
以上的情况是基于Spring容器实例化Bean的情况,就是实例化时不会附带Arguments,就是不带参数,如果是使用者自己实例化Bean时,通过BeanFactory的 Object getBean(String name, Object… args) throws BeansException; T getBean(Class requiredType, Object… args) throws BeansException;方法实例化时,按照构造函数的顺序传入实例化参数,则Spring在找合适的构造函数时会忽略之前缓存的最优解,以同样的顺序解析构造函数候选者集合,看看哪些构造函数的参数适合传入的参数,找不到合适的则跑出BeanCreationException。
c)AbstractAutowireCapableBeanFactory#instantiateBean,未指定构造参数,未设定偏好,使用默认的无参数的构造方法进行创建实例。假设此时走的是这条路,即通过Class拿到无参的Constructor构造器,进行反射创建对象,得到一个早期对象,filed和setter注入方式就是依靠无参构造方法创建早期实例进而解决循环依赖问题。
执行完createBeanInstance后,返回一个bean的早期实例,早期实例指的是没有进行依赖注入的bean实例;
8.2.2.2)AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors调用spring的bean生命周期第三个后置处理器,收集注入的元信息,其中调用MergedBeanDefinitionPostProcessor类型的方法
postProcessMergedBeanDefinition。
8.2.2.3)AbstractAutowireCapableBeanFactory#addSingletonFactory方法将A的早期对象封装成ObjectFactory放入三级缓存中,其中key为beanName,value为一个匿名内部类(拉姆达表达式),匿名内部类的核心方法是getEarlyBeanReference,这是spring的bean生命周期的第四个后置处理器,其中调用了SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法,主要用于判断早期实例是否需要增强,若需要增强,则返回增强后的bean早期实例,否则调用getEarlyBeanReference方法后,直接返回bean的早期实例;
8.2.2.4)populateBean方法处理依赖注入,如果条件满足,调用spring的bean生命周期第五个后置处理器,其中调用了InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法,可以实现InstantiationAwareBeanPostProcessor接口,重写postProcessAfterInstantiation方法,规定哪些bean不走populate剩下的注入逻辑;接着处理Autowire的byType,byName相关逻辑;接着会调用InstantiationAwareBeanPostProcessor后置处理器的postProcessProperties方法,这是spring生命周期第六个后置处理器,和生命周期第三个后置处理器是配对工作的,第三个处理器是构建出来InjectionMetadata,第六个是使用InjectionMetadata,调用metadata的inject方法,完成依赖注入。populate方法中最后一个方法是applyPropertyValues方法,将依赖注入合并后的pvs应用到真实实例中。
8.2.2.5)initializeBean方法,首先会调invokeAwareMethods方法,这是bean生命周期中第一个单独调用的方法,检查bean是否为BeanNameAware,BeanClassLoaderAware,BeanFactoryAware类型,若是,则执行bean中相应的setXXX方法。接着会调用BeanPostPorcessor的postProcessBeforeInitialization方法,这是bean生命周期中第七个后置处理器,检查bean是否实现了类似于ApplicationContextAware接口,若是,则调用bean中的setApplicationContext(xx),其中参数为applicationContext容器,即可以拿到容器进行相关处理。接着调用invokeInitMethods方法,这是bean生命周期中第二个单独调用的方法,至此,bean就完全创建好了(包括实例化,注入,初始化);最后会调用BeanPostPorcessor的postProcessAfterInitialization方法,这是bean生命周期中第八个后置处理器,处理AOP相关,看bean是否需要被代理增强。
8.2.2.6)registerDisposableBeanIfNecessary,判断当前bean是否需要注册析构回调,当容器关闭时,会进行回调。会判断是否有DestructionAwareBeanPostProcessors,进行相应回调操作,这是bean生命周期中第九个后置处理器。