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

Spring IOCDI————(2)

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 {@Autowiredpublic 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;@Autowiredpublic 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();

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

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

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

@Controller
public class UserController2 {private UserService userService;@Autowiredpublic 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;@Autowiredpublic 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 {@Beanpublic UserService name1(){UserService userService = new UserService();userService.setName("zhangsan");return userService;}@Beanpublic 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;@Autowiredpublic 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;@Autowiredpublic 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 {@Beanpublic User get1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User get2(){User user = new User();user.setName("lisi");user.setAge(20);return user;}
}

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


@Controller
public class UserControl {@Autowiredprivate 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@Beanpublic 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@Beanpublic User get2(){User user = new User();user.setName("lisi");user.setAge(20);return user;}

 

2,@Qualifier

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

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

我们来看代码:


@Configuration
public class UserConfig2 {@Beanpublic User get1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User get2(){User user = new User();user.setName("lisi");user.setAge(20);return user;}
}
@Controller
public class UserControl2 {@Qualifier("get1")@Autowiredprivate 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 {@Beanpublic User get1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Primary@Beanpublic User get2(){User user = new User();user.setName("lisi");user.setAge(20);return user;}
}
;
@Controller
public class UserControl {@Autowiredprivate 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 {@Beanpublic User get1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User get2(){User user = new User();user.setName("lisi");user.setAge(20);return user;}
}
@Controller
public class UserControl3 {@Resource(name = "get1")@Autowiredprivate 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

相关文章:

Spring IOCDI————(2)

DI详解 我们之前讲了控制反转IOC,也就是bean的存,那么我们还需要Bean的取,就是DI了,DI翻译过来就是依赖注入,啥意思呢,就是我们通过IOC容器,把所有的对象交给Spring管理,我们指定哪…...

80. Java 枚举类 - 使用枚举实现单例模式

文章目录 80. Java 枚举类 - 使用枚举实现单例模式**1️⃣ 为什么用枚举实现单例?****2️⃣ 枚举实现单例模式****3️⃣ 枚举单例如何防止反射攻击?****4️⃣ 枚举单例如何防止反序列化破坏?****5️⃣ 枚举单例 vs 传统单例****6️⃣ 枚举单例…...

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

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

Java中的集合详解

下面是文章详细介绍了 Java 集合框架的基本思路、主要接口与实现、各类集合之间的区别与各自的适用场景,以及一些常见的使用技巧和最佳实践,供你参考。 Java中的集合详解 在 Java 开发中,集合(Collection)作为存储和操…...

利用 Java 爬虫根据关键词获取某手商品列表

在电商领域,根据关键词获取商品列表是常见的需求。某手作为国内知名的电商平台,提供了丰富的商品资源。通过 Java 爬虫技术,我们可以高效地根据关键词获取某手商品列表,并提取商品的基本信息。本文将详细介绍如何利用 Java 爬虫根…...

Axure项目实战:智慧运输平台后台管理端-订单管理2(多级交互)

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢!如有帮助请订阅专栏! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:订单管理2 主要内容:中继器筛选、表单跟随菜单拖动、审批数据互通等 应用场景:订单管理…...

篇章五 项目创建

目录 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.创建…...

Ntfs!ATTRIBUTE_RECORD_HEADER结构$INDEX_ROOT=0x90的一个例子

Ntfs!ATTRIBUTE_RECORD_HEADER结构$INDEX_ROOT0x90的一个例子 1: kd> dx -id 0,0,899a2278 -r1 ((Ntfs!_FILE_RECORD_SEGMENT_HEADER *)0xc431a400) ((Ntfs!_FILE_RECORD_SEGMENT_HEADER *)0xc431a400) : 0xc431a400 [Type: _FILE_RECORD_SEGMENT_HEADER …...

AGI大模型(30):LangChain链的基本使用

为开发更复杂的应用程序,需要使用Chain来链接LangChain中的各个组件和功能,包括模型之间的链接以及模型与其他组件之间的链接。 链在内部把一系列的功能进行封装,而链的外部则又可以组合串联。 链其实可以被视为LangChain中的一种基本功能单元。 API地址:https://python.…...

代码随想录算法训练营第六十六天| 图论11—卡码网97. 小明逛公园,127. 骑士的攻击

继续补,又是两个新算法,继续进行勉强理解,也是训练营最后一天了,六十多天的刷题告一段落了! 97. 小明逛公园 97. 小明逛公园 感觉还是有点难理解原理 Floyd 算法对边的权值正负没有要求,都可以处理。核心…...

[创业之路-364]:企业战略管理案例分析-5-战略制定-宇树科技的使命、愿景、价值观的演变过程

目录 一、宇树科技的使命、愿景、价值观的演变过程 初创阶段(2016 年成立前后):以技术梦想奠基,明确核心使命愿景 发展阶段(2017 - 2023 年):技术突破与市场拓展,价值观逐步成型 …...

React--函数组件和类组件

React 中的函数组件和类组件是两种定义组件的方式&#xff0c;它们有以下主要区别&#xff1a; 1. 语法与定义方式 函数组件&#xff1a; 是 JavaScript 函数&#xff0c;接收 props 作为参数&#xff0c;返回 JSX。 const MyComponent (props) > {return <div>Hell…...

Flask 路由装饰器:从 URL 到视图函数的优雅映射

前置知识&#xff0c;关于Python装饰器的语法&#xff0c;链接&#xff1a;Python 装饰器&#xff1a;从“语法糖”到“代码神器”的深度解析 1、路由装饰器的功能&#xff1a;给 URL 贴 “功能标签” 在 Flask 开发中&#xff0c;你一定见过这样的代码&#xff1a; from fla…...

DDoS防护实战——从基础配置到高防IP部署

一、基础防护&#xff1a;服务器与网络层加固 Linux内核优化&#xff1a; 调整TCP协议栈参数&#xff0c;缓解SYN Flood攻击&#xff1a; # 启用SYN Cookie并减少超时时间 echo 1 > /proc/sys/net/ipv4/tcp_syncookies echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout…...

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

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

HOT100(二叉树)

二叉树 二叉树的中序遍历 class Solution { public:void traversal(TreeNode* root, vector<int> & vec){if(root nullptr) return;traversal(root->left, vec);vec.push_back(root->val);traversal(root->right, vec);}vector<int> inorderTraver…...

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

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

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…...

springboot3.4.5-springsecurity+session

创建springboot项目&#xff0c;添加以下依赖&#xff1a; LombokSpring WebSpring SecuritySpring Data JDBCMyBatis FrameworkMySQL Driver 添加fastjson2进行序列化和反序列化 <dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>f…...

网络安全利器:蜜罐技术详解

蜜罐是网络安全领域中一种主动防御和情报收集的重要工具。本文将深入探讨蜜罐技术的原理、类型、应用场景以及部署注意事项。 1. 什么是蜜罐? 蜜罐(Honeypot)是一种安全资源,其价值在于被探测、攻击或未经授权使用。简单来说,蜜罐就是一个诱饵系统,用来吸引黑客的注意力…...

Leetcode百题斩-哈希

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

MySQL替换瀚高数据库报错: TO_DAYS()不存在(APP)

文章目录 环境症状问题原因解决方案报错编码 环境 系统平台&#xff1a;中标麒麟&#xff08;海光&#xff09;7,中标麒麟&#xff08;飞腾&#xff09;7 版本&#xff1a;4.5 症状 MySQL替换为瀚高数据库进行应用系统适配报错&#xff1a;TO_DAYS&#xff08;&#xff09;不…...

EXIST与JOIN连表比较

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

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

&#x1f4da; 博主的专栏 &#x1f427; Linux | &#x1f5a5;️ C | &#x1f4ca; 数据结构 | &#x1f4a1;C 算法 | &#x1f152; C 语言 | &#x1f310; 计算机网络 上篇文章&#xff1a;多路转接epoll&#xff0c;实现echoserver 至此&#xff0c;Linux与…...

【jvm第7集】jvm调优工具(命令行工具)

文章目录 JVM 调优工具&#xff08;命令行工具&#xff09;jps&#xff08;Java Virtual Machine Process Status Tool&#xff09;jstat&#xff08;JVM Statistics Monitoring Tool&#xff09;jmap&#xff08;Memory Map Tool&#xff09;jstack&#xff08;Thread Stack T…...

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

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

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

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

关于光谱相机的灵敏度

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

Model 速通系列(一)nanoGPT

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

微信小程序中,一个页面的数据改变了,怎么通知另一个页面也改变?

在微信小程序中&#xff0c;当一个页面的数据改变后通知另一个页面更新&#xff0c;可以通过以下步骤实现&#xff1a; 方法一&#xff1a;使用全局事件总线&#xff08;推荐&#xff09; 步骤说明&#xff1a; 在 app.js 中创建事件系统 在全局 App 实例中实现事件监听和触发…...