Spring 注解编程之模式注解
Spring 框架中有很多可用的注解,其中有一类注解称模式注解(Stereotype Annotations),包括 @Component
, @Service
,@Controller
,@Repository
等。只要在相应的类上标注这些注解,就能成为 Spring 中组件(Bean)。
需要配置开启自动扫描。如在 XML 中配置 ` 或使用注解 @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 注解编程之模式注解的更多相关文章
- 跟Evan学Sprign编程思想 | Spring注解编程模式【译】
Spring注解编程模式 概况 多年来,Spring Framework不断发展对注解.元注解和组合注解的支持. 本文档旨在帮助开发人员(Spring的最终用户以及Spring Framework和S ...
- Spring 注解(一)Spring 注解编程模型
Spring 注解(一)Spring 注解编程模型 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring 注解系列 ...
- Spring 注解编程之注解属性别名与覆盖
前两篇文章咱聊了深入了解了 Spring 注解编程一些原理,这篇文章我们关注注解属性方法,聊聊 Spring 为注解的带来的功能,属性别名与覆盖. 注解属性方法 在进入了解 Spring 注解属性功能 ...
- 理解 Spring 注解编程模型
理解 Spring 注解编程模型 Spring 中有一个概念叫「元注解」(Meta-Annotation),通过元注解,实现注解的「派生性」,官方的说法是「Annotation Hierarchy」. ...
- Spring和SpringMVC的常用注解
Spring的部分: 使用注解之前要开启自动扫描功能 其中base-package为需要扫描的包(含子包). <context:component-scan base-package=" ...
- Spring-构造注入&注解注入&代理模式&AOP
1. 课程介绍 1. 依赖注入;(掌握) 2. XML自动注入;(掌握) 3. 全注解配置;(掌握) 4. 代理模式;(掌握) 5. AOP;(掌握) 依赖注入;(掌握) 2.1. 构 ...
- spring事务详解(基于注解和声明的两种实现方式)
Spring事务( Transaction ) 事务的概念 事务是一些sql语句的集合,作为一个整体执行,一起成功或者一起失败. 使用事务的时机 一个操作需要多天sql语句一起完成才能成功 程序中事务 ...
- [Spring]IoC容器之进击的注解
先啰嗦两句: 第一次在博客园使用markdown编辑,感觉渲染样式差强人意,还是github的样式比较顺眼. 概述 Spring2.5 引入了注解. 于是,一个问题产生了:使用注解方式注入 JavaB ...
- SSH(Struts2+Spring+Hibernate)框架搭建流程<注解的方式创建Bean>
此篇讲的是MyEclipse9工具提供的支持搭建自加包有代码也是相同:用户登录与注册的例子,表字段只有name,password. SSH,xml方式搭建文章链接地址:http://www.cnblo ...
随机推荐
- 如何控制WAP网站上输入框的默认键盘类型
百度上对这样的资料介绍很多,基本上都和这个页面是一个意思 http://www.w3school.com.cn/html5/att_input_type.asp : 语法 <input type ...
- 怎样将数据库MySQL 迁移到 MariaDB 上
自从甲骨文收购 MySQL 后,由于甲骨文对 MySQL 的开发和维护更多倾向于闭门的立场,很多 MySQL 的开发者和用户放弃了它.在社区驱动下,促使更多人移到 MySQL 的另一个叫 MariaD ...
- Leetcode 328 Contains Duplicate set和map应用
找出数组中重复的数,裸的map和set题 class Solution { public: bool containsDuplicate(vector<int>& nums) { ...
- [LeetCode OJ] Copy List with Random Pointer 扩大
职务地址:https://oj.leetcode.com/problems/copy-list-with-random-pointer/ 题意:对一个有回路的链表的深复制 解题:这道题我AC了之后才发 ...
- XF 表视图添加和删除行
using System;using Xamarin.Forms;using Xamarin.Forms.Xaml; [assembly: XamlCompilation (XamlCompilati ...
- Bootstrap 单按钮下拉菜单
@{ Layout = null;}<!DOCTYPE html><html><head> <meta name="viewport&q ...
- WPF中的图像处理简介
原文:WPF中的图像处理简介 和Winform中的GDI+相比,WPF提供了一组新的API用于显示和编辑图像.新API特点如下: 适用于新的或专用图像格式的扩展性模型. 对包括位图 (BMP).联合图 ...
- MVC EF 导航属性
@model IQueryable<EFExam.Models.CategoryProductViewModel>@{ Layout = null;}<!DOCTYPE htm ...
- 图像滤镜艺术---ZPhotoEngine超级算法库
原文:图像滤镜艺术---ZPhotoEngine超级算法库 一直以来,都有个想法,想要做一个属于自己的图像算法库,这个想法,在经过了几个月的努力之后,终于诞生了,这就是ZPhotoEngine算法库. ...
- UWP-电子音读出文字
原文:UWP-电子音读出文字 源码: https://github.com/lindexi/Markdown 代码 private async void speech(string str, Medi ...