当前位置: 首页 > news >正文

Spring framework Day10:JSR330注入注解

前言

JSR330是Java社区标准化进程(Java Community Process,简称JCP)中的一个规范,全名为"Dependency Injection for Java",即Java的依赖注入规范。它定义了一组注解和相关的规范,用于实现依赖注入(Dependency Injection,简称DI)。

依赖注入是一种设计模式,旨在解耦应用程序中的不同模块或组件之间的依赖关系。通过依赖注入,可以将对象的创建、维护和配置等责任从使用对象的代码中剥离出来,并由容器负责提供和注入所需的依赖项。

 

一、开始学习

本次主学习三个注解,@RequiredArgsConstructor、@Inject、@Named。那么它们分别是什么意思,有什么用呢?

@RequiredArgsConstructor@Inject@Named是JSR330规范中的注解,用于实现依赖注入。

  1. @RequiredArgsConstructor:这是一个Lombok注解,而不是JSR330规范中的注解。它可以用于生成一个包含所有标记为final@NonNull的字段的构造函数。这样,在使用@RequiredArgsConstructor注解的类中,就无需手动编写构造函数,Lombok会自动帮我们生成。这在依赖注入中特别有用,可以省去手动编写大量的构造函数代码。

  2. @Inject:这是JSR330规范中的注解,用于标记需要进行依赖注入的构造方法、字段或者方法。通过在目标类中标记@Inject,依赖注入框架会在需要的时候自动实例化并注入相应的依赖项。

  3. @Named:也是JSR330规范中的注解,用于为依赖项指定名称或者限定符。当一个接口有多个实现类时,可以通过@Named注解配合不同的名称来区分注入的具体实例。在使用@Inject进行注入时,可以结合@Named注解指定要注入的具体实现。

这些注解都是为了简化依赖注入的使用,并保持与JSR330规范的一致性。通过标记相关的注解,我们可以更方便地使用依赖注入框架来管理和注入各个组件的依赖关系。

1、新建项目,结构如下

2、导入 spring 依赖 
 <!-- spring 的核心依赖 --><dependencies><!-- https://mvnrepository.com/artifact/org.springframework/spring-context --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.23</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.4.5</version></dependency><!-- JSR 330 标准注入注解 --><dependency><groupId>javax.inject</groupId><artifactId>javax.inject</artifactId><version>1</version></dependency></dependencies>

注意:@Inject 不存在 JDK 11 中,如果要使用需要额外添加依赖,我使用的是 JDK 11,所以需要自己添加依赖使用 @Inject 注解。

3、在 service 包下新建一个 UserService 接口,在 impl 包下新建一个 UserServiceImpl 实现类

UserService 接口

public interface UserService {void save();
}

 UserServiceImpl 实现类

@Slf4j
@Service("userService")
public class UserServiceImpl implements UserService {@Overridepublic void save() {log.info("添加用户.....");}
}
4、在 controller 包下新建 UserController 类,使用 @RequiredArgsConstructor 注解

@Controller
@RequiredArgsConstructor
public class UserController {private final UserService userService;public void addUser() {userService.save();}}

这是一个示例的Java类,使用了Spring框架中的注解来实现依赖注入和控制反转(IoC)。

在这个示例中,UserController是一个控制器类,使用了@Controller注解来标识它是一个控制器组件。@RequiredArgsConstructor注解是Lombok库提供的,用来自动生成构造函数并注入依赖。

UserController类有一个私有字段 userService,通过final关键字标记,并在构造函数中进行初始化。这里使用了构造函数注入,即通过构造函数将UserService的实例注入到UserController中,实现了依赖注入。

addUser方法中,调用了userService.save()方法。由于userService字段已经通过必要的构造函数注入,因此可以直接使用userService对象调用其中的方法。

整体而言,这段代码展示了基于Spring框架的控制器类定义和依赖注入的方式。通过使用相应的注解,可以方便地管理和注入依赖对象,实现松耦合的组件之间的协作。

lombook 迎合了 spring 4.2 的新特性实现了更加简洁的注入方式,使用 @RequiredArgsConstructor 注解,lombook 会自动添加一个带参的构造方法实现构造器的注入,注意;此时的字段必须是final 修饰

 5、在 resources 下新建一个 spring 的 xml 文件 application.xml
<?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:context="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"><!-- 启用包扫描 --><context:component-scan base-package="edu.nf.ch09"/></beans>
6、测试
public class Main {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");UserController bean = context.getBean(UserController.class);bean.addUser();}}

运行结果

 二、使用 @inject、@Named 注解

1、在 service 包下的 impl 包下在新建一个 StuServiceImpl 实现类
@Slf4j
@Service("stuService")
public class StuServiceImpl implements UserService {@Overridepublic void save() {log.info("添加学生......");}
}
2、使用 setter 方法注入

@Controller
public class UserController {private final UserService userService;/*** 当有多个实现类,并且方法参数与 id 不一致时,* 可以结合 @Named 注解来指定 bean 的 id 又或者* 可以使用 @Primary 注解设置注入的优先级** @param aa*/@Inject@Named("userService")public UserController(UserService aa) {this.userService = aa;}public void addUser() {userService.save();}}

上述代码是一个使用了@Inject@Named注解进行依赖注入的示例,涉及到多个实现类时可以使用@Named注解来指定要注入的实现类的bean的id。

@Inject是Java依赖注入规范中定义的注解,用于在运行时自动注入需要的实例。在使用@Inject注解时,可以结合使用@Named注解来指定要注入的实例的bean的id,这样Spring框架就可以根据指定的bean id来选择对应的实例进行注入。

在上面的示例中,UserController类被标记为@Controller组件,用于处理HTTP请求。UserService字段被声明为final,并在构造函数中通过@Inject@Named注解进行注入。使用@Named("userService")可以指定要注入的bean为id为"userServie"的bean。在addUser()方法中,直接调用userService.save()方法即可使用该对象提供的服务。

整体来说,使用注解进行依赖注入的好处是可以避免手动管理对象依赖关系,从而减少与依赖相关的代码量和复杂度,并且避免由于错误的依赖关系引起的运行时异常。

3、测试
public class Main {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");UserController bean = context.getBean(UserController.class);bean.addUser();}}

运行结果

那如果要调用 StudentServiceImpl 实现类的方法呢?很简单,只需要把 @Named 的值改为注入的bean为id为"stuService"的bean  即可。

 

三、使用 @RequiredArgsConstructor、@Inject、@Named 有什么好处

@RequiredArgsConstructor@Inject@Named这些注解在依赖注入中可以提供以下好处:

  1. @RequiredArgsConstructor注解:该注解是Lombok库提供的注解,用于自动生成构造函数,其中参数为被声明为final或者被标记为@NonNull的字段。使用该注解可以简化代码,省略手动编写构造函数的过程,从而提高开发效率。

  2. @Inject注解:该注解是Java依赖注入(JSR-330)规范中定义的注解,用于在运行时自动注入所需的实例。使用该注解可以避免手动处理对象的依赖关系,框架会自动将所需的实例注入到相应的位置。这样可以减少与依赖相关的代码量和复杂度,并且降低耦合度,使代码更加可维护和可测试。

  3. @Named注解:该注解也是Java依赖注入(JSR-330)规范中定义的注解,用于为bean指定唯一的名称或id。当存在多个实现类时,可以使用@Named注解来标识不同的实现类,然后在注入时根据指定的bean名称进行选择注入哪个实例。使用@Named注解可以更精确地控制依赖注入的目标对象,提高灵活性。

综上所述,使用@RequiredArgsConstructor可以简化构造函数的编写,提高代码效率;@Inject可以自动注入依赖,减少手动管理对象依赖关系的代码量和复杂度;@Named可以为bean指定唯一的名称或id,使得在存在多个实现类时更精确地控制注入目标。这些注解能够有效地提高代码的可读性、可维护性和可测试性,同时减少出错的可能性。

四、gitee 案例

案例完整地址:https://gitee.com/qiu-feng1/spring-framework.git

相关文章:

Spring framework Day10:JSR330注入注解

前言 JSR330是Java社区标准化进程&#xff08;Java Community Process&#xff0c;简称JCP&#xff09;中的一个规范&#xff0c;全名为"Dependency Injection for Java"&#xff0c;即Java的依赖注入规范。它定义了一组注解和相关的规范&#xff0c;用于实现依赖注…...

Java开发中List数据量大,需要分片批次处理

在开发过程中可能会遇到需要处理的List数据量过大&#xff0c;可以选择分批处理的方式对大量数据进行处理。 1、使用 apache 的工具包 <dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><v…...

Apache Doris 2.0.2 版本正式发布!

峰会官网已上线&#xff0c;最新议程请关注&#xff1a;doris-summit.org.cn 点击报名 亲爱的社区小伙伴们&#xff0c;Apache Doris 2.0.2 版本已于 2023 年 10 月 6 日正式发布&#xff0c;该版本对多个功能进行了更新优化&#xff0c;旨在更好地满足用户的需求。有 92 位贡献…...

transformers架构实现

目录 架构代码如下 模型打印如下 架构代码如下 import numpy as np from torch.autograd import Variable import copy from torch import softmax import math import torch import torch.nn.functional as F import torch.nn as nn # 构建Embedding类来实现文本嵌入层 class…...

C++类型推导

这里对C的类型推导方式进行一次全面的总结。 C中有三种类型推导的方式&#xff0c;分别是模板、auto以及decltype()。以下分别介绍这三种方式的同异。 一 模板 假设有这样的函数模板和这样的调用&#xff1a; template<typename T> void f(ParamType param);f(expr);…...

Open3D(C++) SVD分解求两个点云的变换矩阵

目录 一、算法原理二、代码实现三、结果展示四、相关链接一、算法原理 计算两个点云的质心计算中心化向量计算协方差矩阵奇异值分解,求解旋转矩阵 R R R计算平移向量 t t...

rtmp htttp推流Windows桌面到srs进行播放

推流命令: ffmpeg -f gdigrab -framerate 30 -i desktop -c:v libx264 -preset ultrafast -tune zerolatency -pix_fmt yuv420p -f flv rtmp://xxx.xxx.xxxx.xx/live/livestream 后面是推流地址 推流后的播放地址为: http://xxxxxx:8080/live/livestream.flv 可以写一个…...

NSSCTF做题(9)

[GDOUCTF 2023]<ez_ze> 看见输入框而且有提示说是ssti注入 输入{{7*7}} 试试&#xff0c;发现报错 输入{%%}发现了是jinja2模板 找到关键函数 Python SSTI利用jinja过滤器进行Bypass ph0ebuss Blog 原理见这篇文章&#xff0c;这里直接给出payload {%set ninedict(aaa…...

【09】基础知识:React组件的生命周期

组件从创建到死亡它会经历一些特定的阶段。 React 组件中包含一系列勾子函数&#xff08;生命周期回调函数 <> 生命周期钩子函数 <> 生命周期函数 <> 生命周期钩子&#xff09;&#xff0c;会在特定的时刻调用。 我们在定义组件时&#xff0c;会在特定的生…...

Pytorch之ConvNeXt图像分类

文章目录 前言一、ConvNeXt设计决策1.设计方案2.Training Techniques3.Macro Design&#x1f947;Changing stage compute ratio&#x1f948;Change stem to "Patchify" 4.ResNeXt-ify5. Inverted Bottleneck6.Large Kernel Size7.Micro Design✨Replacing ReLU wit…...

Linux系统编程:makefile以及文件系统编程

增量编译概念 首先回顾一下我们之前写的各种gcc指令用来执行程序&#xff1a; 可以看见非常繁琐&#xff0c;两个文件就要写这么多&#xff0c;那要是成百上千岂不完蛋。 所以为了简化工作量&#xff0c;很自然的想到了将这些命令放在一起使用脚本文件来一键执行&#xff0c…...

《动手学深度学习 Pytorch版》 8.5 循环神经网络的从零开始实现

%matplotlib inline import math import torch from torch import nn from torch.nn import functional as F from d2l import torch as d2lbatch_size, num_steps 32, 35 train_iter, vocab d2l.load_data_time_machine(batch_size, num_steps) # 仍然使用时间机器数据集8.…...

写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换

我们这里是利用按位与来计算的 我们可以想想怎么保留偶数上的位&#xff1f;我们可以利用0x55555555按位与上这个数就保留了偶数 我们知道&#xff0c;16进制0x55555555转换为二进制就是0x01010101010101010101010101010101 我们知道&#xff0c;二进制每一位&#xff0c;如…...

Zabbix监控系统详解2:基于Proxy分布式实现Web应用监控及Zabbix 高可用集群的搭建

文章目录 1. zabbix-proxy的分布式监控的概述1.1 分布式监控的主要作用1.2 监控数据流向1.3 构成组件1.3.1 zabbix-server1.3.2 Database1.3.3 zabbix-proxy1.3.4 zabbix-agent1.3.5 web 界面 2. 部署zabbix代理服务器2.1 前置准备2.2 配置 zabbix 的下载源&#xff0c;安装 za…...

docker 安装oracle

拉取镜像 拉取oracle_11g镜像 拉取oracle镜像(oracle 11.0.2 64bit 企业版 实例名: helowin) Oracle主要在Docker基础上安装&#xff0c;安装环境注意空间和内存&#xff0c;Oracle是一个非常庞大的一个软件&#xff0c; 建议使用网易镜像或阿里镜像网站这里以oracle 11.0.2…...

C++ vector 自定义排序规则(vector<vector<int>>、vector<pair<int,int>>)

vector< int > vector<int> vec{1,2,3,4};//默认从小到大排序 1234 sort(vec.begin(),vec.end()); //从大到小排序 4321 sort(vec.begin(),vec.end(),greater<int>());二维向量vector<vector< int >> vector<vector<int>> vec{{0…...

机器学习 Q-Learning

对马尔可夫奖励的理解 看的这个教程 公式&#xff1a;V(s) R(s) γ * V(s’) V(s) 代表当前状态 s 的价值。 R(s) 代表从状态 s 到下一个状态 s’ 执行某个动作后所获得的即时奖励。 γ 是折扣因子&#xff0c;它表示未来奖励的重要性&#xff0c;通常取值在 0 到 1 之间。…...

产品设计心得体会 优漫动游

产品设计需要综合考虑用户需求、市场需求和技术可行性&#xff0c;从而设计出能够满足用户需求并具有市场竞争力的产品。以下是我在产品设计方面的心得体会&#xff1a; 产品设计心得体会 1.深入了解用户需求&#xff1a;在产品设计之前&#xff0c;需要进行充分的用户调研…...

前端--CSS

文章目录 CSS的介绍 引入方式 代码风格 选择器 复合选择器 (选学) 常用元素属性 背景属性 圆角矩形 Chrome 调试工具 -- 查看 CSS 属性 元素的显示模式 盒模型 弹性布局 一、CSS的介绍 层叠样式表 (Cascading Style Sheets). CSS 能够对网页中元素位置的排版进行像素级精…...

实操指南|如何用 OpenTiny Vue 组件库从 Vue 2 升级到 Vue 3

前言 根据 Vue 官网文档的说明&#xff0c;Vue2 的终止支持时间是 2023 年 12 月 31 日&#xff0c;这意味着从明年开始&#xff1a; Vue2 将不再更新和升级新版本&#xff0c;不再增加新特性&#xff0c;不再修复缺陷 虽然 Vue3 正式版本已经发布快3年了&#xff0c;但据我了…...

系统架构设计:15 论软件架构的生命周期

目录 一 软件架构的生命周期 1 需求分析阶段 2 设计阶段 3 实现阶段 4 构件组装阶段...

金山wps golang面试题总结

简单自我介绍如果多个协程并发写map 会导致什么问题如何解决&#xff08;sync.map&#xff0c;互斥锁&#xff0c;信号量&#xff09;chan 什么时候会发生阻塞如果 chan 缓冲区满了是阻塞还是丢弃还是panicchan 什么时候会 panic描述一下 goroutine 的调度机制goroutine 什么时…...

计算机视觉实战--直方图均衡化和自适应直方图均衡化

计算机视觉 文章目录 计算机视觉前言一、直方图均衡化1.得到灰度图2. 直方图统计3. 绘制直方图4. 直方图均衡化 二、自适应直方图均衡化1.自适应直方图均衡化&#xff08;AHE&#xff09;2.限制对比度自适应直方图均衡化&#xff08;CRHE&#xff09;3.读取图片4.自适应直方图均…...

501. 二叉搜索树中的众数

501. 二叉搜索树中的众数 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution:def findMode(self, root: Option…...

【Linux】常用命令

目录 文件解压缩服务器文件互传scprsync 进程资源网络curl发送简单get请求发送 POST 请求发送 JSON 数据保存响应到文件 文件 ls,打印当前目录下所有文件和目录; ls -l,打印每个文件的基本信息 pwd,查看当前目录的路径 查看文件 catless&#xff1a;可以左右滚动阅读more :翻…...

机器人制作开源方案 | 齿轮传动轴偏心轮摇杆简易四足

1. 功能描述 齿轮传动轴偏心轮摇杆简易四足机器人是一种基于齿轮传动和偏心轮摇杆原理的简易四足机器人。它的设计原理通常如下&#xff1a; ① 齿轮传动&#xff1a;通过不同大小的齿轮传动&#xff0c;实现机器人四条腿的运动。通常采用轮式齿轮传动或者行星齿轮传动&#xf…...

Windows中将tomcat以服务的形式安装,然后在服务进行启动管理

Windows中将tomcat以服务的形式安装,然后在服务进行启动管理 第一步&#xff1a; 在已经安装好的tomcat的bin目录下&#xff1a; 输入cmd&#xff0c;进入命令窗口 安装服务&#xff1a; 输入如下命令&#xff0c;最后是你的服务名&#xff0c;避免中文和特殊字符 service.…...

解决ERROR: No query specified的错误以及\G 和 \g 的区别

文章目录 1. 复现错误2. 分析错误3. 解决问题4. \G和\g的区别 1. 复现错误 今天使用powershell连接数据库后&#xff0c;执行如下SQL语句&#xff1a; mysql> select * from student where id 39 \G;虽然成功查询除了数据&#xff0c;但报出如下错误的信息&#xff1a; my…...

mysql中SUBSTRING_INDEX函数用法详解

MySQL中的SUBSTRING_INDEX函数用于从字符串中提取子字符串&#xff0c;其用法如下&#xff1a; SUBSTRING_INDEX(str, delim, count)参数说明&#xff1a; str&#xff1a;要提取子字符串的原始字符串。delim&#xff1a;分隔符&#xff0c;用于确定子字符串的位置。count&am…...

AndroidStudio报错:android.support.v4.app.Fragment

解决办法一 android.support.v4.app.Fragment替换为android.app.Fragment 解决办法二 有时太多&#xff0c;先类型过去再说。 找到gradle.properties&#xff0c;修改&#xff1a; android.useAndroidXfalse android.enableJetifierfalse...