spring controller 增加header字段forward_Spring 注解编程之模式注解
上篇文章研究 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 都将能其成为候选组件。
注解上的注解 Spring 将其定义为元注解(meta-annotation),如
@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 thejava.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
beans-stereotype-annotations
『Spring Boot 编程思想』
spring controller 增加header字段forward_Spring 注解编程之模式注解相关推荐
- 设计模式——Spring注解编程模型
文章目录 1. 引言 2. Spring注解编程模型 2.1 元注解(Meta-Annotations) 2.2 Spring模式注解(Stereotype Annotations) 2.3 Spri ...
- Spring基础专题——第十一章(高级注解编程完结)
前言:去年到现在一直没有很好的时间完成这个spring基础+源码的博客目标,去年一年比较懒吧,所以今年我希望我的知识可以分享给正在奋斗中的互联网开发人员,以及未来想往架构师上走的道友们我们一起进步,从 ...
- Spring基础专题——第九章(基础注解编程——上)
目标,去年一年比较懒吧,所以今年我希望我的知识可以分享给正在奋斗中的互联网开发人员,以及未来想往架构师上走的道友们我们一起进步,从一个互联网职场小白到一个沪漂湿人,一路让我知道分享是一件多么重要的事情 ...
- Spring注解编程基石(一)
目录 Java注解 Java原生注解 元注解 Stereotype 注解 组合注解 组合注解实现的基础 @AliasFor 隐式别名 @AliasFor 和 @Inherited 区别 注解解析工具 ...
- Spring注解编程基石(二)
目录 辅助类 AttributeMethods AnnotationFilter RepeatableContainers MergedAnnotation接口 AnnotationsProcesso ...
- Spring注解编程基石(三)
目录 AnnotationUtils 源码分析 方法列表 方法源码 AnnotatedElementUtils 源码分析 Spring注解编程基石(一) Spring注解编程基石(二) Spring注 ...
- Spring注解编程基石(四)
目录 AnnotationsScanner 扫描方法 扫描source为Class方法 扫描source为Method方法 辅助方法 MergedAnnotationSelector MergedAn ...
- 利用Spring扩展点模拟MyBatis的注解编程「知识点多多」「扩展点实战系列」- 第448篇
历史文章(文章累计440+) <国内最全的Spring Boot系列之一> <国内最全的Spring Boot系列之二> <国内最全的Spring Boot系列之三> ...
- Spring基础篇:高级注解编程
文章内容来自于B站孙哥说Spring 第一章:@Configuration 一:配置Bean替换XML细节 二:应用配置Bean工厂对象 三:配置Bean细节分析 1:整合Logback 三:@Com ...
最新文章
- ubuntu安装rar win解压缩工具
- python学习之turtle库基本操作
- php用于防SQL注入的几个函数
- ArcGIS 的 http://localhost:8399/arcgis/rest/services 无法打开,显示404 的解决办法
- 新晋“网红”Cat1 是什么
- 有哪些关于iPhone使用的小技巧?
- 20个问题:平凡的天才人格特质
- yii CComponent组件 实例说明1
- Illustrator 教程,如何在 Illustrator 中重新塑造文本?
- 一文弄懂数据挖掘的十大算法,数据挖掘算法原理讲解
- EasyRecovery注册码哪里有?
- 硬件安全模块- HSM
- layabox 打印_Layabox 集成指南
- centons7安装k8s集群
- 秋招经验总结(私企,外企,国企)
- c语言实验作业在dev蜗居的思路,C语言程序设计实验(共5篇)
- ADFS 概念与基本开发介绍 (1)
- zuk z2刷机android p,zuk z2p 解锁详细步骤
- Redis Desktop Manager连接失败/超时?
- Mongodb 索引 对查询结果的排序
热门文章
- php的mbstring模块安装折腾记录
- 【codevs1036】商务旅行,LCA练习
- C ++ 类 | 类的创建和使用_1
- jsp测试连接mysql_JSP 连接MySQL配置与测试
- 自走棋电脑版_手游版《自走棋》上线试玩
- php滚动图代码,JS上下、左右滚动代码(支持图片滚动)
- Android中VectorDrawable与SVG
- CentOS 7 SSH相关使用问题及其解决办法
- python十大实例_Python练习实例100例(从简入难)96-100
- python 运行时 变量_python运行过程,变量,符号