Spring自动扫描装配bean大体流程

1. 标签的扫描解析

解析配置文件,遇到标签,该标签属于自定义标签,该自定义标签的命名空间对应的NamespaceHandler的实现类是ContextNamespaceHandler,在ContextNamespaceHandler下注册了一个BeanDefinitionParser,具体实现类为ComponentScanBeanDefinitionParser.由ComponentScanBeanDefinitionParser完成对标签的解析和扫描注解bean的工作.

2. ComponentScanBeanDefinitionParser完成的工作

  • 获取扫包路径.
  • 创建一个ClassPathBeanDefinitionScanner并进行相应扫描属性配置,将bean definition的解析和注册工作委托给这个ClassPathBeanDefinitionScanner来处理.
  • 执行扫描scanner.doScan方法.对每个扫包路径循环执行:
    1. 扫描扫包路径以获取candidate components,具体为获取扫包路径下所有.class文件路径,每个.class文件作为一个Resource资源进行解析.
      1.1 过滤出符合要求的class(基本上主要是获取@component注解标注的类)
      1.2 进行一些其他设置
      1.3 再次过滤,需要保证该类不是接口,不是抽象类,底层类是独立的能够独立构造,符合条件的添加到结果集Set
      1.4 返回结果集
    2. 对1中返回的结果集Set candidates中的每一项做循环处理:
      2.1 一些属性配置,beanName生成,scope配置,一些属性默认值设置(lazyInit,autowireMode,initMehtod,destroyMethod等等)
      2.2 做一些属性覆盖(根据注解中的属性设置,对2.1中设置的默认属性进行覆盖)
      2.3 注册BeanDefinitionHolder到registry
  • 注册一些BeanPostProcessor和BeanFactoryPostProcessor来完成后续处理工作.(@autowired注解自动注入的实现就是通过AutowiredAnnotationBeanPostProcessor来实现的,更具体的,通过实现InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法来实现注入).

3. AutowiredAnnotationBeanPostProcessor完成的工作

  • 获取注入元数据InjectionMetadata
    1. 缓存中取元数据.
      1.1 不需要更新则直接返回;
      1.2 需要更新(包括缓存中元数据信息为空或者缓存的元数据信息中目标类型class对象与当前bean的class类型不匹配)则重新构建元数据
       1.2.1 如果原来的元数据不为null,则清空原来的元数据
       1.2.2 构建元数据,通过反射处理每一个field和method,把@autowired注解标注的属性或方法添加到需注入元素列表LinkedList elements中,以从子类开始往上向父类的顺序,循环执行.以class类型和上述构造好的该bean下对应的elements列表构造元数据InjectionMetadata并返回
       1.2.3 将元数据写入缓存,并返回元数据
  • 执行注入,遍历元数据InjectionMetadata中的injectedElements,对每个待注入元素执行注入
    1. 若已缓存,从缓存中获取
    2. 若未缓存,执行解析(包括Array、Collection、Map、和普通属性类的注入)
    3. 通过反射进行注入

你可能感兴趣的:(Spring自动扫描装配bean大体流程)