1. <context:component-scan/>标签的扫描解析
解析配置文件,遇到<context:component-scan/>标签,该标签属于自定义标签,该自定义标签的命名空间对应的NamespaceHandler的实现类是ContextNamespaceHandler,在ContextNamespaceHandler下注册了一个BeanDefinitionParser,具体实现类为ComponentScanBeanDefinitionParser.由ComponentScanBeanDefinitionParser完成对<context:component-scan/>标签的解析和扫描注解bean的工作.
2. ComponentScanBeanDefinitionParser完成的工作
- 获取扫包路径.
- 创建一个ClassPathBeanDefinitionScanner并进行相应扫描属性配置,将bean definition的解析和注册工作委托给这个ClassPathBeanDefinitionScanner来处理.
- 执行扫描scanner.doScan方法.对每个扫包路径循环执行:
- 扫描扫包路径以获取candidate components,具体为获取扫包路径下所有.class文件路径,每个.class文件作为一个Resource资源进行解析.
1.1 过滤出符合要求的class(基本上主要是获取@component注解标注的类)
1.2 进行一些其他设置
1.3 再次过滤,需要保证该类不是接口,不是抽象类,底层类是独立的能够独立构造,符合条件的添加到结果集Set<BeanDefinition>中
1.4 返回结果集 - 对1中返回的结果集Set<BeanDefinition> candidates中的每一项做循环处理:
2.1 一些属性配置,beanName生成,scope配置,一些属性默认值设置(lazyInit,autowireMode,initMehtod,destroyMethod等等)
2.2 做一些属性覆盖(根据注解中的属性设置,对2.1中设置的默认属性进行覆盖)
2.3 注册BeanDefinitionHolder到registry
- 扫描扫包路径以获取candidate components,具体为获取扫包路径下所有.class文件路径,每个.class文件作为一个Resource资源进行解析.
- 注册一些BeanPostProcessor和BeanFactoryPostProcessor来完成后续处理工作.(@autowired注解自动注入的实现就是通过AutowiredAnnotationBeanPostProcessor来实现的,更具体的,通过实现InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法来实现注入).
3. AutowiredAnnotationBeanPostProcessor完成的工作
- 获取注入元数据InjectionMetadata
- 缓存中取元数据.
1.1 不需要更新则直接返回;
1.2 需要更新(包括缓存中元数据信息为空或者缓存的元数据信息中目标类型class对象与当前bean的class类型不匹配)则重新构建元数据
1.2.1 如果原来的元数据不为null,则清空原来的元数据
1.2.2 构建元数据,通过反射处理每一个field和method,把@autowired注解标注的属性或方法添加到需注入元素列表LinkedList<InjectionMetadata.InjectedElement> elements中,以从子类开始往上向父类的顺序,循环执行.以class类型和上述构造好的该bean下对应的elements列表构造元数据InjectionMetadata并返回
1.2.3 将元数据写入缓存,并返回元数据
- 缓存中取元数据.
- 执行注入,遍历元数据InjectionMetadata中的injectedElements,对每个待注入元素执行注入
- 若已缓存,从缓存中获取
- 若未缓存,执行解析(包括Array、Collection、Map、和普通属性类的注入)
- 通过反射进行注入
网友评论