Spring 五大类注解、方法注解、对象注入简化 Bean 操作

news2024/11/25 12:55:53

目录

为什么要使用注解

配置扫描文件:

1.配置扫描路径

1. 五大类注解:

 五大类注解有哪些?

 1.1 @Controller:

1.1.1 存储 Bean

1.1.2 读取 Bean

 1.2 @Service:

1.2.1 存储 Bean

1.2.2 读取 Bean

 1.3 @Repository:

1.3.1 存储 Bean

1.3.2 读取 Bean

 1.4 @Component:

1.4.1 存储 Bean

1.4.2 读取 Bean

 1.5 @Configuration:

1.5.1 存储 Bean

1.5.2 读取 Bean

 五大类注解匹配 Bean 时默认 id 命名规则

 为什么要有这么多的注解?

1.五大类注解之间的关系

2.为什么使用这么多注解?

2. 方法注解 @Bean:

 2.1 存储 Bean

 2.2 获取 Bean 对象

 2.3 @Bean 重命名策略

3. 对象装配(更简单地获取 Bean 对象):

 3.1 属性注入:

3.1.1 优缺点分析

 3.2 Setter 注入:

3.2.1 优缺点分析

 3.3 构造方法注入:

3.3.1 优缺点分析

4. @Resource 注解:

 4.1 @Resource 和 @AutoWired 的区别:

4.1.1 解决同一类型 @Bean 报错问题



为什么要使用注解

        使用这五种类注解可以简化对 Bean 的存储和读取。其实不仅限于五大类注解,其他注解、注入方式都是相同原理来简化操作的,可以直接将 Bean 存储到 Spring 容器中。

        在上一篇中,我们每存储一个新的 Bean 时,都需要在配置文件 spring-config.xml 中添加一行新的 <bean><bean> 标签,这样明显很麻烦,于是在本篇中主要介绍一劳永逸的方法:配置扫描文件-路径;

配置扫描文件:

        配置扫描文件是必须的操作;

1.配置扫描路径:

        先要建好 Spring 项目,接着理解下面的内容:

        ① 在 resources 包里创建配置文件,名为:spring-config.xml;

        ② 在配置文件里添加 Spring 配置内容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <content:component-scan base-package="com.java.demo"></content:component-scan>
</beans>

        需要注意的是 <content:component-scan><content:component-scan> 标签,其内部最重要的就是 base-package 这个路径,这个路径的含义见下图:

        换个角度来讲:对于不在该最终路径下的类或对象,即使为它加了注解,也不能做为 Bean 存储到 Spring 容器中;

----------------------------------------------前置工作完成--------------------------------------------------


1. 五大类注解:

五大类注解有哪些?

@Controller(控制器存储):可以验证用户请求的数据的正确性;

@Service(服务存储):服务于编排和调度具体具体方法的执行;

@Repository(仓库存储):与数据库交互;

@Component(组件存储):管理组件、工具类等;

@Configuration(配置存储):管理配置项、设置等;

1.1 @Controller:

        为了适应 javaEE 标准分层,演示代码前先创建响应层级的包,在包内创建类(后面同理、标准分层下面介绍);

1.1.1 存储 Bean:

        像这样,写一个 PersonController 类,加上类注解 @Controller 就可以把这个 Bean 通过配置路径扫描后,放到 Spring 容器中;

@Controller
public class PersonController {
    public void myHobby() {
        System.out.println("psController -> 我爱敲代码");
    }
}

1.1.2 读取 Bean:

        在最初的java包下创建一个启动类:App类,获取 Spring 对象、Bean 对象;

        运行结果得出,我们没有像原始那样在配置文件中添加一行 <bean id="" class=""></bean> 这样的手动注入,也成功的可以读取到 Bean 对象 - personController,这就是 @Controller 注解自动注入的好处;

// 启动类
public class App {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        PersonController personController =
                context.getBean("personController",PersonController.class);
        personController.myHobby();
    }
}

------------------------------------------------------------------------------------------------------

1.2 @Service:

1.2.1 存储 Bean:

@Service
public class PersonService {
    public void myHobby() {
        System.out.println("psService -> 我爱敲代码");
    }
}

1.2.2 读取 Bean:

public class App {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        PersonService personService = context.getBean("personService",PersonService.class);
        personService.myHobby();
    }
}

------------------------------------------------------------------------------------------------------

1.3 @Repository:

1.3.1 存储 Bean:

         创建一个名为 repository 的包,在包下创建类 PersonRepository:

@Repository
public class PersonRepository {
    public void myHobby() {
        System.out.println("psRepository -> 我爱敲代码");
    }
}

1.3.2 读取 Bean:

public class App {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        PersonRepository personRepository =
                context.getBean("personRepository",PersonRepository.class);
        personRepository.myHobby();
    }
}

1.4 @Component:

1.4.1 存储 Bean:

        创建一个名为 Component 的包,在包下创建一个类 PersonComponent:

@Component
public class PersonComponent {
    public void myHobby() {
        System.out.println("psComponent -> 我爱敲代码");
    }
}

1.4.2 读取 Bean:

public class App {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        PersonComponent personComponent =
                (PersonComponent) context.getBean("personComponent", PersonComponent.class);
        personComponent.myHobby();
    }
}

1.5 @Configuration:

1.5.1 存储 Bean:

        创建一个名为 configuration 的包,在包下创建类 PersonConfiguration:

@Configuration
public class PersonConfiguration {
    public void myHobby() {
        System.out.println("psConfiguration -> 我爱敲代码");
    }
}

1.5.2 读取 Bean:

public class App {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        PersonConfiguration personConfiguration =
                context.getBean("personConfiguration",PersonConfiguration.class);
        personConfiguration.myHobby();
    }
}


五大类注解匹配 Bean 时默认 id 命名规则:

        上面通过注解方式直接将 Bean 存储到 Spring 容器中,我们并没有手动设置其 id,那么读取时的 id 该怎么写?

        id 是有默认规则的:双击 shift,找到 AnnotationBeanNameGenerator 方法,alt + 7 直接查看 buildDefaultBeanName 方法:

 再进入其内部的 decapitalize() 方法:

 通过源码可以得到结论:在 @Controller 注解下默认规定:

  1. 类首字母大写,且第二个字母是小写,那么 id 就为首字母小写的类名;
  2. 类首字母大写,且第二个字母也是大写,那么 id 就是原类名;

图解: 


为什么要有这么多的注解?

1.五大类注解之间的关系:

        同样通过五种注解的源码可以看到:@Controller、@Service、@Repository、@Configuration 这四个注解的实现都依赖于 @Component注解,因此可以理解为 前面四个注解是 @Component 注解的“子类”,是对其的扩展

2.为什么使用这么多注解?

        这就不得不提 javaEE 标准分层了,既然 Spring 框架是针对企业开发使用的,因此这些注解一定程度上也是为了适应开发规则、符合业务逻辑而设计的。

        javaEE标准分层就是各大企业为了高效开发设计出来的一种逻辑分层结构模型,主要分为:表现层 —> 控制层 —> 服务层 —> 数据持久层;

        写代码不仅是为了设计程序,另一方面也是为了给程序员看的,虽然五大注解的功能都是一样的,但它们各自代表着一种设计层,在开发过程中,哪些类是用在哪一层的,借助对应的注解就可以很直观的起到标识功能,便于流程调度。


2. 方法注解 @Bean:

        除了上面介绍的五大类注解之外,还有一种专门使用在方法上的“方法注解”:@Bean;

        @Bean 注解的作用:告诉方法产生一个 Bean 对象,将这个对象交给 Spring IoC容器管理,所以这个方法要返回创建的对象;

2.1 存储 Bean:

        先在 demo 包下创建一个 bean 包,在该包下创建一个类 PersonBean:

2.2 获取 Bean 对象:

        通过 @Bean 注解存储的对象,获取时就不能像之前那样了,因为这个注解的 id 命名规则和五大注解的是不同的;

如图:

注意! 以上报错有两个原因:

  1. @Bean 命名规则,默认情况下存储的Bean对象名和方法名保持一致;
  2. @Bean 注解必须要结合五大类注解一起使用;这是出于保证 Spring 性能所规定的;

修改以上代码:

2.3 @Bean 重命名策略:

        默认情况下 @Bean 注解存储的对象的 id 和方法名一致,除此之外,还可以根据程序员需要,自行重命名;

        写法:

  •         在 @Bean 后面加上括号(),括号对使用{ } ,内部可以设置多个id 名;
  •         { } 内的属可以是 name,也可以是 value,如下图中参数; 

修改后: 

 也可以省略着写:

  • 这样重命名后,产生的 name 或者 value,就作为数组存储着 Bean 的多个名字;
  • 使用重命名后,默认的方法名获取就不再可行了;


3. 对象装配(更简单地获取 Bean 对象):

        从容器中读取到 Bean 对象也叫“对象装配”,是把对象取出来放到某个类中,有时也叫“对象注入”

下面介绍的三种新的注入方式:

  1. 属性注入;
  2. Setter 注入;
  3. 构造方法注入;

3.1 属性注入:

        属性注入要借助 @Autowired 注解;

        示例:现在有一个数据表 personDao,其中要存储上面创建出来的 PersonBean 的实例,因此思路为:创建一个 PersonDao 实体类,在这个类内部,借助属性注入直接将 PersonBean 类的 Bean 对象注入到 PersonDao 类中;

3.1.1 优缺点分析:

优点:

  1. 写法简单、使用方便方便;

缺点:

  1. 不能注入被 final 修饰的对象;

  2. 只适用于 IoC 容器;
  3. 只有在使用的时候才会出现 NPE(空指针异常);
  4. 容易违背单一设计原则;

3.2 Setter 注入:

        Setter 注入也要借助 @Autowired 注解,但它确实使用在 setter() 方法上的;

        示例:还是把 PersonBean 对象注入到 PersonDao 类中,稍微修改代码,注解这次要加到 Setter() 方法上;

3.2.1 优缺点分析:

优点:

  1. 由于Setter()方法每次只传递一个对象,所以符合单一设计原则,它是前期 Spring 官方推荐的注入方式;
  2. 保证了使用前注入类的对象不为空;

缺点:

  1. 不能注入被 final 修饰的对象;
  2. 被注入的对象可能会被类内部其他方法修改;

3.3 构造方法注入:

        构造方法注入还是要借助 @Autowired 注解,但这里是使用在构造方法上;

        注意事项:

  • 如果只有一个构造方法,那么 @Autowired 注解可以省略;
  • 如果有多个构造方法,就必须使用 @Autowired 注解标明使用的哪个构造方法;

        示例:依然是把 PersonBean 对象注入到 PersonDao 类中,稍微修改代码,注解这次要加到构造方法上;

3.3.1 优缺点分析:

优点:

  1. 可以注入注入被 final 修饰对象,因为 java 中被 final 修饰的对象要么直接赋值,要么在构造方法中赋值,所以可用;
  2. 注入的对象不会被改变;
  3. 保证了注入的对象正确初始化,不为空;
  4. 通用性好;
  5. Spring 官方目前最为推荐的注入方式;


4. @Resource 注解:

        这个注解也是用来进行对象注入的,先看演示:

4.1 @Resource 和 @AutoWired 的区别:

  • 来源不同:@Autowired 来源于 Spring,@Resource 来源于 JDK 本身;
  • 功能差异:@Resource 比 @Autowired 支持更多参数的设置;
  • 范围差异:@Resource 不能用于构造方法注入,@Autowired 可以用于以上三种注入方式;
  • 查找方式不同:如果在同一个类型的 Bean 存储了多份的环境下,二者的查找方式不同,@Resource 先根据名称去查,之后再根据类型去查;而@Autowired 先根据类型去查,再根据名称去查;于是 @Resource 更适用于查找多个相同类型的 Bean;

4.1.1 解决同一类型 @Bean 报错问题:

        当同一类型的 Bean 存储了多份时,如果仅仅使用 Spring 的 @Autowired 注解来注入到类中,可能会出现查找不到唯一匹配目标的错误。

        示例:DogsBean 类中使用 @Bean 注解存储了两只颜色不同的小狗,现在想在 DogController 类中把某个指定的小狗注入;        

 运行就会出现错误:不能匹配到唯一值。

解决办法:

方法一:使用 @Resource(name= ""):因为 @Autowired 注解的参数只能是 Boolean 类型的值,所以不能指定名称,而 @Resource却可以;

 方法二: 使用 @Qualifier(value="") 注解:有的人可能就是只想用@Autowired注解,那也行,那么就要结合 @Qualifieer 注解一起使用;

 

 

       

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/539211.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hadoop的基本概念和架构

Hadoop的基本概念和架构 学习路线 hadoop的基本概念和架构hadoop的安装和配置hadoop的HDFS文件系统hadoop的MapReduce计算框架hadoop的YARN资源管理器hadoop的高级特效&#xff0c;如HBase&#xff0c;Hive&#xff0c;Pig等hadoop的优化和调优hadoop的应用场景&#xff0c;如…

23种设计模式之组合模式(Composite Pattern)

前言&#xff1a;大家好&#xff0c;我是小威&#xff0c;24届毕业生&#xff0c;在一家满意的公司实习。本篇文章将23种设计模式中的组合模式&#xff0c;此篇文章为一天学习一个设计模式系列文章&#xff0c;后面会分享其他模式知识。 如果文章有什么需要改进的地方还请大佬不…

跨平台应用开发进阶(六十三):微信小程序开发

文章目录 一、前言二、开发物料准备2.1 个性化小程序2.2 开发时如何调用API2.3 微信小程序开发常用组件库2.3.1 WeUI2.3.2 Vant Weapp2.3.3 iView Weapp2.3.4 ColorUI2.3.5 Wux Weapp2.3.6 TaroUI2.3.7 MinUI 三、创建一个UNI-APP项目四、进行调试4.1 启动微信开发者工具4.2 调…

网络基础进阶

1、交换机接口类型 Console口&#xff1a;也称为&#xff1a;串口接口&#xff0c;一般用于与PC连接&#xff0c;用于配置和监控交换机。百兆以太网接口&#xff1a;用于连接计算机和交换机之间的通信。Console到的网络接口&#xff1a;俗称交叉串口&#xff0c;是用于连接交换…

Day.js 常用方法

Day.js是一个极简的JavaScript库&#xff0c;可以为现代浏览器解析、验证、操作和显示日期和时间&#xff0c;文件大小只有2KB左右&#xff0c;下载、解析和执行的JavaScript更少。 官网&#xff1a;Day.js中文网 1. 安装 npm install dayjs --save 2.引入 3. 初始化日期 …

基于开源大模型Vicuna-13B构建私有制库问答系统

本教程专注在怎么使用已经开源的模型和项目&#xff0c;构建一个可以私有化部署的问答知识库&#xff0c;而且整体效果要有所保障。 主要工作包括&#xff1a; 选择基础模型&#xff0c;openAI&#xff0c;claude 这些商用的&#xff0c;或者其他的开源的&#xff0c;这次我们…

vue 全局注册--

注册全局-过滤器 filters 的 js 文件 /*** 格式化单位展示* param value* param unit* returns {string}*/const unitFormatter function (value , unit ) {value value || -return value ([, -].includes(value) ? : unit) }export default {unitFormatter }vue -ma…

如何使用ArcGIS进行字段连接

&#xff08;本文首发于“水经注GIS”公号&#xff0c;关注公号免费领取地图数据 当我们的shapefile文件属性表中的数据不够丰富&#xff0c;而Excel表格中的数据很丰富的时候&#xff0c;我们可以通过两个数据之间的共有字段进行连接&#xff0c;这里为大家介绍一下ArcGIS中字…

五、easyUI中的datagrid(数据表格)组件

1.datagrid&#xff08;数据表格&#xff09;组件的概述 datagrid以表格形式展示数据&#xff0c;并提供了丰富的选择、排序、分组和编辑数据的功能支持。datagrid的设计用于缩短开发时间&#xff0c;并且使开发人员不需要具备特定的知识。它是轻量级的且功能丰富&#xff0c;…

MDM(移动设备管理策略系统)、MAM、MCM作用

目录 定义 MDM MAM MCM 作用 定义 MDM 移动设备管理是一种软件应用程序,用于管理企业中的终端,如笔记本电脑、智能手机、平板电脑等。随着越来越多的员工使用这些设备,各种形式和规模的企业现在都转向移动设备管理,以增强数据安全性并提高生产力。 Device Management…

C嘎嘎~~[构造函数提升篇]

构造函数提升篇 1. 再谈构造函数1.1. 引入1.1.1问题引入1.1.2 const引入 1.2 正篇1.2.1 构造函数体赋值1.2.2 初始化列表1.2.3.1 浅浅认识1.2.3.2 构造函数的 行走顺序1.2.3.3 引用修饰成员变量1.2.3.4 没有默认构造的自定义类型 1.2.3初始化列表的 坑1.2.4 谈谈初始化列表 和 …

如何使用ChatGPT生成Excel公式?

Excel是日常工作和生活中经常使用的一款数据统计和分析软件&#xff0c;它可以帮助我们快速完成各种复杂的数据计算。但对于一些复杂的计算公式&#xff0c;不是每个人都能轻松掌握&#xff0c;或者说有时候并不想手动输入计算公式。如果能有一个智能工具&#xff0c;帮助我们快…

libiosa语音信号处理

img { margin: auto; display: block } librosa是一个非常强大的python语音信号处理的第三方库&#xff0c;本文参考的是librosa的官方文档&#xff0c;本文主要总结了一些重要&#xff0c;对我来说非常常用的功能。学会librosa后再也不用python去实现那些复杂的算法了&#xf…

人工智能与大模型主题师资培训落地,飞桨持续赋能AI人才培养

5月12日-5月14日&#xff0c;由百度飞桨联合中国自动化学会、复旦大学共同举办的“人工智能与大模型”主题师资培训班在百度飞桨&#xff08;张江&#xff09;人工智能产业赋能中心圆满举办。来自全国各地17所高校、26个人工智能及相关专业的50名教师线下参加此次培训。复旦大学…

Java --- redis的缓存淘汰策略

目录 一、redis内存查看与设置 二、redis的数据删除方式 三、redis缓存淘汰策略 一、redis内存查看与设置 查看redis最大占用内存&#xff1a; redis默认内存使用&#xff1a; 不设置最大内存大小或设置为0&#xff0c;在64位操作系统下不限制内存大小&#xff0c;32位操作系…

Linux系统编程(四)—— 进程基本知识

一、进程标识符pid 1、pid的类型&#xff1a;pid_t pid 是有符号的16位整型数&#xff0c;也就是说可以同时进行三万多进程。 2、命令&#xff1a;ps ps命令用于报告当前进程的信息&#xff1a; ps命令有着不同的组合&#xff0c;可以显示进程不同的内容&#xff1a; &…

夜天之书 #83 Web API 的开发工具和平台

上一篇文章《Web API 简介》的落脚点是 Web API 的体验。 Web API 作为许多软件的第一道门面&#xff0c;提升其体验的努力从来没有停止过。今天&#xff0c;围绕 Web API 的开发体验和使用体验&#xff0c;已经成长出一个庞大的软件生态。本文以常用的 Web API 开发工具和平台…

什么是 Java中的零拷贝

什么是零拷贝 WIKI中对其有如下定义&#xff1a; “Zero-copy” describes computer operations in which the CPU does not perform the task of copying data from one memory area to another. 从WIKI的定义中&#xff0c;我们看到“零拷贝”是指计算机操作的过程中&#x…

数据库迁移 | 拥抱国产化数据库openGauss

Squids DBMotion再添新库同步能力&#xff0c;本期增加了对openGauss数据库的同步支持。 openGauss数据库是一款开源关系型数据库管理系统&#xff0c;采用木兰宽松许可证v2发行。openGauss内核深度融合华为在数据库领域多年的经验&#xff0c;结合企业级场景需求&#xff0c;持…

PFTL101B 20KN 3BSE004203R1主要介绍ACS380 Modbus通讯功能

​ PFTL101B 20KN 3BSE004203R1ABB系统优化船舶性能、效率和可持续性 根据经合组织的一份报告&#xff0c;货物和人员的海上运输是全球经济活动的重要驱动力&#xff0c;到2050年将增加两倍。据国际海事组织&#xff08;IMO&#xff09;称&#xff0c;这一增长将导致该行业的温…