Spring 源码(18)Spring IOC 容器的创建总结

Spring IOC Bean对象的创建总结

根据前面的介绍,可以进行Spring IOC容器创建Bean的总结:

  • 调用构造函数启动,调用过程中父类会忽略调用三个Aware接口,BeanNameAwareBeanClassloaderAwareBeanFactoryAware
  • 环境准备,Environment
    • 实现类StandardEnvironment,调用System.getenv()获取系统环境变量,比如配置的java环境变量等,调用System.getProperties()获取到的系统属性变量,比如当前系统的名称,版本号等。
  • 刷新容器,AbstractApplicationContext#refresh
    • 这个类是BeanFactory的实现类,refresh方法是Spring IOC容器启动的关键
    • 整个IOC容器的生命周期都是围绕着这10几个方法进行展开的
  • 创建IOC容器并加载BeanDefinition,调用obtainBeanFactory方法
    • 创建一个默认的BeanFactoryDefaultListableBeanFactory
    • 加载xml中配置的Bean对象,调用loadBeanDefinitions方法
    • 默认会创建一个BeanDefinitionReader进行读取
    • 创建解析器,用于dtd文件和xsd文件的,默认会加载MATE-INF/spring.schemas文件和MATE-INF/spring.handlers文件
    • 解析传入的xml文件,解析过程中文件资源变化:String[] -->String --> Resource[] --> Resource ,不断的调用重载的方法loadBeanDefinitions,最终解析成Document
    • 将解析的Document文件遍历元素Element,会解析两种元素,一种是默认的,调用parseDefaultElement,比如解析bean标签,另一种是定制的,调用parseCustomElement,比如解析contex:compent-scanutil:map 标签等
    • 解析完之后会创建一个GenericBeanDefinition放入beanDefinitionMapbeanDefinitionNames集合中
  • 准备容器,调用prepareBeanFactory方法
    • 创建一个默认的Spel表达式解析器,StandardBeanExpressionResolver
    • 添加一个属性编辑器的注册器,ResourceEditorRegistrar
    • 添加一个BeanPostProcessor实现类,ApplicationContextAwareProcessor,用于执行6的忽略的Aware接口
    • 忽略6个Aware接口,EnvironmentAwareEmbeddedValueResolverAwareResourceLoaderAwareApplicationEventPublisherAwareMessageSourceAwareApplicationContextAware
  • 执行BeanFactoryPostProcessor,调用invokeBeanFactoryPostProcessors方法
    • 先解析传入的BFPP接口实现类,在解析容器中的BFPP
    • 先解析BeanDefinitionRegistryPostProcessor接口实现,在解析BeanFactoryPostProcessor接口实现
    • 解析到BDRPP,就直接调用postProcessBeanDefinitionRegistry方法,使用集合分别存储BDRPP的接口和BFPP的接口
    • 解析时按照PriorityOrdered接口,Ordered接口,无序的顺序进行解析,执行也是按照这个顺序执行
    • 循环遍历执行BDRPP接口方法postProcessBeanDefinitionRegistryBFPP的方法postProcessBeanFactory
    • 遍历解析BDRPP时会执行到注解的解析类ConfigurationClassPostProcessor
      • 解析@Component注解,解析@ComponentScans@ComponentScan注解,解析@PropertySources@PropertySource注解,解析@ImportResouce注解,解析@Import注解,解析@Bean注解
      • 解析完之后将解析到的BeanDefinition创建为GenericBeanDefinition,然后加入到beanDefinitionMapbeanDefinitionNames集合中
  • 执行BeanPostProcessor的注册,调用registerBeanPostProcessors方法
    • 解析过程跟解析BFPP逻辑类似,只是BPP只是进行了注册,调用了addBeanPostProcessor方法
  • 执行国际化设置,多播器设置,监听器注册
  • 执行剩余的非懒加载的单例的初始化,调用finishBeanFactoryInitialization方法
    • 加载一个转换服务,ConversionService,用于类型转换使用
    • 添加一个默认的占位符解析器,PropertySourcesPlaceHolderConfigurer
    • 冻结BeanDefinition的元数据
    • 实例化所有的非懒加载的单例Bean,调用preInstantiateSingletons方法
      • 遍历所有的BeanDefinition开始创建Bean
      • 合并BeanDefinition
      • 判断是否是FactoryBean,如果是则后续通过getObject方法进行创建Bean,如果是的单例的然后放入缓存中,下次使用直接获取
      • 调用getBean方法获取Bean对象
      • 调用doGetBean
        • 调用getSingleton获取bean
          • 首先是从一级缓存singletonObjects中获取,如果有则直接返回
          • 一级缓存中没有,并且当前Bean正在创建,先从一级缓存再获取一次,没有的话那么从二级缓存earlySingletonObjects中获取,如果有则直接返回
          • 二级缓存中没有,那么就从三级缓存singletonFactories中获取,获取到之后放在二级缓存中,然后删除三级缓存的Bean
        • 如果获取到bean对象,那么就去检查是否是FactoryBean对象,如果不是直接返回,否则判断是否带有& 符号,如果带了那么就直接返回,没有带& 那么就会调用缓存获取,获取不到就会执行getObject方法进行创建对象,如果是单例的就会存入缓存中
        • 判断bean的创建类型,如果是单例的,那么就会调用getSingleton方法,然后入参传入一个lambda表达式进行创建,lambda表达式是一个ObjectFactory接口,首先将bean加入到正在创建的集合中,然后调用getObject方法触发lambda表达式中的createBean方法,最终创建完之后加入到一级缓存中,并且从正在创建的集合中移除
        • 调用createBean方法
          • 解析Bean的类型
          • 判断是否进行方法覆盖,如果需要则进行方法覆盖,比如配置了lookup-methodreplace-method标签,方法覆盖的作用是单例对象引用多例对象的场景下使用
          • 给一个机会对实现了InstantiationAwareBeanPostProcessor接口的Bean进行对象的创建,会调用到postprocessBeforeInstantiation方法进行提前实例化
          • 如果没有提前创建对象,那么会调用doCreateBean方法
          • 调用doCreateBean方法
            • 先进行实例化创建对象,调用createBeanInstance方法
              • 判断BeanDefinition是否设置了supplier,如果设置了那么就通过supplier进行实例化
              • 判断BeanDefinition是否配置了factory-method,如果配置了那么会使用静态工厂或者实例工厂进行对象的实例化创建,静态工厂是直接调用静态方法进行对象的获取,实例工厂是需要配置factory-bean 标签进行配合,然后调用factory-bean指定的bean的方法进行对象的获取
              • 如果上面的两种都没有,那么判断是否解析过,如果解析过就会调用反射去实例化创建
                • 首先是获取一个对象实例化策略,然后调用instantiate方法进行反射创建
                • 创建之后将对象包装到BeanWrapper包装器中
                • 然后初始化bean的包装器,里面是设置了转换服务ConversionService,还有就是对象的属性编辑器的注册PropertyEditorRegistrar ,这两个用于后面进行属性填充时对属性值进行解析
              • 如果上面的不满足,那么就会通过SmartInstantiationAwareBeanPostProcessor 去获取构造函数,然后进行自动构造实例化对象
              • 如果也不是,那么就直接调用反射进行创建,创建的是通过无参构造函数进行创建的
              • 最后会将创建的对象封装到BeanWrapper中,然后进行Bean的包装,比如设置转换服务ConversionService和属性编辑器PropertyEditorRegistrar,这里的转换服务和属性编辑器都是可以在自定义的,不过Spring内置了很多,大多数场景下都可以不用自己写,使用Spring提供的都完全够用了
            • 合并BeanDefinition
              • 这里会调用BeanPostProcessor的子接口MergedBeanDefinitionPostProcessor进行合并,主要是为了解析BeanDefinition中的其他注解,比如@Value@Autowired@Resource@PostConstruct@PreDestory等注解
              • MergedBeanDefinitionPostProcessor接口的实现比较重要的有AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessorInitDestroyAnnotationBeanPostProcessor这几各类,他们主要完成了上面提到的几个注解的解析
              • BeanPostProcessor接口下多个子接口:InstantiationAwareBeanPostProcessorSmartInstantiationAwareBeanPostProcessorMergedBeanDefinitionPostProcessorDestructionAwarePostProcessor,这些接口都比较重要
            • 提前暴露Bean(主要是用于解决循环依赖)
              • 先判断Bean是否是单例的,是否允许循环依赖,是否单例Bean正在创建
              • 如果条件满足,那么就调用addSingletonFactory,传入一个lambda表达式,传入的是一个ObjectFactory接口,里面调用的是SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference方法,这个方法会在后面的属性填充时从缓存中获取不到Bean时进行调用,如果没有进行代理,那么会直接返回,不会执行getEarlyBeanReference方法
            • 属性填充populateBean
              • 给机会使用InstantiationAwareBeanPostProcessorBean进行修改,会调用postProcessAfterInstantiation方法
              • 根据注入方式进行属性注入,按类型还是按名称两种
              • 判断是否存在InstantiationAwareBeanPostProcessor接口的实现,如果存在那么会调用postProcessProperties方法进行属性的填充,比如属性标了@Autowired@Resource注解的属性
              • 属性值处理
                • 获取前面步骤解析的属性字段和属性值
                • 获取属性值解析器BeanDefinitionValueResolver
                • 循环遍历解析属性,使用属性值解析器解析
                  • 判断属性值是什么类型的,比如RuntimeReferenceBeanDefinitionSetListMapArrayString等类型
                  • 根据类型会进行类型的转换,最终会调用到前面添加的属性编辑器PropertiesEditorRegistrar或者转换服务ConversionService进行类型的转换
                  • 也可能会调用前面添加的Spel表达式解析器进行解析
                  • 这里会存在大量的递归调用
            • 初始化Bean --->initializeBean
              • 执行Aware方法,invokeAwareMethods,这里只会执行三个Aware方法
                • 执行BeanNameAware接口
                • 执行BeanClassLoaderAware接口
                • 执行BeanFactoryAware接口
              • 调用BeanPostProcessorbefore方法
                • 这里会调用到两个比较重要的类,一个是ApplicationContextAwareProcessor执行另外的6个Aware接口,一个是InitDestoryAnnotationBeanPostProcessor接口执行@PostConstruct注解标记的方法
              • 调用初始化方法invokeInitMethods
                • 如果bean实现了InitializingtionBean,那么就去调用它的afterPropertiesSet方法
                • 如果自定义了init-method方法,那么就去调用自定义的初始化方法
              • 调用BeanPostProcessorafter方法
                • 主要是调用AbstractAutoProxyCreator进行aop的动态代理的调用,也是实现aop的关键

posted @ 2022-05-24 22:54  玲丶蹊  阅读(253)  评论(0编辑  收藏  举报