【Spring进阶系列丨第六篇】Spring的Bean管理(基于注解)

文章目录

  • 一、说明
  • 二、用于创建对象的
    • 2.1、Component注解
      • 2.1.1、定义Bean
      • 2.1.2、主配置文件配置扫描注解
      • 2.1.3、测试
      • 2.1.4、Component注解总结
    • 2.2、Controller注解
    • 2.3、Service注解
    • 2.4、Repository注解
  • 三、用于注入数据的
    • 3.1、Autowired注解
      • 3.1.1、定义Bean
      • 3.1.2、主配置文件配置扫描注解
      • 3.1.3、测试
      • 3.1.4、改造
      • 3.1.5、总结
    • 3.2、Qualifier注解
      • 3.2.1、定义Bean
      • 3.2.2、总结
    • 3.3、Resource注解
      • 3.3.1、定义Bean
      • 3.3.2、总结
    • 3.4、Value注解
      • 3.4.1、案例1
        • 3.4.1.1、定义Bean
        • 3.4.1.2、测试
      • 3.4.2、案例2
        • 3.4.2.1、创建db.properties文件
        • 3.4.2.2、主配置文件需要将properties文件引入进来
        • 3.4.2.3、定义Bean
        • 3.4.2.4、测试
      • 3.4.3、总结
    • 3.5、大总结
  • 四、用于改变Bean的作用域的
    • 4.1、定义Bean
    • 4.2、测试
    • 4.3、总结
  • 五、和Bean的生命周期相关的
    • 5.1、定义Bean
    • 5.2、测试
    • 5.3、总结

在这里插入图片描述

一、说明

回顾一下基于xml配置的Spring对Bean的管理 ,对Bean的完整管理如下所示:

<bean id="" class="" init-method="" destroy-method="" scope=""><property name="" value=""/><property name="" ref=""/>
</bean>

分析可以发现:我们对Bean的管理就四个方面,分别是:

  • 用于创建对象的
  • 用于注入数据的
  • 用于改变Bean的作用域的
  • 和Bean的生命周期相关的

其实对于注解来说,也是包括了这四个方面,换句话说,使用注解的方式管理Bean和使用xml的方式管理Bean作用是完全一样的,区别仅仅在于配置的形式不同而已。

二、用于创建对象的

2.1、Component注解

2.1.1、定义Bean

@Component
public class DogService {}

2.1.2、主配置文件配置扫描注解

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!-- 告诉spring在创建容器时要扫描的包   --><context:component-scan base-package="cn.bdqn"/></beans>

2.1.3、测试

 @Test
public void testDogServiceImpl() throws Exception{// 1、读取主配置文件信息,获取核心容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");DogServiceImpl dogService = (DogServiceImpl) ac.getBean("dogServiceImpl");System.out.println(dogService);
}

2.1.4、Component注解总结

  • 作用

    ​ 用于把对当前修饰的类创建出来,并存放到Spring容器中。

  • 属性

    ​ a. 用该注解所创建的对象默认的id名称是当前类名,且首字母改小写

    ​ b. 可以通过value属性手动的指定bean的id。

2.2、Controller注解

​ 一般用在表现层,例如SpringMVC、Struts2

2.3、Service注解

​ 一般用在业务层,例如Service层

2.4、Repository注解

​ 一般用在持久层7.2.5、总结

  • Controller、Service、Repository这三个注解他们的作用和属性与Component是一模一样。
  • 既然一模一样,之所以Spring框架还要提供,主要是Spring框架为我们提供明确的三层使用的注解,使我们的三层对象更加清晰。
  • 他们的作用就和在XML配置文件中编写一个标签实现的功能是一样的

三、用于注入数据的

3.1、Autowired注解

作用:

​ 自动按照类型注入。

3.1.1、定义Bean

// 用户service接口
public interface UserService {public void printUserDao();
}
// 用户service接口实现,bean的名称改为:userService
@Service("userService")
public class UserServiceImpl implements UserService {@Autowiredprivate UserDao userDao;// 打印UserDao,看是否可以将值打印出来,如果打印出来说明值真的注入成功了public void printUserDao(){System.out.println(userDao);}
}
// 用户UserDao接口
public interface UserDao {}
// 用户UserDao接口实现,bean的名称改为:userDao01
@Repository("userDao01")
public class UserDaoImpl01 implements UserDao {}

3.1.2、主配置文件配置扫描注解

<beans><!-- 告诉spring在创建容器时要扫描的包   --><context:component-scan base-package="cn.bdqn"/>
</beans>

3.1.3、测试

@Test
public void testUserServiceImpl() throws Exception{// 1、读取主配置文件信息,获取核心容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");UserService userService = (UserService) ac.getBean("userService");userService.printUserDao();	// cn.bdqn.dao.impl.UserDaoImpl@7a52f2a2
}

3.1.4、改造

假设系统中存在两个UserDao的实现,现在再添加一个。现在再添加测试:

@Repository("userDao02")
public class UserDaoImpl02 implements UserDao {}

再次运行程序,会发现,程序报错:

No qualifying bean of type 'cn.bdqn.dao.UserDao' available: expected single matching bean but found 2: userDao01,userDao02

翻译:没有找到一个可用的UserDao,期望能够匹配一个,但是发现了2个。换句话说,由于是根据类型匹配的,而userDao01,userDao02都是符合注入的类型的,不知道要用哪个了.

该如何解决呢?既然Spring不知道具体要用哪个了,那我们由开发者来去指定其中的一个告诉Spring你就用这个注入就可以了,那么实现方式就是:通过名称告诉即可

解决方案:

@Service("userService")
public class UserServiceImpl implements UserService {// 将变量的名称修改为userDao01,那么依赖注入的时候就使用UserDaoImpl01@Autowiredprivate UserDao userDao01;
}

再次测试,程序正常执行。

3.1.5、总结

  • 该注解是根据类型自动注入,假如只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。
  • 如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错。
  • 如果容器中有多个bean对象类型和要注入的变量类型匹配,则可能会发生错误,解决办法就是修改变量的名称为其中的某一个bean的名称

3.2、Qualifier注解

​ 在7.3.1章节使用Autowired注解的时候,会存在一个问题,就是如果系统中存在多个类型的Bean都匹配的时候,就会找不到到底要使用哪个Bean对象了,会报错,我们采取的解决办法是:修改变量名即可解决 , 但是这种做法实际上是挺菜的,我现在就想使用userDao这个变量名,那么能否有一种更好的解决办法呢?答案是肯定的,即使用Qualifier注解。

3.2.1、定义Bean

​ Bean的定义,仍然采用7.3.1章节所定义好的Bean,唯一的区别是UserServiceImpl这个Bean,修改如下:

public class UserServiceImpl implements UserService {@Autowired@Qualifier(value = "userDao01")	// 通过此注解中的value属性明确指定要用哪个name的beanprivate UserDao userDao;
}

3.2.2、总结

  • 在按照类型注入的基础之上再按照名称注入,它在给类的成员变量注入时不能单独使用,需要搭配Autowired注解。

3.3、Resource注解

3.3.1、定义Bean

​ Bean的定义,仍然采用7.3.1章节所定义好的Bean,唯一的区别是UserServiceImpl这个Bean,修改如下:

@Service("userService")
public class UserServiceImpl implements UserService {@Resource(name = "userDao01")private UserDao userDao;
}

3.3.2、总结

  • 该注解采用的是直接按照bean的id注入,它可以独立使用,name用于指定bean的id。

注意:

使用Autowired、Qualifier以及Resource这三个注解都只能注入其他bean类型的数据,对于基本数据类型和String类型是无法通过使用该3个注解实现。同时,对于集合数据类型的注入只能通过XML来实现。


3.4、Value注解

作用:

​ 用于注入基本类型和String类型的数据。

3.4.1、案例1

3.4.1.1、定义Bean
@Component("jdbcUtils")
public class JdbcUtils {@Value("com.mysql.jdbc.Driver")private String driverClass;
}
3.4.1.2、测试
@Test
public void testJdbcUtils() throws Exception{// 1、读取主配置文件信息,获取核心容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");JdbcUtils utils = (JdbcUtils) ac.getBean("jdbcUtils");System.out.println(utils);	// com.mysql.jdbc.Driver
}

3.4.2、案例2

如果Value注解用于案例1,那这样太菜了,我们要为driverClass这个变量赋值,那岂不是直接赋值得了,还需要搞一个Value直接赋值吗?显然是没有必要的,所以一般来说,Value注解常用于对配置文件内容的读取。

3.4.2.1、创建db.properties文件
driverClass=com.mysql.jdbc.Driver
port=3306
3.4.2.2、主配置文件需要将properties文件引入进来
<beans><!-- 告诉spring在创建容器时要扫描的包   --><context:component-scan base-package="cn.bdqn"/><!-- 将properties文件引入到Spring框架中--><context:property-placeholder location="classpath:db.properties"/>
</beans>
3.4.2.3、定义Bean
@Component("jdbcUtils")
public class JdbcUtils {@Value("${driverClass}")private String driverClass;@Value("${port}")private Integer port;
}
3.4.2.4、测试
@Test
public void testJdbcUtils() throws Exception{// 1、读取主配置文件信息,获取核心容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");JdbcUtils utils = (JdbcUtils) ac.getBean("jdbcUtils");System.out.println(utils);	// com.mysql.jdbc.Driver,3306
}

3.4.3、总结

该注解通过可以实现对基本数据类型和String类型的注入,并且是支持使用Spring的EL表达式。那么对于Spring的EL表达式的语法就是:${表达式}。

3.5、大总结

以上注解的作用就和在xml配置文件中的bean标签中写一个标签的作用是一样的

四、用于改变Bean的作用域的

方式:

  • 使用Scope注解,作用是用于指定bean的作用范围。该注解有一个value属性,可以指定范围的取值,常用取值:singleton、 prototype
  • 该Scope注解默认的value值就是单例的【singleton】

4.1、定义Bean

Bean的定义,仍然采用7.3.1章节所定义好的Bean,唯一的区别是UserServiceImpl这个Bean修改作用域,修改如下:

@Service("userService")
@Scope("singleton")
public class UserServiceImpl implements UserService{}

4.2、测试

@Test
public void testUserServiceImpl() throws Exception{// 1、读取主配置文件信息,获取核心容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");UserService userService = (UserService) ac.getBean("userService");UserService userService2 = (UserService) ac.getBean("userService");System.out.println(userService == userService2); // true
}

改造一下:如果将上例的UserServiceImpl中的Scope改为prototype,则再次测试的时候会返回false。

4.3、总结

Scope该注解的作用就和在bean标签中使用scope属性实现的功能是一样的

五、和Bean的生命周期相关的

5.1、定义Bean

​ Bean的定义,仍然采用7.3.1章节所定义好的Bean,唯一的区别是UserServiceImpl这个Bean添加了一个初始化方法和销毁方法。

@Service("userService")
public class UserServiceImpl implements UserService {@PostConstructpublic void init(){System.out.println("对象初始化了");}@PreDestroypublic void destroy(){System.out.println("对象销毁了");}
}

5.2、测试

@Test
public void testUserServiceImpl() throws Exception{// 1、读取主配置文件信息,获取核心容器对象ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");ac.close();
}// 对象初始化了
// 对象销毁了

5.3、总结

这个两个注解作用就和在bean标签中使用init-method和destroy-methode的作用是一样的。


在这里插入图片描述

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

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

相关文章

Linux学习(11)——进程的基本概念

目录 一、程序 1、什么是程序&#xff1f; 二、进程 1、什么是进程&#xff1f; 2、进程具有的特征 2.2进程&#xff0c;线程&#xff0c;协程 2.2.1 进程和线程的区别 2.2.2如何查看一个程序是多线程还是单线程 3、进程使用内存的问题 ①内存泄漏&#xff1a;Memory L…

GO语言笔记1-变量与基本数据类型

变量使用步骤 声明赋值使用 package main import "fmt" func main(){var age int //声明一个 int类型的变量叫ageage 18 //给变量用 赋值fmt.Println(age) //使用变量 输出变量的值 } 编译运行输出变量值 变量的四种使用方式 package main import "fmt&q…

【大数据】Spark学习笔记

初识Spark Spark和Hadoop HadoopSpark起源时间20052009起源地MapReduceUniversity of California Berkeley数据处理引擎BatchBatch编程模型MapReduceResilient distributed Datesets内存管理Disk BasedJVM Managed延迟高中吞吐量中高优化机制手动手动APILow levelhigh level流…

RFID技术在3C家电中的全方位应用

RFID技术在3C家电中的全方位应用 一、RFID技术简述 射频识别&#xff08;RFID&#xff09;技术是一种无线通信技术&#xff0c;已经在各行各业得到广泛应用。在3C家电领域&#xff0c;RFID技术的应用正在逐渐增加&#xff0c;为产品追溯、库存管理、防伪验证等方面提供了许多…

leetcode1944. 队列中可以看到的人数

Problem: 1944. 队列中可以看到的人数 文章目录 题目解题方法复杂度Code 题目 有 n 个人排成一个队列&#xff0c;从左到右 编号为 0 到 n - 1 。给你以一个整数数组 heights &#xff0c;每个整数 互不相同&#xff0c;heights[i] 表示第 i 个人的高度。 一个人能 看到 他右边…

JVM之对象创建

对象创建的流程 1.类加载检查 虚拟机遇到一条new指令时&#xff0c;首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用&#xff0c;并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有&#xff0c;那必须先执行相应的类加载过程。new指令对…

含科研思考六、关于【图神经网络】的一些要点 | 图神经网络节点表示学习研究:选题参考、问题探讨 | 图神经网络多模态 | 异构图神经网络

我们抬头便看到星光,星星却穿越了万年. 🎯作者主页: 追光者♂🔥 🌸个人简介: 📝[1] CSDN 博客专家📝 🏆[2] 人工智能领域优质创作者🏆 🌟[3] 2023年城市之星领跑者TOP1(哈尔滨)🌿 🌿[4] 2022年度博客之星人工智能领域TOP4🌟 🏅

Docker-Compose部署Redis(v7.2)主从模式

文章目录 一、前提准备1. redis配置文件2. 下载redis镜像3. 文件夹结构 二、docker-compose三、主从配置1.主节点配置文件 环境 docker desktop for windows 4.23.0redis 7.2 一、前提准备 1. redis配置文件 因为Redis 7.2 docker镜像里面没有配置文件&#xff0c;所以需要…

Color Control

设计一个优秀的用户界面是一项艰巨的任务。特别是如果你想改变UI的颜色,调整所有元素可能需要花费大量时间。Color Control可以帮助你!在检查器中以可视化的方式将你的项目颜色定义为资源。Color Control为你提供了组件,当你编辑它们时,它们会自动更新你的UI元素。 颜色控制…

Oracle-游标

简介 游标即cursor&#xff0c;是一种用于遍历结果集的数据类型。它是一个指向结果集的指针&#xff0c;可以用于遍历结果集中的每一行数据&#xff0c;但是一次只能指向一行。游标通常用于存储过程和函数中&#xff0c;以便在处理结果集时能够逐行处理数据。 语法 /* 游标:(…

花了一小时,拿python手搓了一个考研背单词软件

听说没有好用的电脑端背单词软件&#xff1f;只好麻烦一下&#xff0c;花了一小时&#xff0c;拿python手搓了一个考研背单词软件。 代码已经开源在我的github上&#xff0c;欢迎大家STAR&#xff01; 其中&#xff0c;数据是存放在sqlite中&#xff0c;形近词跳转是根据jaro …

新的centos7.9安装docker版本的jenkins2.436.1最新版本-后端项目发布(四)

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; https://gitee.com/nbacheng/n…

遥感影像-语义分割数据集:2021年昇腾杯复赛数据集详细介绍及训练样本处理流程

原始数据集详情 简介&#xff1a;细粒度语义分割赛道依据现有的遥感地物分类要求&#xff0c; 结合现有的地物分类实际需求&#xff0c;参照地理国情监测、 “三调”等既有地物分类标准&#xff0c;依据遥感地物“所见即所得”原则&#xff0c; 设计地物要素分类体系&#xff…

Excel技巧之【如何修改密码】

我们知道&#xff0c;Excel可以设置多种密码来保护文件&#xff0c;那想要修改密码&#xff0c;要如何操作呢&#xff1f;下面小编来分享一下Excel常用的3种密码的修改方法&#xff0c;一起来看看吧&#xff01; 1. “打开密码” 想要修改Excel表格的“打开密码”&#xff0c…

scratch给数据清单排序 2023年12月中国电子学会图形化编程 少儿编程 scratch编程等级考试四级真题和答案解析

目录 scratch给数据清单排序 一、题目要求 1、准备工作 2、功能实现 二、案例分析

Web前端篇——ElementUI之el-scrollbar + el-backtop + el-timeline实现时间轴触底刷新和一键返回页面顶部

ElementUI之el-scrollbar el-backtop el-timeline实现时间轴触底刷新和一键返回页面顶部。 背景&#xff1a;ElementUI的版本&#xff08;vue.global.js 3.2.36&#xff0c; index.css 2.4.4&#xff0c; index.full.js 2.4.4&#xff09; 废话不多说&#xff0c;先看动…

VSCode远程开发配置和SSH免密登录

目录 概要远程开发插件安装开始连接SSH免密登录开发环境配置 概要 现在很多公司都是直接远程到服务器上写代码&#xff0c;使用远程开发&#xff0c;可以在与生产环境相同的环境中开发、测试和部署代码&#xff0c;减少因环境不同而导致的问题。本文将详细介绍如何通过VSCode连…

MS713/MS713T:CMOS 低压、4Ω四路单刀单掷开关,替代ADG713

产品简述 MS713/MS713T 是一款单芯片 CMOS 4 路可选择开关&#xff0c;具有低 功耗、高开关速度、低导通阻抗、低漏电和高带宽特性。其工作 电压范围是 1.8V 到 5.5V &#xff0c;可以广泛应用在电池供电仪器仪表、新 一代的模数转换和数模转换系统中。其高带宽特性可用在 …

【React系列】网络框架axios库的使用

本文来自#React系列教程&#xff1a;https://mp.weixin.qq.com/mp/appmsgalbum?__bizMzg5MDAzNzkwNA&actiongetalbum&album_id1566025152667107329) 一. axios库的基本使用 1.1. 网络请求的选择 目前前端中发送网络请求的方式有很多种&#xff1a; 选择一:传统的Aj…

【K8S 云原生】Pod资源限制、Pod容器健康检查(探针)

目录 一、docker的重启方式和K8S重启方式 1、Pod的重启方式&#xff1a; 2、docker的重启策略&#xff1a; 二、yaml文件快速生成&#xff1a; 三、pod的状态&#xff1a; 四、Pod的资源限制 1、限制的方式和种类 2、CPU的限制的格式&#xff1a; 五、K8S拉取镜像的策…