• Spring5.2.x04BeanDefinitionMap


    ApplicationContext
    AnnotationConfigAppplicationContext

    AnnotationConfigApplicationContext实例化

    • 调用父类构造方法时new出来的beanFactory = new DefaultListableBeanFactory();

    • reader = new AnnotatedBeanDefinitionReader(this), 他的register方法可以把类变成BeanDefinition对象
      AnnotatedBeanDefinitionReader会调用父类AnnotatedBeanDefinitionReader实例化方法的时候, AnnotationConfigUtils.registerAnnotationConfigProcessors方法, 注册spring自带的BeanDefinition
      - org.springframework.context.annotation.internalConfigurationAnnotationProcessor(名字) ConfigurationClassPostProcessor(最重要的类)
      - org.springframework.context.annotation.internalAutowiredAnnotationProcessor AutowiredAnnotationBeanPostProcessor(解析@Autowired)
      - org.springframework.context.annotation.internalCommonAnnotationProcessor CommonAnnotationBeanPostProcessor(其中一个功能是解析@Resource)
      - org.springframework.context.event.internalEventListenerProcessor EventListenerMethodProcessor
      - org.springframework.context.event.internalEventListenerFactory DefaultEventListenerFactory

    • scanner = new ClassPathBeanDefinitionScanner(this);

    BeanFactory
    DefaultListableBeanFactory中的重要对象

    • beanDefinitionMap(是一个ConcurrentHashMap)

    BeanDefinition中的重要对象

    • beanClass 与之对应的对象

    AbstractApplicationContext#invokeBeanFactoryPostProcessors()方法

    • 获取到的BeanFactoryPostProcessor
      xml或者带注解
      通过addBeanFactoryPostProcessor进来的

    Spring里谁先谁后?

    • 实现BeanFactoryPostProcessor和实现BeanDefinitionRegistryPostProcessor
    • 实现spring内置的还是实现程序员提供的BeanFactoryPostProcessor
    • 自己提供的分为注解提供的, api提供的
    • 在子类的回调方法中继续注册, 会被扫描
    • 实现PriorityOrdered接口
    • 实现Order接口

    父类是不能再注册BeanDefinition

    AbstractApplicationContext.refresh里面的invokeBeanFactoryPostProcessors, 做了很多事, 其中有意见就是扫描注册BeanDefinition

    context.register(ContextConfig.class);和context.scan("com.test.context.bfpp");是两套扫描器, 可能会影响最初的执行过程

    扫描

    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()

    • // 防止重复执行
      Set processedBeans = new HashSet<>();

    分类执行
    // 父类 存储所有实现了 BeanFactoryPostProcessor 的 bean
    List regularPostProcessors = new ArrayList<>();
    // 子类 代表子类方法已经执行过了 存放所有实现了 BeanDefinitionRegistryPostProcessor 的 bean
    List registryProcessors = new ArrayList<>();

    通过api add的类, 循环list

    子类: 调用其回调方法
    registryProcessor.postProcessBeanDefinitionRegistry(registry)
    加到子类list里
    父类: 加到父类list里

    接着找子类实现PriorityOrdered接口

    之后根据类型查询, 到 BeanDefinitionMap 当中查找 BeanDefinitionRegistryPostProcessor(子类)的实现类, 返回名字
    目前BeanDefinitionMap 只有spring内置注册的 ConfigurationClassPostProcessor
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    同时ConfigurationClassPostProcessor实现PriorityOrdered接口, 会被实例化
    执行ConfigurationClassPostProcessor的子类方法

    接着找子类实现Ordered接口

    接着死循环直接执行子类的方法, 如果有未执行的子类, 就继续while循环

    因为可以在子类的方法里手动注册未加注解的类

    执行子类的父类方法

    执行通过api add的实现父类的类的父类方法

    准备实现priorityOrdered,order和没有实现order接口共三个list

    找个各自的实现, 先执行实现priorityOrdered的父类方法, 再执行实现order的父类方法, 最后执行没有实现order接口的方法

    BeanDefinitionRegistryPostProcessor 和 ImportBeanDefinitionRegistrar(只能通过@Import注入, 加@Component是没用的) 的执行顺序

    先执行内置实现BeanDefinitionRegistryPostProcessor如ccpp, 在执行@Import的ImportBeanDefinitionRegistrar, 再执行通过扫描实现BeanDefinitionRegistryPostProcessor的类

    BeanDefinitionRegistryPostProcessor 和 ImportBeanDefinitionRegistrar 有什么区别

    ImportBeanDefinitionRegistrar 的回调参数多一个 AnnotationMetadata, 可以拿到注解里的值

    Bean的注入, ImportBeanDefinitionRegistrar 或者 通过api, 反正要比 <=ccpp, 在ccpp之前或同期, 要把 beanDefinition 注册好

    ignore 某些bean

  • 相关阅读:
    iis7 绑定多个ssl证书
    公众号微信消息接口官方demo
    前端HTML入门教程,一篇文章搞定,你就是web前端行内人了
    很多优秀的程序员,都有一个好习惯,这个习惯就是做博客写文章
    JavaScript入门到精通,需要掌握的技能盘点
    感觉CSS学习起来很难?很恐惧,消除恐惧的权威CSS学习指南来了
    这5个可以提高前端开发效率的 Chrome扩展程序,建议你尝鲜体验下
    那些你从不使用的 HTML 属性,背后竟然大有文章,赶快了来了解下
    按键消抖实验
    状态机练习 基于EEPROM的I2C 随机读、写
  • 原文地址:https://www.cnblogs.com/richardhaha/p/16557281.html
Copyright © 2020-2023  润新知