【Spring】基于注解方式开发,简化配置(多图预警)

一、前言

今天,我们来学习基于注解的配置方法,代替XML配置文件进行Bean的管理。包括介绍如何使用注解来声明Bean以及实现依赖注入,同时记录如何使用配置类替代XML文件进行全注解开发。

二、内容

2.1 回顾

之前讲过,Spring的IoC(Inversion of Control)容器通过XML配置文件的方式,管理应用程序中的对象(也就是Bean)的生命周期和依赖关系。IoC容器负责实例化、配置、组装和管理这些Bean,开发者则不再需要手动管理对象的创建和依赖注入。

今天,我们来学习更简单的配置方式,即基于注解(Annotation)的配置,不需要XML文件,而配置后让 Spring 自动扫描Bean并组装它们。

2.2 声明Bean

(1)@Component

@Component 是 Spring 框架中用于表示一个类是 Bean 的注解之一。使用了@Component 注解就相当于定义了一个 Bean 。

具体来说,当 Spring IoC 容器启动时,它会自动扫描指定的包,找到带有 @Component 注解的类,并将它们实例化为 Bean。

@Component 有一个 value 属性,该属性的作用实际上就跟之前一样,用来指定 bean 的 id的作用。

@Component注解就相当于定义了一个bean,该bean有一个可选的名称,默认是小写开头的类名。

(2)@Controller、@Service、@Repository

这三个注解 @Controller@Service@Repository 都是 Spring 框架中的特殊化注解,它们都派生自 @Component 注解,用于更明确地表示类的用途或角色。

简单来说,就是 @Component 注解的别名,实际上功能都一样,只不过用了该注解后程序可读性更强。

@Controller:用于标识控制器层(Controller)的类,通常处理用户请求和返回视图。

@Service:用于标识服务层(Service)的类,通常包含应用的业务逻辑。

@Repository:用于标识数据访问层(Repository)的类,通常用于数据库操作。

总的来说,这三个注解的作用与 @Component 一样,都是为了将类标识为 Spring 管理的bean组件,只不过可以在不同的层次上提供更加明确的语义,方便开发者更清晰地区分和理解应用程序中各个类的作用。

(3)举例

注意,在使用注解时,需要使用Spring 的 AOP 功能。因此我们需要在 pom.xml 文件中添加spring-context依赖后,进而关联加入aop的依赖。

下面,我们来看简单的注解例子。

比如,现在我们写一个 UserDao 类,在类上使用@Component 注解,表示这里定义了一个Bean 。

接着,在XML配置文件中这样配置:

下面来看测试结果:

可以看到,我们成功获取了bean。

下面有两个注意点。

首先,在类上使用@Component 注解时,可以省略value属性,不用显示的标明。比如这样:

这也是可以的。

第二个注意点是,当我们不给@Component 注解的value属性进行赋值,那么Spring会给这个bean自动取名,默认为Bean类的首字母小写。如下所示:

(4)多包解决方案

如上所示,如果涉及到多个包下的bean扫描,有两种方法。

第一种方法,在 XML 配置中,<context:component-scan> 元素的 base-package 属性可以包含一个逗号分隔的字符串,其中包含了所有需要扫描的包名。

第二种方法,就是指定多个包的共同父包,就不用显式列出每个包。

(5)控制组件扫描

这部分作为扩展知识。

前面说过,使用@Controller@Service@Repository注解都派生自 @Component 注解,类似 @Component 注解的别名,功能一样,只不过可读性更高。

在一些特殊的业务需求下,我们可能会希望实例化某一个包下所有标注了 @Controller 注解的类,而其他类型注解(比如@Controller@Service等)的Bean则不进行实例化。

那么在这种情况下,可以有两种方案。

方案一:禁用默认规则,仅实例化 @Controller 注解的类

比如:

xml 复制代码
<context:component-scan base-package="com.example.dao" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

在这里,我们通过设置 use-default-filtersfalse 禁用了默认规则,然后使用 <context:include-filter> 明确指定了只有标注了 @Controller 注解的类才会被实例化。其他类型的组件将被排除。

方案二:使用默认规则,排除不需要实例化的注解类型

比如:

xml 复制代码
<context:component-scan base-package="com.example.dao">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

在这里,我们使用默认规则(use-default-filters 默认为 true),但通过 <context:exclude-filter> 排除了标注了 @Repository@Service@Controller 注解的类,从而达到只实例化 @Controller 类的目的。

2.3 使用注解注入

(1)@value

使用@Value注解可以进行简单类型属性的注入,如下所示:

可以看到,我们使用@Value注解直接标注在字段上,这样,Spring容器在初始化 Bean的时候,会自动将值注入到相应的字段中。

另外,我们还可以将使用在 set 方法上,也可以使用在构造器的参数中。如下所示:

(2)@Autowired

使用@Autowired 注解就相当于把指定类型的Bean注入到指定的属性当中。

我们来看源码:

@Autowired注解表示自动装配(自动连线),可以用来注入非简单类型 ,单独使用@Autowired注解时,默认根据类型装配byType)。该注解可以标注在很多地方,包括构造方法上、方法上、形参上、属性上以及注解上。

如果将@Autowired注解的required属性设置为false,表示注入的Bean如果存在,就注入;不存在的话,也不报错。

下面我们来看 @Autowired 的基本使用。

首先我们看下示例一:标注在属性(字段)上。

运行后也是没问题的:

当然,@Autowired 注解还可以标注在很多地方,如下所示:

另外,还可以标注在构造方法的形参上,比如:

需要注意的是,@Autowired注解默认根据类型注入的(byType),因此,如果UserDao接口还有另外一个实现类:

那就会有问题,如下所示:

这时,我们就不用默认的根据类型注入(byType),而是根据名称(byName)进行注入。

我们需要联合使用@Qualifier注解来根据名称进行自动装配,即在@Qualifier注解中指定Bean名称。

我们来总结一下,@Autowired注解可以标注在bean的属性上、setter方法上、构造方法上、构造方法的参数上,默认是根据类型注入(byType)。如果有多个bean冲突,无法自动装配,那么需要结合@Qualifier注解来根据名称注入(byName)。

2.4 使用全注解开发

(1)配置类

现在,我们可以不再编写XML配置文件,而是写一个配置类,如下所示:

这时,我们在编写程序时,需要 new一个 AnnotationConfigApplicationContext 对象,而不是 ClassPathXmlApplicationContext对象。

(2)@Configuration

使用@Configuration注解标识的类就是一个配置类,用于代替原先的XML配置文件。

我们来看一下源码:

配置类其实就是一个普通的 Java 类,在类上用@Configuration 注解来标注后,表明该类是一个配置类,通过配置类可以定义和组装 Spring Bean。

(3)@ComponentScan

@ComponentScan 注解用于 bean 扫描配置,替代原有XML配置文件中的<context:component-scan base-package=""/>,我们可以指定一个或多个包名,Spring会扫描指定包及其子包下使用注解的类。

如果不配置包名,那么扫描当前@componentScan注解配置类所在包及其子包下的类。

源码如下:

三、总结

总的来说,基于注解的配置方式极大的简化了开发,使得配置更加简洁。每个Bean都通过@Component来声明,以及使用 @Autowired进行注入,同时,为了提高程序的可读性,我们可以使用@Controller@Service@Repository 来代替@Component,实质上是一样的。

下一节,我们来学习 @Resource 注解,分析该注解和@Component注解的区别。

相关推荐
计算机毕设指导614 分钟前
基于 SpringBoot 的作业管理系统【附源码】
java·vue.js·spring boot·后端·mysql·spring·intellij-idea
Gu Gu Study15 分钟前
枚举与lambda表达式,枚举实现单例模式为什么是安全的,lambda表达式与函数式接口的小九九~
java·开发语言
Chris _data18 分钟前
二叉树oj题解析
java·数据结构
牙牙70523 分钟前
Centos7安装Jenkins脚本一键部署
java·servlet·jenkins
paopaokaka_luck31 分钟前
[371]基于springboot的高校实习管理系统
java·spring boot·后端
以后不吃煲仔饭44 分钟前
Java基础夯实——2.7 线程上下文切换
java·开发语言
进阶的架构师44 分钟前
2024年Java面试题及答案整理(1000+面试题附答案解析)
java·开发语言
The_Ticker1 小时前
CFD平台如何接入实时行情源
java·大数据·数据库·人工智能·算法·区块链·软件工程
大数据编程之光1 小时前
Flink Standalone集群模式安装部署全攻略
java·大数据·开发语言·面试·flink
爪哇学长1 小时前
双指针算法详解:原理、应用场景及代码示例
java·数据结构·算法