Spring IOCDI————(2)

news2025/5/22 21:45:35

DI详解

我们之前讲了控制反转IOC,也就是bean的存,那么我们还需要Bean的取,就是DI了,DI翻译过来就是依赖注入,啥意思呢,就是我们通过IOC容器,把所有的对象交给Spring管理,我们指定哪个对象使用哪个类,就给他注入哪个类,这个类就能直接使用我们给他注入的类;

1,属性注入

第一种方法,使用@Autowired注解;

先创建一个功能类,交给Spring进行管理,


@Service
public class UserService {
    public void sayHello(){
        System.out.println("Hello,sayHello");
    }
}

再创建控制器,也交给Spring管理,把UserService注入到UserController中, 

@Controller
public class UserController {
    @Autowired
    public UserService userService;

    public void SayHello(){
        System.out.println("Hello,UserController");
        userService.sayHello();
    }
}

 获取上下文对象,通过上下文获取UserController对象,我们直接调用UserController的SayHello方法,看看效果;

@SpringBootApplication
public class JavaTest2025521Application {

    public static void main(String[] args) {

        ApplicationContext context = SpringApplication.run(JavaTest2025521Application.class, args);
        UserController userController = context.getBean("userController", UserController.class);
        userController.SayHello();
    }
}

证明,UserService对象被Spring自动创建出来了;


2,构造方法注入

@Controller
public class UserController2 {
    private UserService userService;

    @Autowired
    public UserController2(UserService userService){
        this.userService = userService;
    }

    public void SayHello(){
        System.out.println("Hello,Controller2");
        userService.sayHello();
    }
}

我们直接在构造方法上写上注解@Autoweired,就可以了,

        UserController2 userController2 = context.getBean("userController2", UserController2.class);
        userController2.SayHello();

也是可以的,那么如果有两个构造方法呢?

    @Autowired
    public UserController2(UserService userService){
        this.userService = userService;
    }
    
    @Autowired
    public UserController2(){}

 这段代码直接标红红嗷,我们想使用哪个构造方法,就得在哪个构造方法上标记@Autowired注解,

@Controller
public class UserController2 {
    private UserService userService;

    @Autowired
    public UserController2(UserService userService){
        this.userService = userService;
    }
    
    public UserController2(){}

    public void SayHello(){
        System.out.println("Hello,Controller2");
        userService.sayHello();
    }
}

这样还是可以正常传参的,

那么如果有参数呢,Spring会找这个类型的Bean来给他赋值,比如参数需要String,它就会去找Bean下的类型Sting给他赋值,我们看我们这个代码:
 


@Controller
public class UserController3 {
    private UserService userService;

    @Autowired
    public UserController3(UserService userService){
        this.userService = userService;
    }


    public void SayHello(){
        System.out.println("Hello,Controller3");
        userService.sayHello();
        System.out.println(userService.getName());
    }
}

现在有三个Spring管理的UserService对象,

@Configuration
public class UserSer {
    @Bean
    public UserService name1(){
        UserService userService = new UserService();
        userService.setName("zhangsan");
        return userService;
    }

    @Bean
    public UserService name2(){
        UserService userService1 = new UserService();
        userService1.setName("lisi");
        return userService1;
    }
}

@Service
@Data
public class UserService {
    private String name;
    public void sayHello(){
        System.out.println("Hello,sayHello");
    }
}

 那我们前面这个构造方法使用的是哪个对象呢,

        UserController3 userController3 = context.getBean("userController3", UserController3.class);
        userController3.SayHello();

我们这样直接指定的会就是通过Service注解生成的默认的, 

打印为null啊,我们试试修改getBean的名称

        UserController3 userController4 = context.getBean("name1", UserController3.class);
        userController4.SayHello();

 得到了,这就是我们之前讲Bean时使用的方法,我们说过还有别的办法就是@Qualifier注解,

@Controller
public class UserController3 {
    private UserService userService;

    @Autowired
    public UserController3(@Qualifier("name2") UserService userService){
        this.userService = userService;
    }


    public void SayHello(){
        System.out.println("Hello,Controller3");
        userService.sayHello();
        System.out.println(userService.getName());
    }
}

类似参数绑定,用@Qualifier指定name2注解,这样getbean都不用指定String名字了;

        UserController3 userController5 = context.getBean(UserController3.class);
        userController5.SayHello();
        System.out.println();

另外啊,这只是获取UserController对象,如果获取的是UserService那么就又不对了,我们直接有三个类型,UserService,name1,name2,这可不是根据构造方法了,Spring想直接得到,那么我们需要加@primary注解才行,


3,Setter注入

这个跟属性的那个Set基本是一样的,

@Controller
public class UserController4 {
    private UserService userService;

    @Autowired
    public void Set(UserService userService){
        this.userService = userService;
    }

    public void SayHello(){
        System.out.println("Hello,Controller4");
        userService.sayHello();
    }

}
        UserController4 userController6 = context.getBean(UserController4.class);
        userController6.SayHello();

 setter方法还是很简单的,没有什么特别要说的;

(5-21忘了就过一遍代码)


4,三种注入优缺点分析

 

 


5,@Autowired存在问题

当同一个类型出现多个Bean就会出现问题,来上代码:
先来一个User类:
 

@Repository
@Data
public class User {
    private String name;
    private Integer age;
}

这里就自己创建了一个类,这个@Repository可以不加 

交给Spring管理,再来lombok,

@Configuration
public class UserConfig {
    @Bean
    public User get1(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }

    @Bean
    public User get2(){
        User user = new User();
        user.setName("lisi");
        user.setAge(20);
        return user;
    }
}

在来一个类里面可以得到User类,并且有两个方法可以得到,两个Bean,


@Controller
public class UserControl {
    @Autowired
    private User user;

    public void sayHello(User user){
        System.out.println(user.getAge()+"    "+user.getName());
    }
}

来控制器类,现在我不说了,现在有几个重复的Bean呢,


        User user = context.getBean(User.class);
        System.out.println(user);

运行试试:

有三个 ,我们怎么解决这个问题呢,我们有三种办法

1,@Primary

使用该注解直接标注到Bean上面:

    @Primary
    @Bean
    public User get1(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
        User user = context.getBean(User.class);
        System.out.println(user);

 

    @Primary
    @Bean
    public User get2(){
        User user = new User();
        user.setName("lisi");
        user.setAge(20);
        return user;
    }

 

2,@Qualifier

必须搭配合@Autowired使用,指定要注入的对象是哪个:

这里指的是指定注入哪个,然后在被注入的对象中用被注入的对象,而刚才那个@primary,是直接指定这个类型就用这个被指定的了

我们来看代码:


@Configuration
public class UserConfig2 {

    @Bean
    public User get1(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }

    @Bean
    public User get2(){
        User user = new User();
        user.setName("lisi");
        user.setAge(20);
        return user;
    }
}
@Controller
public class UserControl2 {

    @Qualifier("get1")
    @Autowired
    private User user;

    public void sayHello(){
        System.out.println(user.getAge()+"    "+user.getName());
    }
}
        UserControl2 userControl2 = context.getBean(UserControl2.class);
        userControl2.sayHello();
        System.out.println();

 

来个总结嗷,怕大家混了:

我们刚开始创建一个对象,比如刚才的User我们交给Spring就代表了有一个User类了,Spring已经自己创建一个了;

1,属性注入就是我们在写一个A类的时候如果想用User类,就直接使用 @Autowired注解,我们在获取上下文对象的时候可以获取A类,调用A类的方法,如果有User相关的,就能调用到;但是如果接收的是User对象的话就不行了,即使A类注入了,如果成功了的话就是因为User交给Spring管理了,就是

@Repository
@Data
public class User {
    private String name;
    private Integer age;
}

如果属性注入同一类型出现了多个Bean呢,我们就可以使用@Primary来标记Bean,表示这写类型的Bean就使用标记的这个就行,可以直接获取到,或者包含它的类获取到,

@Configuration
public class UserConfig {

    @Bean
    public User get1(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
    @Primary
    @Bean
    public User get2(){
        User user = new User();
        user.setName("lisi");
        user.setAge(20);
        return user;
    }
}
;
@Controller
public class UserControl {

    @Autowired
    private User user;

    public void sayHello(){
        System.out.println(user.getAge()+"    "+user.getName());
    }
}
User user = context.getBean(User.class);
System.out.println(user);
UserControl userControl = context.getBean(UserControl.class);
userControl.sayHello();

这个就可以用User接收,也可以使用注入过的User的类来调用,都是可以的,

还有就是刚才的@Autowired,是指定被注入的类,去使用Spring中的哪个User类的,

@Qualifier("get1")
@Autowired
private User user;

直接接收User类是做不到的,只能让被注入的那个类调用;

还有就是构造方法注入要注意,有多个构造方法要用@Autowired来制定,参数有多个类型也要使用@Qualifier()来绑定;

3,@Resource

按照Bean的名称注入@Resource(name = "user2")通过那么来指定要注入的;

@Configuration
public class UserConfig3 {

    @Bean
    public User get1(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }

    @Bean
    public User get2(){
        User user = new User();
        user.setName("lisi");
        user.setAge(20);
        return user;
    }
}
@Controller
public class UserControl3 {

    @Resource(name = "get1")
    @Autowired
    private User user;

    public void sayHello(){
        System.out.println(user.getAge()+"    "+user.getName());
    }
}
        User user = context.getBean(User.class);
        System.out.println(user);

 直接获取还是不行的,

 

        UserControl3 userControl3 = context.getBean(UserControl3.class);
        userControl3.sayHello();

 


@Autowired和Resource的区别

1,@Autowired是spring框架提供的注解,⽽@Resource是JDK提供的注解

2,@Autowired默认是按照类型注⼊,⽽@Resource是按照名称注⼊.相⽐于@Autowired 来说, @Resource ⽀持更多的参数设置,例如name设置,根据名称获取Bean

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

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

相关文章

融云 uni-app IMKit 上线,1 天集成,多端畅行

融云 uni-app IMKit 正式上线,支持一套代码同时运行在 iOS、Android、H5、小程序主流四端,集成仅需 1 天,并可确保多平台的一致性体验。 融云 uni-app IMKit 在 Vue 3 的高性能加持下开发实现,使用 Vue 3 Composition API&#x…

篇章五 项目创建

目录 1.创建一个SpringBoot项目 2.创建核心类 2.1 Exchange类 2.2 MessageQueue类 2.3 Binding类 2.4 Message类 1.Message的组成 2.逻辑删除 3.工厂方法 4.序列化与反序列化 5.offsetBeg和offsetEnd 1.创建一个SpringBoot项目 1.点击 2.填写表单 3.添加依赖 2.创建…

aws平台s3存储桶夸域问题处理

当我们收到开发反馈s3存在跨域问题 解决步骤: 配置 S3 存储桶的 CORS 设置: 登录到 AWS 管理控制台。转到 S3 服务。选择你存储文件的 存储桶。点击 权限 标签页。在 跨域资源共享(CORS)配置 部分,点击 编辑。 登陆…

【vue-text-highlight】在vue2的使用教程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、下载二、使用步骤1.引入库2.用法 效果速通 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发…

pycharm无法正常调试问题

pycharm无法正常调试问题 1.错误代码 已连接到 pydev 调试器(内部版本号 231.8109.197)Traceback (most recent call last):File "E:\Python\pycharm\PyCharm 2023.1\plugins\python\helpers\pydev\_pydevd_bundle\pydevd_comm.py", line 304, in _on_runr r.deco…

Leetcode百题斩-哈希

看来面试前还是要老老实实刷leetcode为好,今天看到一个题库,leetcode百题斩,刚好最近面试的这两题全在里面。瞄了一眼,也有不少题之前居然也刷过。那么,冲冲冲,看多久能把这百题刷完。 第一天,先…

EXIST与JOIN连表比较

结论 1:EXIST可以用于链表,且可以利用到索引2:当join无法合理利用到索引,可以尝试EXIST链表3:EXIST在某些情况下可以更好地利用到索引4:大数据量时,要考虑EXIST的使用 EXIST SQL: EXPLAN JOIN…

【Linux】利用多路转接epoll机制、ET模式,基于Reactor设计模式实现

📚 博主的专栏 🐧 Linux | 🖥️ C | 📊 数据结构 | 💡C 算法 | 🅒 C 语言 | 🌐 计算机网络 上篇文章:多路转接epoll,实现echoserver 至此,Linux与…

react中运行 npm run dev 报错,提示vite.config.js出现错误 @esbuild/win32-x64

在React项目中运行npm run dev时,如果遇到vite.config.js报错,提示esbuild/win32-x64在另一个平台中被使用,通常是由于依赖冲突或缓存问题导致的。解决方法是删除node_modules文件夹,并重新安装依赖。 如下图: 解决办…

鸿蒙UI开发——Builder与LocalBuilder对比

1、概 述 在ArkUI中,有的朋友应该接触过Builder和LocalBuilder。其中有了LocalBuilder的存在,是为了解决组件的父子关系和状态管理的父子关系保持一致的问题。 这里面最直观的表现则是this的指向问题与组件刷新问题,本文对Builder与LocalBu…

关于光谱相机的灵敏度

一、‌灵敏度的核心定义‌ ‌光谱灵敏度(单色灵敏度)‌ 描述光谱相机对单色辐射光的响应能力,即探测器对特定波长入射光的输出信号强度与入射光功率的比值。 例如,若在680nm波长下的光谱灵敏度较高,则表示该相机对此…

Model 速通系列(一)nanoGPT

这个是新开的一个系列用来手把手复现一些模型工程,之所以开这个系列是因为有人留言说看到一个工程不知道从哪里读起,出于对自身能力的提升与兴趣,故新开了这个系列。由于主要动机是顺一遍代码并提供注释。 该系列第一篇博客是 nanoGPT &…

MySQL--day4--排序与分页

(以下内容全部来自上述课程) 1. 排序数据 1.1 排序基本使用 #1.排序 #如果没有使用排序操作,默认情况下查询返回的数据是按照添加数据的顺序显示的 SELECT * FROM employees;# 练习:按照salary从高到低的顺序显示员工信息 # 使用 ORDER …

系分论文《论软件系统安全分析和应用》

系统分析师论文范文系列 【摘要】 2023年3月,我司承接了某知名电商企业“智能化供应链管理系统”的开发任务,我作为系统分析师负责全面的安全分析与设计工作。该系统以提升电商供应链效率为核心,整合仓储、物流、支付等模块,并需应…

Mac安装redis

1、 去往网址 http://​编download.​编redis.io/releases/ 找到任意 结尾为* .tar.gz的文件下载下来 2、使用终端进入下载下来的redis文件 3、直接执行redis-server 如果出现redis标志性的图代表成功 如果显示command not found :redis-server 则在终端再进入src文件夹下&…

srs-7.0 支持obs推webrtc流

demo演示 官方教程: https://ossrs.net/lts/zh-cn/blog/Experience-Ultra-Low-Latency-Live-Streaming-with-OBS-WHIP 实现原理就是通过WHIP协议来传输 SDP信息 1、运行 ./objs/srs -c conf/rtc.conf 2、obs推流 3、web端播放webrtc流 打开web:ht

Babylon.js学习之路《七、用户交互:鼠标点击、拖拽与射线检测》

文章目录 1. 引言:用户交互的核心作用1.1 材质与纹理的核心作用 2. 基础交互:鼠标与触摸事件2.1 绑定鼠标点击事件2.2 触摸事件适配 3. 射线检测(Ray Casting)3.1 射线检测的原理3.2 高级射线检测技巧 4. 拖拽物体的实现4.1 拖拽基…

星际争霸小程序:用Java实现策略模式的星际大战

在游戏开发的世界里,策略模式是一种非常实用的设计模式,它允许我们在运行时动态地选择算法或行为。今天,我将带你走进一场星际争霸的奇幻之旅,用Java实现一个简单的星际争霸小程序,通过策略模式来模拟不同种族单位的战…

Python数据可视化高级实战之一——绘制GE矩阵图

目录 一、课程概述 二、GE矩阵? 三、GE 矩阵图的适用范围 五、GE 矩阵的评估方法 (一)市场吸引力的评估要素 二、企业竞争实力的评估要素 三、评估方法与实践应用 1. 定量与定性结合法 2. 数据来源 六、GE矩阵的图形化实现 七、总结:GE 矩阵与 BCG 矩阵的对比分析 (一)GE…

StreamSaver实现大文件下载解决方案

StreamSaver实现大文件下载解决方案 web端 安装 StreamSaver.js npm install streamsaver # 或 yarn add streamsaver在 Vue 组件中导入 import streamSaver from "streamsaver"; // 确保导入名称正确完整代码修正 <!--* projectName: * desc: * author: dua…