摘要: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注解

/** * 数据库层注解 * */@Repositorypublic 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框架乃至之后开发会常常用到的货色,

点击关注,第一工夫理解华为云陈腐技术~