内容简介:上篇文章研究Spring 框架中有很多可用的注解,其中有一类注解称模式注解(Stereotype Annotations),包括需要配置开启自动扫描。如在 XML 中配置 <context:component-scan base-package="xxx.xxx.xx"/>` 或使用注解 @ComponentScan。
上篇文章研究 Spring XML Schema 扩展进制 ,这段时候一直研究 Spring 注解编程的原理。原本以为有了之前研究基础,可以很快理解注解编程原理。没想到这个过程非常困难,注解编程源码难度是 XML 扩展好几倍。o(╥﹏╥)o。
Spring 框架中有很多可用的注解,其中有一类注解称模式注解(Stereotype Annotations),包括 @Component , @Service , @Controller , @Repository 等。只要在相应的类上标注这些注解,就能成为 Spring 中组件(Bean)。
需要配置开启自动扫描。如在 XML 中配置 <context:component-scan base-package="xxx.xxx.xx"/>` 或使用注解 @ComponentScan。
从最终的效果上来看, @Component , @Service , @Controller , @Repository 起到的作用完全一样,那为何还需要多个不同的注解?
从官方 wiki 我们可以看到原因。
A _ stereotype annotation _ is an annotation that is used to declare the role that a component plays within the application. For example, the @Repository annotation in the Spring Framework is a marker for any class that fulfills the role or _stereotype_ of a repository (also known as Data Access Object or DAO).
不同的模式注解虽然功能相同,但是代表含义却不同。
标注 @Controller 注解,这类组件就可以表示为 WEB 控制层 ,处理各种 HTTP 交互。标注 @Service 可以表示为内部服务层 ,处理内部服务各种逻辑。而 @Repository 可以代表示为数据控制层,代表数据库增删改查动作。
这样一来不同模式注解带来了不同的含义,清晰将服务进行分层。
除了上面的作用,特定的模式注解,Spring 可能会在未来增加额外的功能语义。如现在 @Repository 注解,可以增加 异常的自动转换功能 。
所以,对于分层服务最好使用各自特定语义的模式注解,如 WEB 层就使用 @Controller 注解。
模式注解原理
在 Spring 中任何标注 @Component 的组件都可以成为扫描的候选对象。另外任何使用 @Component 标注的注解,如 @Service ,当其标注组件时,也能被当做扫描的候选对象。。
@Component is a generic stereotype for any Spring-managed component. Any component annotated with @Component is a candidate for component scanning. Similarly, any component annotated with an annotation that is itself meta-annotated with @Component is also a candidate for component scanning. For example, @Service is meta-annotated with @Component .
如果想使自定义的注解也能如 @Service 注解功能一样,只要在自定义注解上标注 @Component 就可以。
AnnotationMetadata
从上面文档看出只要在类上存在 @Component 注解,即使存在于注解的注解上,Spring 都将能其成为候选组件。
@Component 标注在
@Service 上,
@Component 就被称作为元注解。后面我们就将注解的注解称为元注解。
A _ meta-annotation _ is an annotation that is declared on another annotation. An annotation is therefore _meta-annotated_ if it is annotated with another annotation. For example, any annotation that is declared to be _documented_ is meta-annotated with @Documented from the java.lang.annotation package.
那么对于一个类是否可以成为 Spring 组件,需要判断这个类是否包含 @Component 注解,或者类上元注解中是否包含 @Component 。
在 Spring 中可以通过 MetadataReader 获取 ClassMetadata 以及 AnnotationMetadata ,然后获取相应元数据。
ClassMetadata 可以获取类的各种元数据,比如类名,接口等。
而 AnnotationMetadata 可以获取当前类上注解的元数据,如注解名字,以及元注解信息等。
所以只要获取到 AnnotationMetadata,就可以判断是否存在 @Component 。判断方式如下
获取 AnnotationMetadata
这里我们从 XML 配置开启扫描开始讲起。
<context:component-scan base-package="xxx.xxx.xx"/>
首先在 META-INF 下查找 spring.handles 文件。
不明白小伙伴们可以查看上一篇文章 缘起 Dubbo ,讲讲 Spring XML Schema 扩展机制
context 标签在 ContextNamespaceHandler 注册 XML 解析器。在 ContextNamespaceHandler 中其使用了 ComponentScanBeanDefinitionParser 真正解析 XML。
在 ComponentScanBeanDefinitionParser#parse 方法中,首先获取 XML 中配置 base-package 属性,获取扫描的范围,然后调用 ClassPathBeanDefinitionScanner#doScan 获取 base-package 所有 BeanDefinition 。
在 doScan 方法中最终会调用 ClassPathScanningCandidateComponentProvider#scanCandidateComponents 获取扫描范围内所有 BeanDefinition
在 scanCandidateComponents 中首先获取扫描包范围内资源对象,然后迭代从可读取资源对象中 MetadataReaderFactory#getMetadataReader(resource) 获取 MetadataReader` 对象。
上文已经讲到 MetadataReader 对象作用,这里查看如何使用 MetadataReader 进行判断。
筛选组件
在 isCandidateComponent 方法中将会传入 MetadataReader 到 TypeFilter#match 进行判断。
条件的判断主要使用 excludeFilters 与 includeFilters 两个字段决定。那两个字段从何处生成?
原来在 ComponentScanBeanDefinitionParser 中调用 ClassPathBeanDefinitionScanner 构造方法时,默认传入 useDefaultFilters=true 。
在 registerDefaultFilters 注册默认的过滤器,生成 excludeFilters 与 includeFilters 初始值。
默认情况下, excludeFilters 将会是个空集,而 includeFilters 集合中增加一个包含 @Component 类型信息的 AnnotationTypeFilter 实例,以及另外两个包含 Java EE 注解 AnnotationTypeFilter 实例。
跳到 AnnotationTypeFilter#match 方法中。AnnotationTypeFilter 类图如下。
AnnotationTypeFilter#match 方法在抽象类 AbstractTypeHierarchyTraversingFilter 中实现。
match 方法首先调用了 matchSelf ,而该方法最终由 AnnotationTypeFilter 重写。
可以看到这里最终使用 AnnotationMetadata 方法判断是否存在指定注解。
源码分析就到此为止,下篇文章将会深入 AnnotationMetadata ,查看其实如何获取元数据的。
帮助文档
Spring Annotation Programming Model)
『Spring Boot 编程思想』
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Ordering Disorder
Khoi Vinh / New Riders Press / 2010-12-03 / USD 29.99
The grid has long been an invaluable tool for creating order out of chaos for designers of all kinds—from city planners to architects to typesetters and graphic artists. In recent years, web designers......一起来看看 《Ordering Disorder》 这本书的介绍吧!