首页/新闻资讯/正文详情

Spring DI 详解

发布时间:2026/9/27 7:38:36 来源:云帆数科 栏目:资讯中心
Spring DI 详解
学习过 IoC 后就知道我们可以将对象交给 Spring 进行管理但是我们在一个类会有若干属性也就是这个类依赖于这若干个属性那么我们就可以将交给 Spring 管理的对象注入到这个类中这也就是依赖注入。依赖注入有三种方式分别为属性注入、构造方法注入、setter方法注入。下面一一介绍。一、属性注入Autowired有如下代码Controller public class TestController { //属性注入 Autowired private TestService service; public void print() { System.out.println(controller); service.print(); } } Service public class TestService { public void print() { System.out.println(service); } } //SpringBoot 启动类 SpringBootApplication public class SpringBootDemo2025417Application { public static void main(String[] args) { ApplicationContext context SpringApplication.run(SpringBootDemo2025417Application.class, args); //获取 TestController 对象 TestController controller context.getBean(TestController.class); controller.print(); } }在 TestController 类中有属性 service我们通过 Autowired 注解将 TestService 输入到属性 service 中这样我们就可以使用 TestService 中的相关方法了代码运行结果如下代码先执行了 TestController 的print 方法然后又执行了 TestService 的 print 方法。现有下面两种情况一种没加 Service另一种是没加 Autowired下面我们来分别看看这两种情况。没加 Service运行代码后发现报错了错误代码如下Description: Field service in com.gjm.demo.controller.TestController required a bean of type com.gjm.demo.service.TestService that could not be found.由于我们没有加 Service就代表我们没有将 TestService 类交给 Spring 进行管理那么我们在使用 Autowired 在 Spring 容器中获取对象时就找不到这个对象就会报这个错。没加 Autowired运行代码后发现报错了错误代码如下controller Exception in thread main java.lang.NullPointerException: Cannot invoke com.gjm.demo.service.TestService.print() because this.service is null at com.gjm.demo.controller.TestController.print(TestController.java:16) at com.gjm.demo.SpringBootDemo2025417Application.main(SpringBootDemo2025417Application.java:19)我们发现了这里报了一个空指针异常这时为什么呢原因是虽然我们加了 Service 注解将 TestService 交给 Spring 进行管理但是由于我们没有加 Autowired 注解就使得我们并没有将 TestService 的对象注入给 service也即是并没有初始化 service当我们在吊桶TestService 的 print 方法时就会报空指针异常。这也就是 “controller” 可以显示出来但 “service” 显示不出来的原因。二、构造方法注入顾名思义就是将属性放到构造方法中在进行注入代码如下Controller public class TestController { private TestService service; //构造方法 public TestController(TestService service) { this.service service; } public void print() { System.out.println(controller); service.print(); } } Service public class TestService { public void print() { System.out.println(service); } } SpringBootApplication public class SpringBootDemo2025417Application { public static void main(String[] args) { ApplicationContext context SpringApplication.run(SpringBootDemo2025417Application.class, args); //获取 TestController 对象 TestController controller context.getBean(TestController.class); controller.print(); } }代码运行结果如下在上面的构造方法中没有加任何注解就将 TestService 注入给了 TestController。但在日常开发中加上了有参的构造函数无参的构造函数就默认没有了为了避免出现问题我们还会将无参的构造函数也加上代码如下Controller public class TestController { private TestService service; //无参构造函数 public TestController() { } //有参构造函数 public TestController(TestService service) { this.service service; } public void print() { System.out.println(controller); service.print(); } }代码运行结果如下controller Exception in thread main java.lang.NullPointerException: Cannot invoke com.gjm.demo.service.TestService.print() because this.service is null at com.gjm.demo.controller.TestController.print(TestController.java:27) at com.gjm.demo.SpringBootDemo2025417Application.main(SpringBootDemo2025417Application.java:19)又报错了 是空指针异常。这是因为我们加上了无参的构造函数在进行构造方法注入的时候默认的构造方法为无参的构造方法若没有无参的给构造方法就会使用我们自己写的构造方法。这里我们把无参的构造方法加上了就会使用无参的构造方法这时就不会给 service 进行注入也就是 service 没有进行初始化在调用 print 方法时就会出现空指针异常。上面时只有一个属性的情况那如果 testController 中有多个属性呢下面我们介绍有两个属性的情况。代码如下package com.gjm.demo.controller; import com.gjm.demo.service.TestService1; import com.gjm.demo.service.TestService2; import org.springframework.stereotype.Controller; Controller public class TestController { private TestService1 service1; private TestService2 service2; public TestController() { } public TestController(TestService1 service1) { this.service1 service1; } public TestController(TestService2 service2) { this.service2 service2; } public TestController(TestService1 service1, TestService2 service2) { this.service1 service1; this.service2 service2; } public void print() { System.out.println(controller); service1.print(); service2.print(); } } Service public class TestService1 { public void print() { System.out.println(service1); } } Service public class TestService2 { public void print() { System.out.println(service2); } } SpringBootApplication public class SpringBootDemo2025417Application { public static void main(String[] args) { ApplicationContext context SpringApplication.run(SpringBootDemo2025417Application.class, args); //获取 TestController 对象 TestController controller context.getBean(TestController.class); controller.print(); } }在 TestController 中有两个属性分别为 TestService1 和 TestService2代码运行结果如下controller Exception in thread main java.lang.NullPointerException: Cannot invoke com.gjm.demo.service.TestService1.print() because this.service1 is null at com.gjm.demo.controller.TestController.print(TestController.java:49) at com.gjm.demo.SpringBootDemo2025417Application.main(SpringBootDemo2025417Application.java:17)发现这个报错信息与前一个报错信息是一样的也是空指针异常。这是因为无论有几个属性构造方法注入的默认构造方法都是无参构造方法就相当于 service1 和 service2 书香都没有初始化在调用 print 方法就会报空指针异常。那如果将无参的构造方法去掉呢代码如下package com.gjm.demo.controller; import com.gjm.demo.service.TestService1; import com.gjm.demo.service.TestService2; import org.springframework.stereotype.Controller; Controller public class TestController { private TestService1 service1; private TestService2 service2; public TestController(TestService1 service1) { this.service1 service1; } public TestController(TestService2 service2) { this.service2 service2; } public TestController(TestService1 service1, TestService2 service2) { this.service1 service1; this.service2 service2; } public void print() { System.out.println(controller); service1.print(); service2.print(); } }代码运行结果如下controller Exception in thread main java.lang.NullPointerException: Cannot invoke com.gjm.demo.service.TestService1.print() because this.service1 is null at com.gjm.demo.controller.TestController.print(TestController.java:49) at com.gjm.demo.SpringBootDemo2025417Application.main(SpringBootDemo2025417Application.java:17)同样的也是空指针异常那应该怎么办呢在构造方法注入中也可以使用 Autowired 注解当在构造方法上使用该注解时表示的含义就是修改默认的构造函数于是可以在全参的构造函数上加上 Autowired 注解代码如下package com.gjm.demo.controller; import com.gjm.demo.service.TestService1; import com.gjm.demo.service.TestService2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; Controller public class TestController { private TestService1 service1; private TestService2 service2; public TestController() { } public TestController(TestService1 service1) { this.service1 service1; } public TestController(TestService2 service2) { this.service2 service2; } Autowired public TestController(TestService1 service1, TestService2 service2) { this.service1 service1; this.service2 service2; } public void print() { System.out.println(controller); service1.print(); service2.print(); } }运行结果如下这次就运行成功了。三、setter 方法注入setter 方法注入即使用 setter方法进行属性注入在使用时需要在对应的 setter 方法上加上 Autowired 注解如果不加就会报错。代码如下package com.gjm.demo.controller; import com.gjm.demo.service.TestService1; import com.gjm.demo.service.TestService2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; Controller public class TestController { private TestService1 service1; private TestService2 service2; Autowired public void setService1(TestService1 service1) { this.service1 service1; } Autowired public void setService2(TestService2 service2) { this.service2 service2; } public void print() { System.out.println(controller); service1.print(); service2.print(); } } Service public class TestService1 { public void print() { System.out.println(service1); } } Service public class TestService2 { public void print() { System.out.println(service2); } } SpringBootApplication public class SpringBootDemo2025417Application { public static void main(String[] args) { ApplicationContext context SpringApplication.run(SpringBootDemo2025417Application.class, args); //获取 TestController 对象 TestController controller context.getBean(TestController.class); controller.print(); } }运行结果如下

相关推荐

自定义一个简单的MCP Server:使用SpringAI + Cline + DeepSeek实现AI创建文件并写入内容
自定义一个简单的MCP Server:使用SpringAI + Cline + DeepSeek实现AI创建文件并写入内容

实现功能 通过与AI的对话,让AI自动完成将指定内容写入指定目标文件的功能,效果如下:环境 windows 11、jdk 17、SpringBoot 3.4.4 步骤 1、安装vscode并安装Cline插件2、在Cline插件中配置大模型 Cline可以配置多种大模型,比如本地… · 2026/9/27 7:38:36

Longhorn v1.9.2 版本解析:补丁版中的系统韧性、稳定性与安全增强
Longhorn v1.9.2 版本解析:补丁版中的系统韧性、稳定性与安全增强

云原生存储高可用容器编排 【免费下载链接】longhorn Cloud-Native distributed storage built on and for Kubernetes 项目地址: https://gitcode.com/gh_mirrors/lo/longhorn 点击查看 免费下载 导读:本文基于 Longhorn 开源仓库 CHANGELOG/CHANGELOG… · 2026/9/27 7:38:30

Metrics JVM Instrumentation 实战指南:基于 Dropwizard Metrics 采集 GC、内存、线程与文件描述符指标
Metrics JVM Instrumentation 实战指南:基于 Dropwizard Metrics 采集 GC、内存、线程与文件描述符指标

可观测性后端 【免费下载链接】metrics :chart_with_upwards_trend: Capturing JVM- and application-level metrics. So you know whats going on. 项目地址: https://gitcode.com/gh_mirrors/met/metrics 点击查看 免费下载 metrics-jvm 是 Dropwizard Metrics&a… · 2026/9/27 7:38:30

网站被黑挂马怎么救?一文搞懂有什么好用的模拟建站软件
网站被黑挂马怎么救?一文搞懂有什么好用的模拟建站软件

网站被黑挂马怎么救?一文搞懂有什么好用的模拟建站软件 上周半夜两点,我盯着后台报警日志,手心全是汗。服务器突然弹出大量恶意跳转链接,首页被替换成了赌博广告,更糟的是数据库里的用户数据疑似被拖走。那一刻,那种“网站被黑挂马不知道怎么办”的无力… · 2026/9/27 8:21:31

WordPress免邮箱验证建站多少钱新手避坑指南
WordPress免邮箱验证建站多少钱新手避坑指南

WordPress免邮箱验证建站多少钱新手避坑指南 自己不会代码想做网站,是不是经常被各种“专业术语”劝退?别慌,今天咱们就聊聊 wordpress免邮箱验证… · 2026/9/27 8:21:31

Penrose Path 形状详解:用 `d` 属性绘制 SVG 折线、弧线与插值曲线
Penrose Path 形状详解:用 `d` 属性绘制 SVG 折线、弧线与插值曲线

开发工具数据可视化 【免费下载链接】penrose Create beautiful diagrams just by typing notation in plain text. 项目地址: https://gitcode.com/gh_mirrors/pe/penrose 点击查看 免费下载 Path 是 Penrose 样式程序(Style)中最灵活的基础… · 2026/9/27 8:21:18

Matplotlib Cheatsheets 文档体系全解析:双页速查表、三阶讲义与仓库构建流程
Matplotlib Cheatsheets 文档体系全解析:双页速查表、三阶讲义与仓库构建流程

【免费下载链接】cheatsheets Official Matplotlib cheat sheets 项目地址: https://gitcode.com/gh_mirrors/che/cheatsheets 点击查看 免费下载 Matplotlib Cheatsheets 是 Matplotlib 官方维护的速查资源仓库,docs/index.rst 是 Sphinx 文档站点的首… · 2026/9/27 8:21:18

Terratest 使用 Docker 进行本地迭代测试:把基础设施代码的“单元测试“跑在容器里
Terratest 使用 Docker 进行本地迭代测试:把基础设施代码的“单元测试“跑在容器里

测试开发工具DevOps质量保障 【免费下载链接】terratest Terratest is a Go library that makes it easier to write automated tests for your infrastructure code. 项目地址: https://gitcode.com/gh_mirrors/te/terratest 点击查看 免费下载 Terratest 官方最佳… · 2026/9/27 8:21:12

普陀区网站开发避坑:3招搞定源码下载与低价陷阱
普陀区网站开发避坑:3招搞定源码下载与低价陷阱

普陀区网站开发避坑:3招搞定源码下载与低价陷阱 在普陀区找建站公司,最让人头疼的不是技术难,而是怕被坑高价。很多老板拿着几千块的预算,最后被忽悠花了几万,还发现拿不到核心代码。其实,只要搞懂 源码下载 的逻辑,你就掌握了谈判的主动权。… · 2026/9/27 8:21:06

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码