关于Spring注解开发教程,打包全送你
摘要:spring是我们web开发中必不可少的一个框架,基于传统的xml方式配置bean总觉得太过繁琐,从spring2.5之后注解的出现可以大大简化我们的配置。
本文分享自华为云社区《如何高效提升Java开发效率—Spring注解开发全套教程!》,作者: 灰小猿。
一、使用注解标识组件
为了不再在IOC中一个个的声明类对象,首先根据每一个类的功能的不同,Spring中先规定了基于组件的注解,大致可以分为以下四种:
①普通组件:@Component
标识一个受Spring IOC容器管理的组件,我们也可以理解为是除了数据库层、业务逻辑层、控制层组件以外的其他组件使用的注解。
②持久化层组件:@Respository
标识一个受Spring IOC容器管理的持久化层组件,一般就是用来标注数据库层
③业务逻辑层组件:@Service
标识一个受Spring IOC容器管理的业务逻辑层组件,
④表述层控制器组件:@Controller
标识一个受Spring IOC容器管理的表述层控制器组件。
同时这几个注解后面也可以添加一些参数,比如比较常用的一个是注解的括号中加value属性,来表示这个组件在容器中的ID,如果不设置value值时,默认的ID是类名的全称(第一个字母小写)。
如下实例,我们为一个Dao层组件添加一个@Respository注解
/**
* 数据库层注解
* */
@Repository
public class BookDao {
public void saveBook() {
System.out.println("bookDao中的图书已保存...");
}
}
通过这四个注解我们首先就可以将所有的组件逐一分类。置于为什么要使用注解进行分类,说到底其实就是为了方便方便快速的知道哪一个类是做了什么类型的功能,同时方便之后通过这四个注解将组件加入到IOC容器中。
所以你也可以把这四个注解理解为是Spring分发给不同功能组件的一个“身份证”,只有拥有这四种“身份证”,那么这个组件就可以被加入到IOC容器中。
在这里有一点需要注意:事实上Spring并没有能力识别一个组件到底是不是它所标记的类型,即使将@Respository注解用在一个表述层控制器组件上面也不会产生任何错误,所以@Respository、@Service、@Controller这几个注解仅仅是为了让开发人员自己明确当前的组件扮演的角色。方便将组件加入到容器中去。
二、组件扫描
1、普通扫描
现在倒是对所有的组件进行了详细的分类,但是这样就等于将所有的组件已经加入到IOC容器中了嘛?如果真的是这样的话,那么我们就真正的实现了低代码时代了...
所以现在我们就是应该如何将拥有注解标识的组件加入到IOC容器中呢?在这里Spring在IOC中提供了一个包扫描的功能,通过这个名字我们就可以知道,Spring可以自动的扫描整个项目中被标记了这四个注解的组件,并且将其加入到IOC容器中。
进行包扫描的具体操作是这样的:
进行包扫描依赖于Context名称空间,所以需要在IOC中加入该名称空间,加入名称空间的方法有两种,一种是在IOC的头文件中加入如下代码:
xmlns:context="http://www.springframework.org/schema/context"
但是因为这种不好记所以不推荐,
还有一种就是直接在界面点击下方的Namespaces,在其中找到并勾选Context,

在容器中进行包扫描的代码是:
<context:component-scan base-package="com.spring"></context:component-scan>
其中base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包及其子包中的所有类。当需要扫描多个包时可以使用逗号分隔。如上面的代码就是扫描com.spring包下面的所有类。
2、包含与排除特定组件
但是这样进行扫描的范围有时候未免还是有一些大,那么能不能再缩小进行包扫描的范围呢?当然是可以的。
如果仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类,如:
<context:component-scan base-package="com.atguigu.component" resource-pattern="autowire/*.class"/>
(1)扫描包含特定组件
如果我们仅仅是想要扫描包含特定特征的组件,那么我们可以如下方法:
<context:include-filter>子节点表示要包含的目标类
但是需要注意的是:由于context:component-scan默认是将所有的类全部都添加进去,所以在此基础上再添加是没有用的,需要在context:component-scan中加入属性参数use-default-filters,use-default-filters="true" 表示默认将所有的类都添加进去,false表示将所有的类都不添加进去,
如下代码表示仅仅扫描包含include-filter中所指特征的组件,其中的type用来表示使用何种类型的扫描表达式,expression后面跟表达式。
<context:component-scan base-package="com.spring" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
(2)扫描排除特定组件
尽然有扫描包含特定组件,那么就有扫描排除特定组件,
<context:exclude-filter>子节点表示要排除在外的目标类。
以下代码表示扫描除以下特征外的其他组件。
<context:component-scan base-package="com.spring">
<context:exclude-filter type="assignable" expression="com.spring.service.BookService"/>
</context:component-scan>
同时component-scan下可以拥有若干个include-filter和exclude-filter子节点,来表示可以包含多个哪种特征的组件或排除具有哪种特征的组件。
关于上面说到的type中填写的过滤表达式类型及作用如下表:

最常用的上面两个,以下三个几乎不用:
type="aspectj" aspectj表达式
type="custom" 定义一个TypeFile,自己写一个类定义使用哪一个
type="regex" 利用正则表达式
注意有bug:有些小伙伴们在进行注解开发的时候注解和扫描都写的很完美,可就是不起作用,原因可能是缺少相应特有的一个jar包,在这里需要导入额外的一个aop包
spring-aop-4.0.0.RELEASE.jar
到这里,将组件添加到容器中的操作就算是完成了,
在我们将组件添加成功之后呢,我们可以在组件图标的右上角看到一个小S的图标,这个时候就表示这个组件已经成功的加入到了容器中,
3、实现注解的三步骤
总结一下实现注解的三步骤:
- 添加context依赖
 context:component-scan
- 为类添加相应的注解
- 导入aop包
 spring-aop-4.0.0.RELEASE.jar
三、组件自动装配
但是这样就结束了嘛?就这么轻松了嘛?之前学习的bean的作用域与生命周期这些都没用了嘛?当然不是!!!更重要的是组件还没获取呢!!!
那么接下来就来和大家讲一下使用注解开发的高端操作,让你知道使用注解是多么的香!!!
我们平常在使用类的时候,难免会在类中调用其他自定义的类对吧,就比如说,Controller组件中往往需要用到Service组件的实例,Service组件中往往需要用到Repository组件的实例。
那么如果我们对这些需要实例化的组件一个一个的在类中进行实例化,是不是就显得太麻烦了呢?哎,聪明机智的程序员们怎么会没有想到这一点呢!所以组件的自动装配就出现了,
在spring中我们可以通过注解的形式来对组件进行自动的装配,那么到底如何对组件进行装配的呢?
其实是这样的,在IOC中指定要扫描的包时,<context:component-scan> 元素会自动注册一个bean的后置处理器:AutowiredAnnotationBeanPostProcessor的实例。该后置处理器可以自动装配标记了@Autowired、@Resource或@Inject注解的属性。
而上面的@Autowired、@Resource或@Inject这三个注解,就是我们在进行组件的自动装配时最常用的注解,
下面我和大家介绍一下这三种注解的具体使用。
1、@autowired注解
@autowired注解能够根据类型实现自动装配。无论是构造器、普通字段(即使是非public)、还是一切具有参数的方法都可以应用@Autowired注解
默认情况下,所有使用@Autowired注解的属性都需要被设置。当Spring找不到匹配的bean装配属性时,会抛出异常。
(1)@autowired装配原理
接下里我来和大家详细的讲一下@autowired注解的装配原理:
1、使用自动装配时,首先会根据类型去容器中查找相应的组件,这就类似于
getBean("bookService.class"),
2、如果没有找到就抛异常,如果找到一个就赋值
3、如果找到多个,那么也是有一定的装配依据的,并不是随便找一个进行装配。
首先根据属性名作为ID进行继续寻找,找到对应属性名的组件就进行装配,没有找到就报错,报错的原因是:使用变量名作为id进行匹配时候,没有找到对应的属性名
(2)@Qualifier指定装配ID
对于这种报错其实还有一种解决:就是使用@Qualifier("bookService")指定查找ID,找到就装配,找不到报错,指定查找ID的代码示例如下:
// 添加注解表示自动装填
@Autowired
@Qualifier("bookdao")
private BookDao bookDao;
(3)required—装配报错解决
那么要是每次找不到就报错,这样程序不是就崩了吗?对于这样的情况应该怎么办呢?其实还有一种解决办法,解决找不到报错:使用required参数,
@Autowired(required=false) required=false表示如果实在找不到,就装配null
反正装配的依据就是,按照多种规则查找合适的装配对象,直到查找成功,实在不成功就返回null。
(4)特殊属性的自动装配
上面是使用@Autowired注解的基本原理与步骤,我们直到spring的注解开发是十分强大的,下面我们再来说几个特殊的属性的装配。
@Autowired注解可以应用在数组类型的属性上,此时Spring将会把所有匹配的bean进行自动装配。
@Autowired注解也可以应用在集合属性上,此时Spring读取该集合的类型信息,然后自动装配所有与之兼容的bean。
@Autowired注解用在java.util.Map上时,若该Map的键值为String,那么 Spring将自动装配与值类型兼容的bean作为值,并以bean的id值作为键。
这样一来,@Autowired注解的自动装配是不是就显得十分的强大了,以后妈妈再也不用担心我new对象了!!!
2、@Resource注解
@Resource注解要求提供一个bean名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为bean的名称。
3、@Inject注解
@Inject和@Autowired注解一样也是按类型注入匹配的bean,但没有reqired属性。
以上就是进行自动装配时使用的三个注解,在这里再总结一下,
@autoWried是spring自带的,更强大一些,能够实现required=false
@Resource也是java自带的,扩展性更强,所以如果切换成另一个容器框架,@Resource还是可以用的,而@Inject和@Autowired注解一样也是按类型注入匹配的bean,但没有reqired属性。其实在日常开发中,我们最常用到的、功能最强大的注解还是@Autowired注解。所以记住这一个基本上就可以了。
然后再总结一下使用注解的好处,主要就是节省了new对象时麻烦,直接使用一个@Autowired注解,spring就可以自动的为该属性赋值,一般来说将组件加入到IOC的注解和@Autowired是结合使用的。
四、注解使用的小细节
其实在使用注解进行开发时还有一些小细节需要注意,我在这里给大家总结一下。
1、整合多个配置文件
当我们开发时的项目过大的时候,在一个配置文件写如配置有时候就不能满足我们的需求,所以Spring允许通过<import>将多个配置文件引入到一个文件中,进行配置文件的集成。这样在启动Spring容器时,仅需要指定这个合并好的配置文件就可以。import元素的resource属性支持Spring的标准的路径资源,
如下示例,我们有springmvc.xml和spring.xml两个配置文件,现在我们想要将spring.xml引入到springmvc.xml中,方法是:在springmvc.xml中写入下面代码:
<import resource="spring.xml"/>
2、路径书写问题
对于spring中常用地址书写,有时候需要使用classpath,而有时候又需要其他,针对不同的路径书写,有不一样的含义和使用:具体看下表:

3、获取组件时的问题
对于使用注解方法添加到容器中的组件,我们在IOC容器中是看不到的,那么获取它的时候应该如何获取呢?
我们上面也说了,在注解中不指定id的前提下,spring是会自动的为每一个组件设置一个第一个字母小写的组件的全称作为ID,(如Book类的ID默认是book)。在容器中获取组件的方法和以往一样,但是如果是单实例的话,一般建议以类为参数进行获取。如:
Book book = (Book)ioc.getBean(Book.class);
五、写在最后
以上就是Spring注解开发的全部知识点了,是不是觉得使用注解开发比原生代码简洁多了,注解也是SSM框架乃至之后开发会经常用到的东西,
关于Spring注解开发教程,打包全送你的更多相关文章
- spring注解开发:容器中注册组件方式
		1.包扫描+组件标注注解 使用到的注解如下,主要针对自己写的类 @Controller @Service @Repository @Component @ComponentScan 参考 spring ... 
- 浅尝Spring注解开发_自定义注册组件、属性赋值、自动装配
		Spring注解开发 浅尝Spring注解开发,基于Spring 4.3.12 包含自定义扫描组件.自定义导入组件.手动注册组件.自动注入方法和参数.使用Spring容器底层组件等 配置 @Confi ... 
- 浅尝Spring注解开发_AOP原理及完整过程分析(源码)
		浅尝Spring注解开发_AOP原理及完整过程分析(源码) 浅尝Spring注解开发,基于Spring 4.3.12 分析AOP执行过程及源码,包含AOP注解使用.AOP原理.分析Annotation ... 
- 浅尝Spring注解开发_Servlet3.0与SpringMVC
		浅尝Spring注解开发_Servlet 3.0 与 SpringMVC 浅尝Spring注解开发,基于Spring 4.3.12 Servlet3.0新增了注解支持.异步处理,可以省去web.xml ... 
- Annotation(三)——Spring注解开发
		Spring框架的核心功能IoC(Inversion of Control),也就是通过Spring容器进行对象的管理,以及对象之间组合关系的映射.通常情况下我们会在xml配置文件中进行action, ... 
- spring注解开发中常用注解以及简单配置
		一.spring注解开发中常用注解以及简单配置 1.为什么要用注解开发:spring的核心是Ioc容器和Aop,对于传统的Ioc编程来说我们需要在spring的配置文件中邪大量的bean来向sprin ... 
- JAVAEE——SSH项目实战06:统计信息管理、Spring注解开发和EasyUI
		作者: kent鹏 转载请注明出处: http://www.cnblogs.com/xieyupeng/p/7190925.html 一.统计信息管理 二.Spring注解开发 1.service ... 
- Spring注解开发-全面解析常用注解使用方法之生命周期
		本文github位置:https://github.com/WillVi/Spring-Annotation/ 往期文章:Spring注解开发-全面解析常用注解使用方法之组件注册 bean生命周期  ... 
- Spring注解开发系列Ⅵ --- AOP&事务
		注解开发 --- AOP AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,横向重复,纵向抽取.详细的AO ... 
- 浅尝Spring注解开发_Bean生命周期及执行过程
		Spring注解开发 浅尝Spring注解开发,基于Spring 4.3.12 包含Bean生命周期.自定义初始化方法.Debug BeanPostProcessor执行过程及在Spring底层中的应 ... 
随机推荐
- ES6和node模块化
			node模块化: 1.输出:exports.a=12; 或者module.exports={ a:12, b:5 } 2.引入:require('./a.js'); 3.引用自定义模块 放到node_ ... 
- 前端工程化&&自动化部署&&model抽离
			你不知道的前端 MVVM 模式中的数据层(万字长文,教你造轮子) 实现了 Model 层抽离的全部想法, 后端返回的接口--model(错误处理,返回统一格式,洗数据,缓存)--再拿这个处理过的数据 ... 
- ant design TreeSelect支持搜索,切换value和title属性
			测试人员测试我form里面一个select的时候,发现只能搜索英文和数字,不能搜中文 后来找到原因,treeNodeFilterProp字段默认是velue,我value里面是id,当然搜不到中文啦 ... 
- Java Web程序在Tomcat上是如何运行的
			https://blog.csdn.net/fuzhongmin05/article/details/104379514 一个JVM是一个进程,JVM上跑Tomcat,Tomcat上可以部署多个应用. ... 
- 使用openpyxl库读取Excel文件数据
			在Python中,我们经常需要读取和处理Excel文件中的数据.openpyxl是一个功能强大的库,可以轻松地实现Excel文件的读写操作.本文将介绍如何使用openpyxl库读取Excel文件中的数 ... 
- 多数元素 (3.12 leetcode每日打卡)
			给定一个大小为 n 的数组,找到其中的多数元素.多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是非空的,并且给定的数组总是存在多数元素. 示例 1: 输入: [3,2,3] ... 
- Walrus 0.4发布:单一配置、多态运行,体验下一代应用交付模型
			今天,我们高兴地宣布云原生统一应用平台 Walrus 0.4 正式发布,这是一个里程碑式的版本更新.新版本采用了全新的应用模型--仅需进行单一配置,即可在多种模态的基础设施及环境中运行包括应用服务及周 ... 
- 阿里云轻量服务器上编译安装docker trojan时报错  fatal error: Killed signal terminated program cc1plus compilation
			轻量服务器编译安装docker trojan时报错 72%时 通过以下操作解决,和编译其他软件类似,是内存不足引起的 编译安装swoole的时候报错 fatal error: Killed sig ... 
- 【Android】学习day05|RadioButton
			注意事项:当使用默认选中标签:check时,必须要给标签加id,否则失效. 这个没什么,挺简单的,就记录一下代码[监听事件] package com.example.app02; import and ... 
- Linux笔记03: Linux常用命令_3.4文件和目录共用命令
			3.4 目录和文件共用命令 3.4.1 rm命令 ●命令名称:rm. ●英文原意:remove files or directories. ●所在路径:/usr/bin/rm. ●执行权限:所有用户. ... 
