基于 Annotation 的依赖注入

1.AnnotationConfigApplicationContext对注解Bean初始化:
Spring中,管理注解Bean定义的容器有两个:AnnotationConfigApplicationContext和AnnotationConfigWebApplicationContex。这两个类是专门处理Spring注解方式配置的容器,直
接依赖于注解作为容器配置信息来源的IOC容器。AnnotationConfigWebApplicationContext是AnnotationConfigApplicationContext的web版本,两者的用法以及对注解的处理方式几乎没有什么差别。

看看AnnotationConfigApplicationContext的源码:

基于 Annotation 的依赖注入基于 Annotation 的依赖注入基于 Annotation 的依赖注入通过对AnnotationConfigApplicationContext的源码分析,我们了解到Spring对注解的处理分为两种方式:
(1).直接将注解Bean注册到容器中:
可以在初始化容器时注册;也可以在容器创建之后手动调用注册方法向容器注册,然后通过手动刷新容器,使得容器对注册的注解Bean进行处理。

(2).通过扫描指定的包及其子包下的所有类:

在初始化注解容器时指定要自动扫描的路径,如果容器创建以后向给定路径动态添加了注解Bean,则需要手动调用容器扫描的方法,然后手动刷新容器,使得容器对所注册的Bean进行处理。接下来,将会对两种处理方式详细分析其实现过程。

3.AnnotationConfigApplicationContext注册注解Bean
当创建注解处理容器时,如果传入的初始参数是具体的注解Bean定义类时,注解容器读取并注册。

(1).AnnotationConfigApplicationContext通过调用注解Bean定义读取器AnnotatedBeanDefinitionReader的register方法向容器注册指定的注解Bean,注解Bean定义读取器向容器注册注解Bean的源码:

基于 Annotation 的依赖注入基于 Annotation 的依赖注入从上面的源码我们可以看出,注册注解Bean定义类的基本步骤:
a,需要使用注解元数据解析器解析注解Bean中关于作用域的配置。
b,使用AnnotationConfigUtils的processCommonDefinitionAnnotations方法处理注解Bean定义类中通用的注解。
c,使用AnnotationConfigUtils的applyScopedProxyMode方法创建对于作用域的代理对象。
d,通过BeanDefinitionReaderUtils向容器注册Bean。
下面我们继续分析这3步的具体实现过程

(2).AnnotationScopeMetadataResolver解析作用域元数据:AnnotationScopeMetadataResolver通过processCommonDefinitionAnnotations方法解析注解Bean定义类的作用域元信息,即判断注册的Bean是原生类型(prototype)还是单态(singleton)类型,其源码:

基于 Annotation 的依赖注入上述代码中的 annDef.getMetadata().getAnnotationAttributes 方法就是获取对象中指定类型的注解的值

(3).AnnotationConfigUtils 处理注解 Bean 定义类中的通用注解
AnnotationConfigUtils 类的 processCommonDefinitionAnnotations 在向容器注册 Bean 之前,

首先对注解 Bean 定义类中的通用 Spring 注解进行处理, 源码

基于 Annotation 的依赖注入基于 Annotation 的依赖注入

(4).AnnotationConfigUtils 根据注解 Bean 定义类中配置的作用域为其应用相应的代理策略

AnnotationConfigUtils 类的 applyScopedProxyMode 方法根据注解 Bean 定义类中配置的作用域@Scope 注解的值, 为 Bean 定义应用相应的代理模式, 主要是在 Spring 面向切面编程(AOP)中使用。源码:

基于 Annotation 的依赖注入

(5).BeanDefinitionReaderUtils 向容器注册 Bean

BeanDefinitionReaderUtils向容器注册载入的Bean前面博客中已经分析过,主要是校验Bean 定义,然后将 Bean 添加到容器中一个管理Bean定义的HashMap中,这里就不做分析。

2.AnnotationConfigApplicationContext 扫描指定包及其子包下的注解 Bean

当创建注解处理容器时, 如果传入的初始参数是注解 Bean 定义类所在的包时, 注解容器将扫描给定的包及其子包, 将扫描到的注解包及其子包, 将扫描到的注解 Bean 定义载入并注册。

(1).ClassPathBeanDefinitionScanner 扫描给定的包及其子包:
AnnotationConfigApplicationContext 通 过 调 用 类 路 径 Bean 定 义 扫 描 器ClassPathBeanDefinitionScanner 扫描给定包及其子包下的所有类, 主要源码如下
基于 Annotation 的依赖注入基于 Annotation 的依赖注入基于 Annotation 的依赖注入基于 Annotation 的依赖注入

类路径Bean定义扫描器ClassPathBeanDefinitionScanner主要通过findCandidateComponents方法调用其父类ClassPathScanningCandidateComponentProvider类来扫描获取给定包及其子包下的类。

(2).ClassPathScanningCandidateComponentProvider 扫描给定包及其子包的类
ClassPathScanningCandidateComponentProvider类的findCandidateComponents方法具体实现

扫描给定类路径包的功能,源码:

基于 Annotation 的依赖注入基于 Annotation 的依赖注入基于 Annotation 的依赖注入基于 Annotation 的依赖注入基于 Annotation 的依赖注入基于 Annotation 的依赖注入

3.AnnotationConfigWebApplicationContext 载入注解 Bean 定义

AnnotationConfigWebApplicationContext AnnotationConfigApplicationContext Web 版,它们对于注解 Bean 的注册和扫描是基本相同的, 但是 AnnotationConfigWebApplicationContext对注解 Bean 定义的载入稍有不同, AnnotationConfigWebApplicationContext 注入注解 Bean 定义源码:

基于 Annotation 的依赖注入基于 Annotation 的依赖注入

解析和注入注解配置资源的过程分析


上一篇: 基于 XML 的依赖注入

下一篇: IOC容器中常用扩展点