(b)Spring注解式开发,@Value,@Autowired,@Resource注解属性自动装配时的原理和区别

@Value简单类型的注入

属性注入的三种方式

为了简便开发Spring给我们提供了多样化的注入: @Value注解可以出现在属性上,setter方法上以及构造方法的形参上

简单类型的属性上使用@Value注解完成属性值的注入(可以不提供属性的setter方法)

@Component
public class User {@Value(value = "zhangsan")private String name;@Value("20")private int age;@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}

简单类型属性对应的setter方法上添加@Value注解完成注入

@Component
public class User {private String name;private int age;@Value("李四")public void setName(String name) {this.name = name;}@Value("30")public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}

简单类型属性所在的构造方法的形参上添加@Value注解完成注入

@Component
public class User {private String name;private int age;public User(@Value("张三") String name, @Value("33") int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}

测试程序简单类型的注入

@Test
public void testAutowired(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-di-annotation.xml");UserService userService = applicationContext.getBean("user", UserService.class);System.out.println(user);
}

@Autowired非简单类型的注入

@Autowired注解的应用

@Autowired自动装配注解可以用来注入非简单类型, 单独使用时默认是根据类型进行注入的,若要根据名称注入的话需要配合@Qualifier注解一起使用

  • @Autowired注解可以标注在属性上、setter方法上、构造方法上、构造方法的参数上, 一切具有参数的方法上(可以不提供属性的setter方法上)
  • @Autowired注解可以应用在数组类型的属性上,此时Spring将会把所有匹配的bean自动装配到数组上
  • @Autowired注解可以应用在指定了泛型的集合属性上, 此时Spring会读取集合的泛型信息然后自动装配所有同类型的bean
  • @Autowired注解用在指定了泛型的Map属性上(Map的键值为String), 那么Spring将自动装配所有泛型类型的bean作为value,以bean的id值作为key
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {boolean required() default true;
}

@Autowired注解的required属性

属性值说明
required=true(默认)自动注入的时候要求被注入的Bean必须是存在的,如果不存在则报错
required=false允许某一属性不被设置 , 自动注入的时候Bean存在或者不存在都没关系,存在的话就注入不存在的话也不报错

属性注入的几种方式

Dao接口及其实现类

//UserDao接口
public interface UserDao {void insert();
}//UserDao实现类
@Repository 
public class UserDaoForMySQL implements UserDao{@Overridepublic void insert() {System.out.println("正在向mysql数据库插入User数据");}
}//UserDao接口的另一个实现类
@Repository 
public class UserDaoForOracle implements UserDao{@Overridepublic void insert() {System.out.println("正在向Oracle数据库插入User数据");}
}

非简单类型的属性上使用@Autowired注解完成属性值的注入(可以不提供属性的setter方法)

  • @Autowired注解默认是根据类型注入的,如果UserDao接口有两个实现类,给UserService的自定义属性UserDao时自动注入时会报错(提示Bean的数量大于1)
@Service 
public class UserService {// 自动注入属性@Autowired private UserDao userDao;// 没有提供构造方法和setter方法public void save(){userDao.insert();}
}

非简单类型属性对应的setter方法上使用@Autowired注解完成属性的自动注入

@Service
public class UserService {private UserDao userDao;@Autowiredpublic void setUserDao(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}

非简单类型属性所在的构造方法上使用@Autowired注解完成属性的自动注入

@Service
public class UserService {private UserDao userDao;@Autowiredpublic UserService(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}

非简单类型对应的构造方法的形参上使用@Autowired注解完成属性的自动注入

@Service
public class UserService {private UserDao userDao;public UserService(@Autowired UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}

测试程序

@Test
public void testAutowired(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-injection.xml");UserService userService = applicationContext.getBean("userService", UserService.class);userService.save();
}

省略@Autowired注解

构造方法只有一个并且构造方法的形参名和对象的属性名能够对应上时@Autowired注解可以省略,如果有多个构造方法就不能省略

@Service
public class UserService {private UserDao userDao;// 构造方法的参数只有一个时,自动注入时@Autowired注解可以省略public UserService(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}

属性/方法形参注入的原理

@Autowired注解是根据类型进行自动装配的,所有可能找到多个或者一个

  • 如果是非集合类型的自定义属性找到多个组件,Spring会继续以属性名/形参名作为bean的id值匹配到具体的一个bean,然后为对象的属性赋值
  • 如果是集合类型的属性找到多个组件不会报错,Spring会把容器中的所有集合泛型类型的bean封装到一个集合中然后为这个属性赋值

属性注入: Spring从容器查找组件时先按照属性的类型(可能找到一个或多个bean,也可能没找到bean),若找到多个会将属性名作为id继续匹配到某个具体的bean

  • 根据类型找到且只有一个组件,直接为对象的属性赋值
  • 根据类型没有找到组件则报NoSuchBeanDefinitionException异常
  • 找到了多个bean则会按照属性名作为id继续匹配到某个具体的bean , 找到则会为该属性赋值 ,如果根据id还是找不到则会报错
  • 默认情况下所有使用@Autowired注解的属性默认一定要被赋值,当Spring找不到匹配的bean去装配属性时会抛出异常

方法形参的注入: Spring从容器中找到对应的组件为方法上的每一个形参赋值,注入原理和属性注入原理一样

  • 先按照形参的类型匹配bean,如果匹配多个bean再将形参的变量名作为bean的id继续匹配到某个具体的bean,如果还匹配不到则报错

@Autowired和@Qualifier联合使用

属性注入的几种方式

@Autowired注解和@Qualifier注解联合起来才可以根据名称进行装配,在@Qualifier注解中指定要查找的Bean名称(SpringMVC常用)

  • 默认情况下当IoC容器里存在多个类型相同的bean时,Spring会尝试将属性名/形参名作为bean的Id去匹配到一个具体的bean然后为对象的属性自动装配
  • 若将属性名/形参名作为bean的Id还是匹配不到具体的bean,此时自动装配将无法工作即报错
  • 此时可以添加一个@Qualifier注解指定一个字符串作为bean的Id去容器中匹配对应名称的bean,找到则为对象的属性自动装配,再找不到还报错

Dao层的UserDao接口及其实现类

public interface UserDao {void insert();
}
@Repository 
public class UserDaoForMySQL implements UserDao{@Overridepublic void insert() {System.out.println("正在向mysql数据库插入User数据");}
}
@Repository 
public class UserDaoForOracle implements UserDao{@Overridepublic void insert() {System.out.println("正在向Oracle数据库插入User数据");}
}

非简单类型的属性上额外添加@Qualifier注解指定bean的Id(默认按照属性名)去容器中匹配对应名称的bean完成对象属性的自动装配

@Service 
public class UserService {// 自动注入属性@Autowired @Qualifier("userDaoForOracle") private UserDao userDao;// 没有提供构造方法和setter方法public void save(){userDao.insert();}
}

非简单类型属性对应的setter方法上额外添加@Qualifier注解指定bean的Id(默认按方法形参的变量名)去容器中匹配对应名称的bean完成对象属性的自动装配

@Service
public class UserService {private UserDao userDao;@Autowired// 指定要查找的bean的名称@Qualifier("userDaoForOracle") public void setUserDao(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
} 

非简单类型属性所在方法的形参中额外添加@Qualifiter注解指定bean的Id(默认按照形参的变量名)去容器中匹配对应名称的bean完成对象属性的自动装配

@Autowired
public void setUserDao(@Qualifier("userDaoForOracle") UserDao userDao ) {// 容器启动时候bean对象就会被创建,那么这个方法也会自动运行 System.out.println(bookDao);System.out.println(bookService);
}

@Resource非简单类型注入(通用)

@Resource和@Autowired的区别

来源的区别

  • @Resource注解是JDK扩展包属于JDK的一部分,所以该注解是标准注解更加具有通用性(JSR-250标准中制定的注解类型, JSR是Java规范提案)
  • @Autowired注解是Spring框架自己的

注入方式的区别

  • @Resource注解根据名称装配: 默认使用标注处的属性名/形参名作为bean的Id去匹配bean,如果找不到还会通过类型装配但要求这种类型的Bean只能有一个
  • @Autowired注解根据类型装配: 默认根据标注处的属性名/形参名的类型去匹配bean,如果想根据名称装配需要配合@Qualifier注解一起用

注解的作用范围不同

  • @Resource注解可以标注在属性上、setter方法上
  • @Autowired注解可以标注在属性上、setter方法上、构造方法上、构造方法的参数上

@Resource注解属于JDK扩展包所以不在JDK当中需要额外引入jakarta.annotation-api依赖(高于JDK11或低于JDK8需要引入以下依赖)

  • Spring6不再支持JavaEE而是JakartaEE9 (Oracle把JavaEE贡献给Apache了, Apache把JavaEE的名字改成JakartaEE了,之前的包名javax.*统一修改为jakarta.*)
<!--Spring6版本引入的依赖-->
<dependency><groupId>jakarta.annotation</groupId><artifactId>jakarta.annotation-api</artifactId><version>2.1.1</version>
</dependency>
<!--spring5-版本引入的javax.annotation-api依赖-->
<dependency><groupId>javax.annotation</groupId><artifactId>javax.annotation-api</artifactId><version>1.3.2</version>
</dependency>

属性注入的几种方式

在属性上使用Resource注解根据指定的bean的Id去容器中匹配对应的bean为属性自动装配

//给UserDao接口的实现类UserDaoForOracle起名xyz
@Repository("xyz")
public class UserDaoForOracle implements UserDao{@Overridepublic void insert() {System.out.println("正在向Oracle数据库插入User数据");}
}
@Service
public class UserService {@Resource(name = "xyz")private UserDao userDao;public void save(){userDao.insert();}
}

在属性上使用Resource注解根据默认的bean的Id(属性名/形参名)去容器中匹配对应的bean为属性自动装配

//指定UserDaoForOracle的名字为userDao,让这个Bean的名字和UserService类中的UserDao属性名一致
@Repository("userDao")
public class UserDaoForOracle implements UserDao{@Overridepublic void insert() {System.out.println("正在向Oracle数据库插入User数据");}
}@Service
public class UserService {//当使用@Resource注解时没有指定name属性的时候,会把属性名当作bean的Id去容器中匹配对应的bean为属性自动装配@Resourceprivate UserDao userDao;public void save(){userDao.insert();}
}

属性上使用Resource注解根据类型注入属性值,当通过bean的Id找不到对应bean的时候也会按照属性的类型进行注入(要求该类型的bean只要一个否则报错)

@Service
public class UserService {//UserService的属性名修改为userDao2@Resourceprivate UserDao userDao2;public void save(){userDao2.insert();}
}

属性对应的setter方法上使用@Resource注解根据默认的bean的Id(属性名/形参名)属性自动装配(setter方法去掉set之后首字母变小写就是bean的Id)

//指定UserDaoForOracle的名字为userDao
@Repository("userDao")
public class UserDaoForOracle implements UserDao{@Overridepublic void insert() {System.out.println("正在向Oracle数据库插入User数据");}
}@Service
public class UserService {private UserDao userDao;@Resourcepublic void setUserDao(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}

属性对应的setter方法上使用@Resource注解指定bean的Id去容器中匹配对应的bean为属性自动装配

@Repository 
public class UserDaoForMySQL implements UserDao{@Overridepublic void insert() {System.out.println("正在向mysql数据库插入User数据");}
}@Service
public class UserService {private UserDao userDao;@Resource(name = "userDaoForMySQL")public void setUserDao(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}

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

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

相关文章

3D设计软件Rhinoceros 6 mac 犀牛6中文版功能特征

Rhinoceros Mac中文版是一款3D设计软件“犀牛”&#xff0c;在众多三维建模软件中&#xff0c;Rhinoceros mac因为其体积小、功能强大、对硬件要求低而广受欢迎&#xff0c;对于专业的3D设计人员来说它是一款非常不错的3D建模软件&#xff0c;Rhinoceros Mac中文版能轻易整合3D…

tensorflow-卷积神经网络-图像分类入门demo

猫狗识别 数据预处理&#xff1a;图像数据处理&#xff0c;准备训练和验证数据集卷积网络模型&#xff1a;构建网络架构过拟合问题&#xff1a;观察训练和验证效果&#xff0c;针对过拟合问题提出解决方法数据增强&#xff1a;图像数据增强方法与效果迁移学习&#xff1a;深度…

DAZ To UMA⭐三.导入Blender的配置, 及Blender快捷键

文章目录 🟥 Blender快捷键1️⃣ 3D视图快捷键2️⃣ 视角快捷键3️⃣ 编辑快捷键4️⃣ 对物体的操作🟧 Blender导入FBX的配置🟩 设置脸部骨骼大小1️⃣ 切换视角2️⃣ 缩小脸部骨骼3️⃣ 本节效果预览🟦 设置眼角膜透明度🟥 Blender快捷键 1️⃣ 3D视图快捷键 快捷键…

【C语言】进阶——结构体+枚举+联合

①前言&#xff1a; 在之前【C语言】初阶——结构体 &#xff0c;简单介绍了结构体。而C语言中结构体的内容还有更深层次的内容。 一.结构体 结构体(struct)是由一系列具有相同类型或不同类型的数据项构成的数据集合&#xff0c;这些数据项称为结构体的成员。 1.结构体的声明 …

CSS实现鼠标悬停图片上升显示

文章目录 前言一、实现效果二、实现思路 前言 当我们想在图片上面放置一些文字内容时&#xff0c;发现不管怎么放置&#xff0c;要么就是图片影响到文字的观感&#xff0c;要么就是文字挡住图片的细节&#xff0c;那么怎么可以既看到图片的细节又可以看到对图片的文字描述呢&a…

mysqld_exporter监控MySQL服务

一、MySQL授权 1、登录MySQL服务器对监控使用的账号授权 CREATE USER exporterlocalhost IDENTIFIED BY 123456 WITH MAX_USER_CONNECTIONS 3; GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO exporterlocalhost; flush privileges;2、上传mysqld_exporter安装包&#…

springboot整合MeiliSearch轻量级搜索引擎

一、Meilisearch与Easy Search点击进入官网了解&#xff0c;本文主要从小微型公司业务出发&#xff0c;选择meilisearch来作为项目的全文搜索引擎&#xff0c;还可以当成来mongodb来使用。 二、starter封装 1、项目结构展示 2、引入依赖包 <dependencies><dependenc…

基于图像形态学处理的路面裂缝检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ...................................................... %1&#xff1a;从文件夹中读取多个…

spring的ThreadPoolTaskExecutor装饰器传递调用线程信息给线程池中的线程

概述 需求是想在线程池执行任务的时候&#xff0c;在开始前将调用线程的信息传到子线程中&#xff0c;在子线程完成后&#xff0c;再清除传入的数据。 下面使用了spring的ThreadPoolTaskExecutor来实现这个需求. ThreadPoolTaskExecutor 在jdk中使用的是ThreadPoolExecutor…

asp.net企业生产管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net 企业生产管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语 言开发 二、功能介绍 (1)用户管理&…

C# OpenCvSharp 基于直线检测的文本图像倾斜校正

效果 项目 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using OpenCvSharp;namespace OpenCvSharp_基于直线检测的文…

Linux基础指令(五)

目录 前言1. 打包和压缩1.1 是什么1.2 为什么1.3 怎么办&#xff1f; 2. zip & unzip3. tar 指令结语&#xff1a; 前言 欢迎各位伙伴来到学习 Linux 指令的 第五天&#xff01;&#xff01;&#xff01; 在上一篇文章 Linux基本指令(四) 当中&#xff0c;我们学习了 fin…

C语言入门Day_25 函数与指针小结

目录 前言&#xff1a; 1.函数 2.指针 3.易错点 4.思维导图 前言&#xff1a; 函数就像一个“有魔法的加工盒”&#xff0c;你从入口丢一些原材料进去&#xff0c;它就能加工出一个成品。不同的函数能加工出不同的成品。 入口丢进去的瓶子&#xff0c;水和标签就是输入&a…

【服务端 | Redis】如何使用redis 有序集合实现股票交易的订单表(价格优先、时间优先)

前两天倒腾redis的有序集合时&#xff0c;自己发现了一个问题&#xff0c;redis的有序集合在score相同的情况 下是如何排序的&#xff1f; 通过谷歌搜索&#xff0c;发现了一些线索&#xff0c;在score相同的情况下&#xff0c;redis使用字典排序&#xff0c;不过不是太明白什…

计算机网络相关知识点(二)

TCP如何保证传输过程的可靠性&#xff1f; 校验和&#xff1a;发送方在发送数据之前计算校验和&#xff0c;接收方收到数据之后同样需要计算&#xff0c;如果不一致&#xff0c;那么代表传输有问题。 确认应答序&#xff0c;序列号&#xff1a;TCP进行传输时数据都进行了编号…

排查内存泄露

1 通过Performance确认是否存在内存泄露 一个存在内存泄露的 DEMO 代码&#xff1a; App.vue <template><div><button click"myFn" style"width: 200px; height: 200px;"></button><home v-if"ishow"></hom…

Xcode15下载iOS17一直中断解决办法

1、问题描述 目前的 xcode 15 安装时&#xff0c;跟以前有个差别&#xff1a;以往的 xcode 安装时自带了 ide、sdk 等工具包&#xff0c;安装后即可开始开发&#xff0c;而最新的包则被分开成了不同的包&#xff0c;这里以 ios 开发包为例&#xff1a;Xcode_15.xip 和 iOS_17_…

软件测试之敏捷项目风险管理

敏捷项目管理是近年来最为流行的项目管理方式之一。这主要归功于敏捷管理的特点&#xff1a;尽早交付、持续改进、灵活管理、团队投入、充分测试。它能充分利用测试周期&#xff0c;并监测每个测试过程中容易出现的问题&#xff0c;加快项目迭代速度&#xff0c;从而推进项目高…

docker 配置 gpu版pytorch环境--部署缺陷检测--Anomalib

目录 一、docker 配置 gpu版pyhorch环境1、显卡驱动、cuda版本、pytorch cuda版本三者对应2、拉取镜像 二、部署Anomalib1、下载Anomalib2、创建容器并且运行3、安装Anomalib进入项目路径安装依赖测试&#xff1a; 一、docker 配置 gpu版pyhorch环境 1、显卡驱动、cuda版本、p…

《优化接口设计的思路》系列:第四篇—接口的权限控制

系列文章导航 《优化接口设计的思路》系列&#xff1a;第一篇—接口参数的一些弯弯绕绕 《优化接口设计的思路》系列&#xff1a;第二篇—接口用户上下文的设计与实现 《优化接口设计的思路》系列&#xff1a;第三篇—留下用户调用接口的痕迹 《优化接口设计的思路》系列&#…