Spring IoCDI(2)—IoC详解

目录

一、IoC详解

1、Bean的存储

(1)@Controller(控制器存储)

获取bean对象的其他方式

Bean 命名约定

(2)@Service(服务存储)

(3)@Repository(仓库存储)

(4)@Component(组件存储)

(5)@Configuration(配置存储)

2、为什么要这么多类注解?

类注解之间的关系:

3、方法注解 @Bean

(1)方法注解要配合类注解使用

(2)定义多个对象

(3)重命名 Bean

4、扫描路径


一、IoC详解

        IoC控制反转就是将对象的控制权交给Spring的IoC容器,由IoC容器创建及管理对象也就是bean的存储

        共有两类注解类型可以实现:1、类注解:@Controller、@Service、@Repository、@Component、@Configuration2、方法注解:@Bean

1、Bean的存储

(1)@Controller(控制器存储)

        使用@Controller注解,存储bean的代码如下:

@Controller
public class UserController {public void sayHi() {System.out.println("hi, UserController");}
}

        这个对象加了@Controller注解,就把这个对象放在Spring容器中了,下面是从Spring容器获取对象,代码如下:

@SpringBootApplication
public class SpringIoC2Application {public static void main(String[] args) {//获取Spring的上下文ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);//从Spring的上下文中获取对象UserController bean = (UserController)context.getBean(UserController.class);bean.sayHi();}
}

        ApplicantContent 翻译过来就是:Spring 上下文因为对象交给Spring管理了,所以获取对象要从Spring中获取,那么就得先得到Spring的上下文

        关于上下文的概念在计算机领域,上下文这个概念,在线程那已经了解过了,比如应用进行线程切换的时候,切换前都会把线程的状态信息暂时存储起来,这里的上下文就包括了当前线程的信息,等下次该线程又得到CPU时间的时候,从上下文中拿到线程上次运行的信息

        这里的上下文,就是当前的运行环境,也可以看做是一个容器,容器里存了很多内容,这些内容是当前运行的环境

        观察运行结果,发现成功从Spring中获取了Controller 对象,并执行Controller的sayHi方法,如图:

        如果把UserController类上面的注解@Controller去掉,就会报错,如图:

        报错信息找不到类型是com.example.springioc2.controller.UserController的bean因为没加这个注解,自然也就没声明把这个类交给Spring管理,Spring也就找不到该类的bean了

获取bean对象的其他方式

        上述代码是根据类型来查找对象的,如果Spring容器中,同一个类型存在多个bean的话,要怎么获取?ApplicationContext也提供了其他获取bean的方式,ApplicationContext获取bean对象的功能,是父类BeanFactory提供的功能。如下代码:

public interface BeanFactory {//以上省略...// 1. 根据bean名称获取beanObject getBean(String var1) throws BeansException;// 2. 根据bean名称和类型获取bean<T> T getBean(String var1, Class<T> var2) throws BeansException;// 3. 按bean名称和构造函数参数动态创建bean,只适⽤于具有原型(prototype)作⽤域的beanObject getBean(String var1, Object... var2) throws BeansException;// 4. 根据类型获取bean<T> T getBean(Class<T> var1) throws BeansException;// 5. 按bean类型和构造函数参数动态创建bean, 只适⽤于具有原型(prototype)作⽤域的bean<T> T getBean(Class<T> var1, Object... var2) throws BeansException;//以下省略...
}

        最常用的是1、2、4种,这三种方式(根据bean名称获取bean根据bean类型和名称获取bean根据bean类型获取bean),获取到的bean是一样的

        其中1、2种都涉及到根据名称来获取对象,那么bean的名称是什么呢?

Spring bean 是Spring框架在运行时管理的对象,Spring会给管理的对象起一个名字

比如学校管理学生,会给每个学生分配一个学号,根据学号,就可以找到对应的学生。

Spring也是如此,给每个对象都起一个名字,根据Bean的名称(BeanId)就可以获取到对应的对象

Bean 命名约定

官方文档:Bean Overview :: Spring Framework

        程序开发人员不需要为bean指定名称(BeanId),如果没有显示的提供名称(BeanId),Spring容器将为该bean生成唯一的名称。

        命名约定使用Java标准约定作为实例字段名。也就是bean名称以小写字母开头,然后使用驼峰式大小写。例子如下:

类名:UserController,Bean的名称为:userController

类名:AccountManager,Bean的名称为:accountManager

类名:AccountService,Bean的名称为:accountService

        也有一些特殊情况,当多个字符并且第一个字符和第二个字符都是大写时,将保留原始大小写。这些规则与java.beans.Introspector.decapitalize(Spring在这里使用的)定义的规则相同。例子如下:

类名:UController,Bean的名称为:UController

类名:AManager,Bean的名称为:AManager

        根据这个命名规则,我们来获取Bean,代码如下:

@SpringBootApplication
public class SpringIoC2Application {public static void main(String[] args) {//获取Spring的上下文ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);//从Spring的上下文中获取对象//根据bean类型,从Spring上下文中获取对象UserController userController1 = (UserController)context.getBean(UserController.class);//根据bean名称,从Spring上下文获取对象UserController userController2 = (UserController)context.getBean("userController");//根据bean名称+类型,从Spring上下文获取对象UserController userController3 = (UserController) context.getBean("userController", UserController.class);System.out.println(userController1);System.out.println(userController2);System.out.println(userController3);}
}

        运行结果如下图:

        地址都是一样的,说明对象是同一个。

ApplicationContext 和 BeanFactory (常见面试题)

1、从继承关系和功能方面来说Spring容器有两个顶级的接口:BeanFactory 和 ApplicationContext。其中BeanFactory提供了基础的访问容器的能力,而 ApplicationContext 属于 BeanFactory 的子类,它除了继承 BeanFactory 的所有功能外,它还有自己独特的特性,还添加了对国际化支持、资源访问支持、以及事件传播等方面支持

2、从性能方面来说ApplicationContext是一次性加载并初始化所有Bean对象(提前加载),而 BeanFactory 是需要哪个对象了,才去加载那个对象(懒加载),因此更轻量

(2)@Service(服务存储)

        使用@Service存储bean的代码如下:

@Service
public class UserService {public void doService() {System.out.println("do Service...");}
}

        读取bean的代码:

@SpringBootApplication
public class SpringIoC2Application {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);//从Spring中获取UserService对象UserService userService = context.getBean(UserService.class);//使用对象userService.doService();}
}

        执行结果如下:

        

        把注解@Service删掉,会报错,如图:

        和去掉@Controller注解一样的报错原因一样,找不到bean。

(3)@Repository(仓库存储)

        使用@Repository存储bean代码如下:

@Repository
public class UserRepository {public void doRepository() {System.out.println("do Repository...");}
}

        读取bean的代码:

@SpringBootApplication
public class SpringIoC2Application {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);//从Spring中获取UserRepository对象UserRepository userRepository = context.getBean(UserRepository.class);//使用对象userRepository.doRepository();}
}

        运行结果:

        同样把注解@Repository去掉,会报错,如图:

        原因和上面的一样。

(4)@Component(组件存储)

        使用@Component存储bean的代码:

@Component
public class UserComponent {public void doComponent() {System.out.println("do Component...");}
}

        读取bean的代码:

@SpringBootApplication
public class SpringIoC2Application {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);//从Spring中获取UserComponent对象UserComponent userComponent = context.getBean(UserComponent.class);//使用对象userComponent.doComponent();}
}

        执行结果:

        如果把注释@Component去掉,报错和上面的一样,如图:

(5)@Configuration(配置存储)

        使用@Configuration存储bean的代码如下:

@Configuration
public class UserConfiguration {public void doConfiguration() {System.out.println("do Configuration...");}
}

        读取bean的代码:

@SpringBootApplication
public class SpringIoC2Application {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);//从Spring中获取UserComponent对象UserConfiguration userConfiguration = context.getBean(UserConfiguration.class);//使用对象userConfiguration.doConfiguration();}
}

        执行结果如下:

        同样,把注释@Configuration去掉,会报错,原因和上面的都一样,结果如下:

2、为什么要这么多类注解?

        这个和前面的应用分层是对应的,程序员看到这些类注解后,就能直接了解当前类的用途。

@Controller控制层,接收请求,对请求进行处理,并进行响应

@Service业务逻辑层,处理具体的业务逻辑

@Repository数据访问层,也称为持久层。负责数据访问操作

@Configuration配置层,处理项目中的一些配置信息

        和三层架构的对应关系@Controller 对应 表现层,@Service 对应 业务逻辑层,@Repository 对应 数据层

        这里和每个省 / 市都有自己的车牌号一样,车牌号都是唯一的,我们看到车牌,就能知道车主是哪里的了 / 车的归属地,比如 粤X、京X等等。这样做的好处即可以节约号码,还有更重要的作用:标识一辆车的归属地。

        程序的应用分层,调用流程如下:

类注解之间的关系:

        查看@Controller、@Service 、@Repository、@Configuration注解的源码我们发现,它们里面都有一个@Component注解

        这也能说明它们本身就是属于 @Component 的 “子类”。而@Component是一个元注解,也就是说可以注解其他类的注解,如 @Controller、@Service、@Repository 等等,这些注解则被称为 @Component的衍生注解

        @Controller、@Service 和 @Repository 用于更具体的用例(分别为控制层、业务逻辑层、数据访问层),在开发过程中,如果你要在业务逻辑层使用@Component或者@Service,显然@Service是更好的选择

        好比是杯子有喝水的(水杯),也有刷牙的(刷牙杯)等等,但我们更倾向于在日常喝水时使用水杯,洗漱时使用刷牙杯。

更多资料参考:Classpath Scanning and Managed Components :: Spring Framework

3、方法注解 @Bean

        类注解是添加到某个类上的,但是存在两个问题:1、使用外部包里的类,没办法添加类注解。2、一个类,需要多个对象,比如多个数据源。这些场景,我们就需要使用方法注解:@Bean

        以下是方法注解@Bean使用的代码:

public class BeanConfig {@Beanpublic UserInfo userInfo() {UserInfo user = new UserInfo();user.setId(6);user.setName("zhangsan");user.setAge(18);return user;}
}

        读取bean的代码:

@SpringBootApplication
public class SpringIoC2Application {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);//从Spring中获取对象UserInfo userInfo = context.getBean(UserInfo.class);//使用对象System.out.println(userInfo);}
}

        但我们发现,获取不到,程序报错了,如图:

        原因就是方法注解要搭配类注解使用,上面却没有搭配。

        为什么要搭配类注解呢?因为Spring Boot项目会引入非常多的依赖,里面的代码的方法也会有很多注解,如果都进行扫描,那就太耗时了,不如搭配类注解,Spring就知道从哪些类中扫描,大大的提高了性能

(1)方法注解要配合类注解使用

        在Spring框架的设计中,方法注解 @Bean 要配合类注解才能将对象正常的存储到Spring容器中,代码如下:

@Component
public class BeanConfig {@Beanpublic UserInfo userInfo() {UserInfo user = new UserInfo();user.setId(6);user.setName("zhangsan");user.setAge(18);return user;}
}

        执行结果如下:

(2)定义多个对象

        对于同一个类,定义多个对象(多个方法使用@Bean注解);比如多数据源的场景,类是同一个,但配置是不同的,指向不同的数据源。

@Component
public class BeanConfig {@Beanpublic UserInfo userInfo1() {UserInfo user = new UserInfo();user.setId(6);user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic UserInfo userInfo2() {UserInfo user = new UserInfo();user.setId(7);user.setName("lisi");user.setAge(19);return user;}
}

        定义了多个对象的话,我们根据类型获取对象,获取的是哪个对象呢?代码如下:

@SpringBootApplication
public class SpringIoC2Application {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);//从Spring中获取对象UserInfo userInfo = context.getBean(UserInfo.class);//使用对象System.out.println(userInfo);}
}

        执行结果,可以看到,报错了:

        可以看到,报错信息显示期望只有一个匹配,结果发现两个:userInfo1,userInfo2。从报错信息中,可以看出来,@Bean注解的bean,bean的名称就是它的方法名

        我们现在改一下代码,根据名称来获取bean对象,代码如下:

@SpringBootApplication
public class SpringIoC2Application {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);//从Spring中获取对象UserInfo userInfo1 = (UserInfo) context.getBean("userInfo1");UserInfo userInfo2 = (UserInfo) context.getBean("userInfo2");//使用对象System.out.println(userInfo1);System.out.println(userInfo2);}
}

        运行结果如下:

        可以看到,@Bean可以针对同一个类,定义多个对象。

(3)重命名 Bean

        可以通过设置 name 属性,给Bean对象进行重命名操作,代码如下:

@Component
public class BeanConfig {@Bean(name = {"u1", "userInfo1"})public UserInfo userInfo1() {UserInfo user = new UserInfo();user.setId(6);user.setName("zhangsan");user.setAge(18);return user;}
}

        此时使用 u1 就可以获取到User对象了,代码如下:

@SpringBootApplication
public class SpringIoC2Application {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);//从Spring上下文中获取对象UserInfo u1 = (UserInfo)context.getBean("u1");//使用对象System.out.println(u1);}
}

        运行结果如下:

        使用 useInfo1 也可以获取到User对象,两个字符串都是对UserInfo的重命名,代码如下:

@SpringBootApplication
public class SpringIoC2Application {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);//从Spring上下文中获取对象UserInfo u1 = (UserInfo)context.getBean("userInfo1");//使用对象System.out.println(u1);}
}

        执行结果:

        其中,@Bean中的name也可以省略,代码如下:

@Component
public class BeanConfig {@Bean({"u1", "userInfo1"})public UserInfo userInfo1() {UserInfo user = new UserInfo();user.setId(6);user.setName("zhangsan");user.setAge(18);return user;}
}

        只有一个名称时,{ } 也可以省略,代码如下:

@Component
public class BeanConfig {@Bean("u1")public UserInfo userInfo1() {UserInfo user = new UserInfo();user.setId(6);user.setName("zhangsan");user.setAge(18);return user;}
}

4、扫描路径

        现在有个问题,就是不管啥类,只要搭配了五大注解或者五大注解+Bean,Spring就能启动成功吗?

        其实不然,原因就是扫描路径的问题,Spring默认只会对启动类所在的目录下进行扫描,并且扫描的是搭配了五大注解的类或者搭配五大注解+Bean的类

        启动类加了 @SpringBootApplication 注解的类

        现在测试一下,把启动类移动一下,此时启动类所在路径如图:

        

        试试看还能不能获取到UserService对象,UserService类的代码如下:

@Service
public class UserService {public void doService() {System.out.println("do Service...");}
}

        启动柜类代码如下:

@SpringBootApplication
public class SpringIoC2Application {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);//从Spring中获取UserService对象UserService userService = context.getBean(UserService.class);//使用对象userService.doService();}
}

        执行结果如下图:

        报错解释没有bean的类型是UserService的

        这里为什么没有找到bean对象呢?原因:即使使用了五大注解,或者五大注解 + @Bean注解,要想生效,还需要配置扫描路径,让Spring扫描到这些注解下的类,也就是通过 @ComponentScan 来配置。加了 @ComponentScan注解 的代码如下:

@ComponentScan({"com.example.springioc2.service"})
@SpringBootApplication
public class SpringIoC2Application {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);//从Spring中获取UserService对象UserService userService = context.getBean(UserService.class);//使用对象userService.doService();}
}

        其中注解@ComponentScan的括号里面,加的是UserService类的包路径,直接复制即可,在Service类里面,如下图:

        执行结果如下:

         可以拿到bean对象了。

        其中注解@ComponentScan括号里的 { } ,可以加多个大括号,表示扫描多个路径,如图:

        那为什么之前没有配置 @ComponentScan注解 ,也可以正常启动?原因是: @ComponentScan注解 虽然没有显示配置,但是实际上已经包含在启动类声明注解@SpringBootApplication 中了

        默认扫描的范围是SpringBoot启动类所在包及其子包在配置类添加 @ComponentScan注解,该注解默认会扫描该类所在的包下所有的配置类,如图:

        开发时的推荐做法把启动类放在我们希望扫描的包的路径下,这样我们自己写的代码就都可以被扫描到了,如图:


都看到这了,点个赞再走吧,谢谢谢谢谢

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

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

相关文章

2分钟教你Flutter怎么避免引用内存泄漏

2分钟教你Flutter怎么避免引用内存泄漏 内存泄漏原因1. 在当前类&#xff0c;或者方法等移除改引用&#xff0c;让其他自动释放&#xff0c;等下一轮GC扫描释放。如2. 使用弱引用-----**WeakReference**&#xff0c;当前使用完&#xff0c;生命周期结束后&#xff0c;自动释放。…

VTK —— 三、图形格式 - 示例1 - 读取.vtp文件并输出.ply文件(附完整源码)

代码效果&#xff1a;演示程序读取.vtp后输出.ply文件&#xff0c;使用paraview打开该输出的.ply文件 本代码编译运行均在如下链接文章生成的库执行成功&#xff0c;若无VTK库则请先参考如下链接编译vtk源码&#xff1a; VTK —— 一、Windows10下编译VTK源码&#xff0c;并用V…

opencv图像处理详细讲

传统的计算机视觉框架&#xff1a; SimpleCV BoofCV Dlib JavaCV 深度学习计算机视觉框架 Caffe Tensorflow Pytorch Paddlepaddle Keras 深度视觉计算机视觉框架 OpenVINO TensorRT onnxruntime Deepface YOLO/DarkNet mmdetection Paddle-detection/seg/ocr …

重识来伊份:抢滩首店经济,休闲零食品牌的“面子”和“里子”

前不久&#xff0c;苹果静安零售店的首秀频频登上热搜。 这背后&#xff0c;不仅仅因为它是中国大陆最大的苹果旗舰店&#xff0c;还在于它的设计融入了时尚又古典的上海街区&#xff0c;吸引了众多市民拍照打卡。今年3月至5月&#xff0c;上海会持续举办“首发上海”春季系列…

电能计量抄表系统

1.电能计量抄表系统的概念和作用 电能计量抄表系统是一种前沿的自动化控制&#xff0c;主要运用于电力行业的电费计算及管理。它通过远程数据采集和处理&#xff0c;实时监控系统用户的用电状况&#xff0c;取代了传统的手工抄水表方法&#xff0c;降低了成本&#xff0c;降低…

五、VGA 叠加图像原理和实现(十字光标)

前言&#xff1a;该案例在VGA项目&#xff1a;联合精简帧双fifosobel算法 实现VGA显示项目的基础上进行改动。 要求&#xff1a;通过串口助手把 198x198 的十字光标图像二进制数据传递给 FPGA 板卡&#xff0c;FPGA 板 卡接收到后存储到 Ram 中用于 VGA 叠加显示。 预期效果展…

020、Python+fastapi,第一个Python项目走向第20步:ubuntu 24.04 docker 安装mysql8集群+redis集群(一)

系列文章 pythonvue3fastapiai 学习_浪淘沙jkp的博客-CSDN博客https://blog.csdn.net/jiangkp/category_12623996.html 前言 docker安装起来比较方便&#xff0c;不影响系统整体&#xff0c;和前面虚拟环境有异曲同工之妙&#xff0c;今天把老笔记本T400拿出来装了个ubuntu24…

小程序激励广告视频多次回调问题

1.问题 2. 激励视频使用及解决方案 官方文档 let videoAd null; // 在页面中定义激励视频广告 Page({/*** 页面的初始数据*/data: {},/*** 生命周期函数--监听页面加载*/onLoad(options) {let that this;// 创建激励视频广告实例if (wx.createRewardedVideoAd) {videoAd w…

知识库工具:付费的HelpLook AI知识库比免费的牵牛易帮好在哪里

在知识管理的领域中&#xff0c;选择合适的知识库工具对于企业来说很重要。市面上有很多知识库产品&#xff0c;有付费的和免费的&#xff0c;但是还是有很多企业会选择使用付费的&#xff0c;而不是免费的。这是为什么呢&#xff1f;这就是今天要探讨的问题&#xff0c;下面就…

Android虚拟机机制

目录 一、Android 虚拟机 dalvik/art&#xff08;6版本后&#xff09;二、Android dex、odex、oat、vdex、art区别 一、Android 虚拟机 dalvik/art&#xff08;6版本后&#xff09; 每个应用都在其自己的进程中运行&#xff0c;都有自己的虚拟机实例。ART通过执行DEX文件可在设…

什么是B2B SaaS公司?

前言 在当今数字化时代&#xff0c;B2B SaaS公司正在以惊人的速度崛起&#xff0c;成为企业界的一股重要力量。但是&#xff0c;对于许多人来说&#xff0c;B2B SaaS究竟是什么&#xff0c;以及它如何影响商业生态&#xff0c;可能还是一片未知。本文将简要介绍B2B SaaS公司的…

Python+Selenium 实现自动化测试

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 安装selenium 打开命令控制符输入&#xff1a;pip install -U …

网络安全----小程序渗透测试反编译审计漏洞

一、什么是反编译审计漏洞 微信小程序反编译渗透测试是一种针对微信小程序的安全测试方法&#xff0c;是在通过对小程序源代码的反编译和分析&#xff0c;发现潜在的安全漏洞&#xff0c;并对其进行渗透测试以验证其安全性的一种方法。 二、测试流程及其步骤 反编译小程序&a…

C#知识|如何在WinForm窗体中实现分割线绘制?

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 在上位机UI设计中经常会用到分割线&#xff0c;用来分割界面区域。 像在KingSCADA、杰控、昆仑通态、WinCC、组态王、力控、易控等组态软件中非常简单&#xff0c;有现成的划线操作&#xff0c;选中相关工具直接绘制即…

颠覆传统?「一束光子,两种频率」的量子纠缠!

在最新的研究中&#xff0c;科学家们开发了一种革命性的量子纠缠方式——“频域光子数路纠缠”&#xff08;frequency-domain photon number-path entanglement&#xff09;。这一量子物理学的重大进展涉及到一个创新性的工具&#xff1a;频率分束器&#xff08;frequency beam…

jmeter后置处理器提取到的参数因为换行符导致json解析错误

现象&#xff1a; {"message":"JSON parse error: Illegal unquoted character ((CTRL-CHAR, code 10)): has to be escaped using backslash to be included in string value; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Ill…

开源之夏 2024 学生报名通道现已正式开启!奖金都是12000元,冲啊!!!

Apache SeaTunnel作为数据集成平台的先行者&#xff0c;数以千计的开发者活跃在这个开源社区&#xff0c;我们深知开源社区就像是“众人拾柴火焰高”&#xff0c;希望有更多的青年力量能参与到社区的建设中来&#xff01; 在前段时间&#xff0c;我们不仅成功入选中科院软件所主…

[C++]VS2022配置cplex12.8过程中出现ext未声明标识符语法错误:标识符“ImplClass“

这个时候&#xff0c;主要的是看报错&#xff0c;根据报错&#xff0c;去网上寻找解决办法。因为这个时候&#xff0c;代码可能并没有任何错误&#xff0c;只不过你是VS2022&#xff0c;老师是VS2017或者其他版本。不同的版本之间代码运行问题&#xff0c;如果你换成cplex12.10…

【前端】输入时字符跳动动画实现

输入时字符跳动动画实现 在前端开发中&#xff0c;为了提升用户体验&#xff0c;我们经常需要为用户的交互行为提供即时的反馈。这不仅让用户知道他们的操作有了响应&#xff0c;还可以让整个界面看起来更加生动、有趣。本文将通过一个简单的例子讲解如何实现在用户输入字符时…

速卖通自养号测评海外环境:成本、步骤、技巧全掌握

相信不少涉足跨境业务的企业和商家都对速卖通耳熟能详。作为当下炙手可热的跨境电商平台&#xff0c;速卖通在国内电商市场渐趋饱和的背景下&#xff0c;吸引了众多国内卖家的目光。他们纷纷入驻速卖通&#xff0c;希望借助这一平台的力量&#xff0c;成功打通跨境业务渠道。然…