【Spring】IocDI详解(6)
本系列共涉及4个框架:Sping,SpringBoot,Spring MVC,Mybatis。
博客涉及框架的重要知识点,根据序号学习即可。
有什么不懂的都可以问我,看到消息会回复的,可能会不及时,请见谅!!
目录
本系列共涉及4个框架:Sping,SpringBoot,Spring MVC,Mybatis。
博客涉及框架的重要知识点,根据序号学习即可。
1、前言
1.1 Spring具体概念
1.2 什么是容器呢?
1.3 什么是IoC
2、IoC详解
2.1 什么是IoC
2.2 IoC有什么作用
2.3 IoC有什么优势
2.4 IoC的使用
2.5 Bean的存储【非常重要!!!一定要好好理解】
2.5.1 @Controller(控制器存储)
2.5.2 @Service(服务存储)
2.5.3 @Repository(仓库存储)
2.5.4 @Component (组件存储)
2.5.5 @Configuration(配置存储)
2.5.6 @Bean 【方法注解---唯一的】
2.6 注解之间的关系
3、DI详解
3.1 什么是DI
3.2 DI与IoC的联系
3.3 DI的使用
3.4 依赖注入的三种方式
3.4.1 属性注入
3.4.2 构造方法注入
3.4.3 Setter注入(设值注入)
3.5 三种注入的优缺点
3.6 @Autowired存在的问题
1、前言
1.1 Spring具体概念
之前的文章谈及到什么是Spring,但是只给了一个抽象的定义。目前我们知道Spring是一个开源的框架,它让我们的开发更加简单,也支持广泛的应用场景,有着活跃而庞大的社区,这也是Spring长久不衰的原因。由于对Spring有着模糊的了解,现在给出一个更加具体的概念:Spring是一个包含众多工具的Ioc容器【关键词:容器??Ioc??】
1.2 什么是容器呢?
容器是用来容纳某种物品的装置。其实在开发圈子,容器这个词已经用得泛滥了。
之前我们遇到过什么容器呢?
List/Map——>数据存储容器
Tomcat——>web容器
1.3 什么是IoC
Ioc是Spring的核心思想【Spring两大核心思想:Ioc与Aop(后续会写关于Aop的文章)】。
其实IoC在之前将Spring MVC入门的文章已经用过了,在类上面添加@RestController和@Controller注解,就是把这个对象交给Spring管理,Spring框架启动时就会加载该类,把对象交给Spring管理,就是IoC思想。
2、IoC详解
2.1 什么是IoC
(1)IoC:Inversion of Control(控制反转),也就是说Spring是一个"控制反转"的容器。
(2)什么是控制反转呢?也就是控制权反转。什么的控制权发生反转?获得依赖对象的过程被反转了,也就是说,当需要某个对象时,传统开发模式中需要自己new创建对象,现在不需要再进行创建,把创建对象的任务交给容器,程序中只需要依赖注入(Dependency Injection,DI)就可以了。这个容器称为:IoC容器。Spring是一个IoC容器,所以有时Spring也称Spring 容器。
2.2 IoC有什么作用
使用IoC思想是将控制权进行反转,简而言之就是不再是使用方对象创建并控制依赖对象了,而是把依赖对象注入当前对象中,依赖对象的控制权不再由当前类控制了。这样的话,即使依赖类发生任何改变,当前类是不受影响的,这就是典型的控制反转,也是IoC的实现思想。
2.3 IoC有什么优势
资源不由使用资源的双方管理,而是由不使用资源的第三方管理,可以带来一下好处:
(1)资源集中管理:IoC容器会帮助我们管理一些资源(对象等),需要使用时直接从IoC容器中去取
(2)同时在创建实例的时候不需要了解其中的细节,降低了使用资源双方的依赖程度,以达软件设计原则中的“低耦合”
Spring就是一种IoC容器,帮助我们管理资源
2.4 IoC的使用
(1)既然Spring是一个IoC(控制反转)容器,那么作为容器,它的基本功能就是存和取
(2)Spring容器管理的主要是对象,我们称这些对象为“Bean”。我们把这些“Bean”交给Spring管理,由Spring来负责对象的创建和销毁,我们程序只需要告诉Spring,哪些需要存,以及哪些需要从Spring中取出来。Spring创建及管理对象就是Bean的存储【非常重要!!!】
2.5 Bean的存储【非常重要!!!一定要好好理解】
要把某个对象交给IoC容器管理,需要在类之前加上注解@Component,而Spring框架为了更好的服务web应用程序,提供了更丰富的注解。
共有两类注解类型可以使用:
1、类注解:@Controller、@Service、@Repository、@Component、@Configuration
2、方法注解:@Bean
2.5.1 @Controller(控制器存储)
(1)使用@Controller存储Bean的代码如下:
@Controller
public class UserController {public void sayHi(){System.out.println("hi,UserController");}
}
如何观察这个对象已经存在Spring容器当中了呢?
接下来学习如何从Spring容器中获取对象
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext context=SpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象UserController userController=context.getBean(UserController.class);//使用对象userController.sayHi();}
}
ApplicationContext翻译过来就是Spring上下文。因为对象都交给Spring管理了,所以获取对象要从Spring中取,那么就需要先得到Spring上下文。当前这个上下文是指当前的运行环境,也可以看做是一个容器,容器里面存了很多内容,这个内容是当前的运行环境。
(2)Bean命名约定
程序人员不需要为bean指定名称,就是说如果没有显式的提供名称,Spring容器会为bean生成唯一的名称。
命名约定使用Java标准约定作为实例字段名,也就是说,bean名称使用小驼峰的形式,比如类名为UserController的Bean的名称为userController
当然也会有一些特殊情况就是当多个字符并且第一个和第二个字母都是大写时,将保留原始大小写。比如类名为UController的Bean的名称为UController
(3)获取Bean的其他方式
如果Spring容器中,同一个类型存在多个Bean的话,怎么获取呢?ApplicationContext也提供了其他获取Bean的方式,ApplicationContext获取Bean对象的功能,是父类BeanFactory提供的功能
@SpringBootApplication
public class SpringIocApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext context=SpringApplication.run(DemoApplication.class,args);//根据bean的类型,从上下文中获取对象UserController userController1=context.getBean(UserController.class);//根据bean的名字,从上下文中获取对象UserController userController2=(UserController) context.getBean("userController");//根据bean的类型+名字,从上下文中获取对象UserController userController3=context.getBean("userController", UserController.class);System.out.println(userController1);System.out.println(userController2);System.out.println(userController3);}
}
地址都一样,说明是同一个对象
2.5.2 @Service(服务存储)
使用@Service存储Bean的代码如下:
@Service
public class UserService {public void sayHi(){System.out.println("hi,UserService");}
}
获取bean的代码
@SpringBootApplication
public class SpringIocApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext context=SpringApplication.run(DemoApplication.class);//从上下文中获取对象UserService userServicer=context.getBean(UserService.class);//使用对象userService.sayHi();}
}
2.5.3 @Repository(仓库存储)
使用@Repository存储Bean的代码如下:
@Repository //将对象存储到Spring中
public class UserRepository {public void say(){System.out.println("hi,UserRepository");}
}
获取bean的代码
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext context=SpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象UserRepository userRepository=context.getBean(UserRepository.class);//使用对象userRepository.sayHi();}
}
2.5.4 @Component (组件存储)
使用@Component存储Bean的代码如下:
@Component
public class UserComponent {public void sayHi(){System.out.println("hi,UserComponent");}
}
获取bean的代码
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext context=SpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象UserComponent userComponent=context.getBean(UserComponent.class);//使用对象userComponent.sayHi();}
}
2.5.5 @Configuration(配置存储)
使用@Configuration存储Bean的代码如下:
@Configuration
public class UserConfiguration {public void sayHi(){System.out.println("hi, UserConfiguration");}
}
获取bean的代码
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext context=SpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象UserConfiguration userConfiguration=context.getBean( UserConfiguration .class);//使用对象userConfiguration.sayHi();}
}
2.5.6 @Bean 【方法注解---唯一的】
在某些外部包的类无法使用类注解以及某些类需要多个对象,这个时候需要使用方法注解@Bean
(1)方法注解需要配合类注解使用
import lombok.Data;@Data
public class User {private String name;private int age;
}
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;@Component
public class BeanConfig {@Beanpublic User user(){User user=new User();user.setName("zhangsan");user.setAge(18);return user;}
}
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext context=SpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象User user=context.getBean(User.class);//使用对象System.out.println(user);}
}
(2)定义多个对象
①根据类型获取user时,报错显示:期望只有一个匹配,却发现了两个,user1和user2
@Component
public class BeanConfig {@Beanpublic User user1(){User user=new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User user2(){User user=new User();user.setName("lisi");user.setAge(17);return user;}
}
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext context=SpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象User user=context.getBean(User.class);//使用对象System.out.println(user);}
}
②根据名称来获取bean对象
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext context=SpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象User user1= (User) context.getBean("user1");User user2= (User) context.getBean("user2");//使用对象System.out.println(user1);System.out.println(user2);}
}
(3)重命名Bean
可以通过设置name属性给Bean对象进行重命名。此时我们使用u1就可以获取到User对象了
@Component
public class BeanConfig {@Bean(name = {"u1","user1"})public User user1(){User user=new User();user.setName("zhangsan");user.setAge(18);return user;}
}
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext context=SpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象User u1= (User) context.getBean("u1");//使用对象System.out.println(u1);}
}
2.6 注解之间的关系
(1)为什么有这么多类注解
这个也是和应用分层相呼应的,让开发人员看到类注解之后,就能直接了解当前类的用途。
@Controller:控制层,接受请求,对请求进行处理,并进行响应
@Service:业务逻辑层,处理具体的业务逻辑
@Repository:数据访问层,也称辞旧层,负责数据访问操作
@Configuration:配置层。处理项目中的一些配置信息。
(2)类注解之间的关系
查看@Controller/@Service/@Repository/@Configutation 等注解的源码发现,这些注解里面都有一个注解@Component,说明它们本来就是属于@Component的子类。@Component是一个元注解,就是也可注解其他类的注解,@Controller/@Service/@Repository/@Configutation等,这些注解都被称为@Component的衍生注解。
3、DI详解
3.1 什么是DI
DI:Dependency Injection(依赖注入)。容器在运行期间,动态的为应用程序提供运行时所依赖的资源,称之为依赖注入。
3.2 DI与IoC的联系
(1)程序运行时需要某个资源,此时容器就为其提供这个资源。从这点可以看出,依赖注入(DI)与控制反转(IoC)是从不同的角度的描述的同一件事,就是指通过引入IoC容器,利用依赖关系注入的方式,实现对象间的解耦。
(2)IoC是一种思想,也是一种“目标”,而思想只是一种指导原则,最终还是需要有可行的落地方案,而DI就是属于具体的实现,所以,DI是IoC的一种实现
3.3 DI的使用
依赖注入是一个过程,是指IoC容器在创建Bean时,去提供运行时所依赖的资源,而资源指的就是对象。
3.4 依赖注入的三种方式
3.4.1 属性注入
属性注入式使用@Autowired实现的,将Service类注入到Controller类中
Service类的实现代码:
import org.springframework.stereotype.Service;@Service
public class UserService {public void sayHi(){System.out.println("hi,UserService");}
}
Controller类的实现代码:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class UserController {//1、属性注入@Autowiredprivate UserService userService;public void sayHi(){System.out.println("hi,UserController");userService.sayHi();}
}
获取Controller中的sayHi方法
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext context=SpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象UserController userController=context.getBean(UserController.class);//使用对象userController.sayHi();}
}
3.4.2 构造方法注入
构造方法是在类的构造方法中实现注入的
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class UserController2 {//2、构造方法注入private UserService userService;@Autowiredpublic UserController2(UserService userService){this.userService=userService;}public void sayHi(){System.out.println("hi,UserController2");userService.sayHi();}
}
@SpringBootApplication public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext context=SpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象UserController2 userController2=context.getBean(UserController2.class);//使用对象userController2.sayHi();} }
PS:如果类只有一个构造方法,那么@Autowired注解可以省略;如果类中又多个构造方法时,那么需要添加上@Autowired来明确指定到底使用哪个构造方法
3.4.3 Setter注入(设值注入)
Setter注入和属性的setter方法实现类似,只不过在设置set方法的时候加上@Autowired注解
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class UserController3 {//2、Setter注入private UserService userService;@Autowiredpublic void setUserController3(UserService userService){this.userService=userService;}public void sayHi(){System.out.println("hi,UserController3");userService.sayHi();}
}
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下文ApplicationContext context=SpringApplication.run(DemoApplication.class,args);//从Spring上下文中获取对象UserController3 userController3=context.getBean(UserController3.class);//使用对象userController3.sayHi();}
}
3.5 三种注入的优缺点
(1)属性注入
优点:简洁,使用方便
缺点:只能用于IoC容器;不能注入一个final修饰的属性
(2)构造方法
优点:可以注入final修饰的属性;注入的对象不会被修改;依赖对象在使用前一定会被完全初始化,因为依赖是在类的构造方法中执行的,而构造方法是在类的加载阶段就会执行的方法;通用性好,构造方法是JDK支持的,所以更换任何框架,也是适用的。
缺点:注入多个对象时,代码会比较繁琐
(3)setter注入
优点:方便在类的实例之后,重新对该对象进行配置或者注入
缺点:不能注入一个final修饰的属性;注入对象可能会被改变,因为setter方法可能会被多洗调用,就会用被修改的风险
3.6 @Autowired存在的问题
(1)同一类型存在多个bean时,使用@Autowired会报错。报错的原因是,非唯一的Bean对象。上面已经出现过了
(2)解决方法:使用以下注解
@Primary、@Qualifier、@Resource
①使用@Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,用来确定默认的实现
@Component
public class BeanConfig {@Primary //指定该bean为默认的bean@Beanpublic User user1(){User user=new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User user2(){User user=new User();user.setName("lisi");user.setAge(17);return user;}
}
②使用@Qualifier注解,指定当前要注入的bean对象。在@Qualifier的value属性中,指定注入的bean的名称【@Qualifier注解不可以单独使用,必须配合@Autowired使用】
@Controller
public class UserController {@Qualifier("user1") //指定bean的名称@Autowiredprivate User user;public void sayHi(){System.out.println("hi,UserController");System.out.println(user);}
}
③使用@Resource注解,是按照bean的名称进行注入。通过name属性指定要注入的bean的名称
@Controller
public class UserController {@Resource(name = "user1")private User user;public void sayHi(){System.out.println("hi,UserController");System.out.println(user);}
}
相关文章:

【Spring】IocDI详解(6)
本系列共涉及4个框架:Sping,SpringBoot,Spring MVC,Mybatis。 博客涉及框架的重要知识点,根据序号学习即可。 有什么不懂的都可以问我,看到消息会回复的,可能会不及时,请见谅!! 目录 本系列共…...

Redis系列之底层数据结构SDS
Redis系列之底层数据结构SDS 实验的环境 Redis 6.0VSCode 1.88.1 什么是SDS? SDS:Simple Dynamic String,翻译为简单动态字符串。SDS是一种用于存储二进制数据的数据结构,具有动态扩容的特点,代码位于src/sds.h和src/sds.c …...

【STM32】esp8266连接wifi
1.配置stm32cubemx 使用串口二接收esp8266的数据,单片机接收,使用串口1将数据发送给串口助手 串口2波特率设置74880,串口1设置115200 在初始化的时候需要将复位引脚拉低20ms,然后再拉高20ms, 设置GPIOB的输出模式 对PB12做输出处理 2.…...
网络运维故障处理
本篇纯是之前的工作经验做一个分享,大家看个热闹就好。 1.突然的断网,在上家上班的时候,有一天突然下午厂区内开始出现大面积网络卡顿,teams,outlook不好使等情况,且网盘也上不去,所以开始排查…...

C++第十一节课 new和delete
一、new和delete操作自定义类型 new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数(new会自动调用构造函数;delete会调用析构函数) class A { public:A(int a 0): _a(a){cout <&l…...

【爱给网-注册安全分析报告-无验证方式导致安全隐患】
前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…...

苹果为什么不做折叠屏手机?
苹果为什么不做折叠屏手机?折叠屏手机在最近这些年里边,可以说是市场的一个主要在手机上的增长点。你像华W最近推出这个三折叠手机,引起了整个市场的轰动。 可是,为什么苹果到今天为止不为所动,还在那不停地在现在的这…...
目标检测经典算法的个人理解
one stage 1、RCNN -> Fast-RCNN:RPN部分从用传统的算法 -> 用深度学习网络来实现。 2、Fast-RCNN -> Faster-RCNN:从先选region再求Feature -> 先求Feature再选region。 two stage 1、SSD(2016):VGG做…...
FewShotChatMessagePromptTemplate 和 FewShotPromptTemplate区别
FewShotChatMessagePromptTemplate 和 FewShotPromptTemplate 都是 LangChain 框架中用于少样本学习的提示模板(Prompt Template),但它们在设计和用途上存在一些区别。 FewShotChatMessagePromptTemplate 用途:主要用于聊天场景…...

《程序猿之设计模式实战 · 策略模式》
📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…...
deepinlinux-v23用deepinunioncode初始c例子
deepinlinux-v23用deepinunioncode初始c例子 # deepinunioncode 新建duc工程cmake模版,开局提示 No CMAKE_CXX_COMPILER could be found错误记录 需要duc 左下角磁轮设置 设置cmake和gcc g的文件,如果本机装过了(apt install gc…...
前端框架对比选择:如何在众多技术中找到最适合你的
引言 在现代Web开发中,前端框架的选择对项目的成功与否至关重要。随着技术的不断发展,市面上涌现出多种前端框架,每种框架都有其独特的特点、优缺点以及适用场景。本文将对当前主流的前端框架进行详细对比,帮助开发者在选择时做出…...

数据结构—(java)反射,枚举,lambda表达式
文章目录 反射反射的定义:反射相关的类:反射相关的方法:反射示例:获取Class类对象创建指定类的对象反射私有属性:反射私有方法:反射私有的构造方法 枚举枚举的意义枚举类的实现枚举类的使用:Enu…...

机器学习(西瓜书)第 14 章 概率图模型
14.1 隐马尔可夫模型 机器学习最重要的任务,是根据一些已观察到的证据(例如训练样本)来对感兴趣的未知变量(例如类别标记)进行估计和推测。概率模型(probabilistic model)提供了一种描述框架&a…...
Python异步编程-asyncio详解
目录 asyncio简介示例什么是 asyncio?适用场景API asyncio的使用可等待对象什么是可等待对象?协程对象任务对象Future对象 协程什么是协程?基本使用运行协程 Task什么是 Task?创建 Task取消 TaskTask 异常获取Task 回调 TaskGroup什么是 Tas…...
UniApp如何打包成客户端应用程序
像flutter是支持PC宽屏、桌面平台(Windows/macOS/Linux),我一直在期望UniApp什么时候也支持PC,桌面平台,终于盼到了。 1、支持PC宽屏 从uni-app 2.9起,支持PC宽屏的适配。 uni-app提供的屏幕适配方案&am…...
你应该掌握的12条饭局规矩!
在职场的舞台上,饭局不仅仅是一场简单的聚餐,它是一场精心编排的社交盛宴,是展示个人魅力、构建人脉网络的重要平台。精通饭局的艺术,能让你在职场的交际中更加自如。以下是酱酒亮哥整理的12条饭局指南,希望你在职场的…...
【541. 反转字符串 II 简单】
题目: 给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。 如果剩余字符少于 k 个,则将剩余字符全部反转。如果剩余字符小于 2k 但大于或等于 k 个,…...

基于PHP的丽江旅游管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的丽江旅游管理系统 一 介绍 此丽江旅游系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈:phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销…...

vue3+Element-plus el-input 输入框组件二次封装(支持金额、整数、电话、小数、身份证、小数点位数控制,金额显示中文提示等功能)
一、效果图 二、组件集成了以下功能 1、输入金额--支持千分号显示、可设置decimalLimit来调整小数点位数 2、金额鼠标移入提示中文--标签添加isTip开启中文提示则不允许开启千分号显示showThousands 3、输入手机号--设置inputTypephone 4、输入整数---设置inputTypeinteger 5、…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...