Spring6 当中的 Bean 循环依赖的详细处理方案+源码解析

1. Spring6 当中的 Bean 循环依赖的详细处理方案+源码解析

文章目录

  • 1. Spring6 当中的 Bean 循环依赖的详细处理方案+源码解析
  • 每博一文案
    • 1.1 Bean的循环依赖
    • 1.2 singletion 下的 set 注入下的 Bean 的循环依赖
    • 1.3 prototype下的 set 注入下的 Bean 的循环依赖
    • 1.4 singleton下的构造注入产生的循环依赖
    • 1.5 Spring 解决循环依赖的原理(源码解析)
  • 2. 总结:
  • 3. 最后:


每博一文案

听完这段话就勇敢起来吧,在任何犹豫的时刻,一旦抱有人生就这么短短几十年,我不去做一定会后悔这样的想法,就会凭空多出几分勇气,比如:尝试新的穿衣风格,向喜欢的人表白,去特别贵的餐厅大吃一顿,对看不惯的人和事说不,不乐观的想,我们其实都是没有来路和归途的,能拥有的就是现在,所以想做什么就去做吧,冲动一点也没关系,吃点亏也没关系.

1.1 Bean的循环依赖

A对象中有B属性。B对象中有A属性。这就是循环依赖。我依赖你,你也依赖我。
比如:丈夫类Husband,妻子类Wife。Husband中有Wife的引用。Wife中有Husband的引用。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

package com.rainbowsea.bean;

public class Wife {
    private String name;
    private Husband husband;

    public Wife() {
    }

    public Wife(String name, Husband husband) {
        this.name = name;
        this.husband = husband;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Husband getHusband() {
        return husband;
    }

    public void setHusband(Husband husband) {
        this.husband = husband;
    }

    // toString()方法重写时需要注意:不能直接输出husband,输出husband.getName()。要不然会出现递归导致的栈内存溢出错误。
    @Override
    public String toString() {
        return "Wife{" +
                "name='" + name + '\'' +
                ", husband=" + this.husband.getName() +
                '}';
    }
}

Husband

package com.rainbowsea.bean;

public class Husband {
    private String name;
    private Wife wife;


    public Husband() {
    }

    public Husband(String name, Wife wife) {
        this.name = name;
        this.wife = wife;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Wife getWife() {
        return wife;
    }

    public void setWife(Wife wife) {
        this.wife = wife;
    }


    // toString()方法重写时需要注意:不能直接输出wife,输出wife.getName()。要不然会出现递归导致的栈内存溢出错误
    @Override
    public String toString() {
        return "Husband{" +
                "name='" + name + '\'' +
                ", wife=" + this.wife.getName() +
                '}';
    }
}

注意点: toString()方法重写时需要注意:不能直接输出wife,输出wife.getName()。要不然会出现递归导致的栈内存溢出错误。

1.2 singletion 下的 set 注入下的 Bean 的循环依赖

我们来编写程序,测试一下在singleton+setter的模式下产生的循环依赖,Spring是否能够解决?

准备工作:配置导入 相关的 spring 框架,让 Maven 帮我们导入 spring的相关jar包。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.rainbowsea</groupId>
    <artifactId>spring6-007-circular-dependency-blog</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.11</version>
        </dependency>


        <!-- junit4 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>

    </dependencies>
</project>

配置相关的 spring.xml 文件信息。

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--     Husband 的配置-->
    <bean id="husbandBean" class="com.rainbowsea.bean.Husband" scope="singleton">
        <property name="name" value="小明" ></property>
        <property name="wife" ref="wifeBean"></property> <!--set 注入-->
    </bean>
    <!--    Wife 的配置-->
    <bean id="wifeBean" class="com.rainbowsea.bean.Wife" scope="singleton">
        <property name="name" value="小花"></property>
        <property name="husband" ref="husbandBean"></property>
    </bean>
</beans>

运行测试:
在这里插入图片描述
通过测试得知:在singleton + set注入的情况下,循环依赖是没有问题的。Spring可以解决这个问题。

package com.rainbowsea.test;

import com.rainbowsea.bean.Husband;
import com.rainbowsea.bean.Wife;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class CircularDependencyTest {
    @Test
    public void testCircularDependency() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        Husband husbandBean = applicationContext.getBean("husbandBean", Husband.class);
        System.out.println(husbandBean);


        Wife wifeBean = applicationContext.getBean("wifeBean", Wife.class);
        System.out.println(wifeBean);
    }


}

解决分析:

singleton + setter模式下可以解决的循环依赖问题

在singleton + setter 模式下,为什么循环依赖不会出现问题,Spring是如何应对的?

主要原因是:在这个 singleton 单例模式下,在Spring 容器中的 bean 对象是独一无二的对象,是唯一的一个。同志在该 singleton 单例模式下:Spring 对 Bean 的管理主要分为清晰的两个阶段

  1. 第一个阶段:在Spring 容器加载的时候,实例Bean ,只要其中任意一个 Bean 实例化之后,马上进行一个==“曝光”== (注意:曝光不等于属性赋值,曝光了,但是属性并没有附上值的)
  2. 第二个阶段:Bean ==“曝光”==之后,再进行属性的赋值操作(调用 set()方法实现对属性的赋值操作)

核心解决方案是:实例化对象和对象的属性赋值分为两个阶段来完成,并不是一次性完成的。

简单来说:就是:singleton 优先被“曝光”,实例化和赋值是分开的,会优先把实例化的对象的地址曝光出来,因为在 singleton 单例模式下,bean 是唯一的一个,独一无二的,并且早晚都要进行赋值操作。提前曝光,后面再进行赋值也是无妨的。因为你弄来弄去,就是那唯一的一个 bean。不存在多个,不知道是哪一个的问题

在这里插入图片描述

1.3 prototype下的 set 注入下的 Bean 的循环依赖

我们再来测试一下:prototype+set注入的方式下,循环依赖会不会出现问题?

我们只需将 spring.xml 配置文件信息,修改为 protoype (多例)即可。

在这里插入图片描述
运行测试看看。

在这里插入图片描述
报错,报错信息如下:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘husbandBean’ defined in class path resource [spring.xml]: Cannot resolve reference to bean ‘wifeBean’ while setting bean property ‘wife’

创建名为“husbandBean”的bean时出错:请求的bean当前正在创建中:是否存在无法解析的循环引用?通过测试得知,当循环依赖的所有Bean的scope="prototype"的时候,产生的循环依赖,Spring是无法解决的,会出现BeanCurrentlyInCreationException异常。

prototype下的 set 注入下的 Bean 的循环依赖;并不能解决循环依赖,原因是:prototype 是多例的存在,多个 Bean 对象,不是唯一的一个Bean,无法确定是具体是哪个,Bean无法提前曝光。

BeanCreationException 报错:当前的Bean正在处于创建中异常

特别的:当两个bean的scope都是prototype的时候,才会出现异常,如果其中任意一个是singleton的,就不会出现异常了。是其中的任意一个 就行,就不会出现异常了。如果是三个 bean 的话,那就需要其中的任意两个 是为singleton才行。

原因是:singleton 优先被“曝光”,实例化和赋值是分开的,会优先把实例化的对象的地址曝光出来,因为在 singleton 单例模式下,bean 是唯一的一个,独一无二的,并且早晚都要进行赋值操作。提前曝光,后面再进行赋值也是无妨的。因为你弄来弄去,就是那唯一的一个 bean。不存在多个,不知道是哪一个的问题。

测试:当两个bean的scope都是prototype的时候,才会出现异常,如果其中任意一个是singleton的,就不会出现异常了。

Husband 为 prototype ,Wife 为 singleten

在这里插入图片描述
反一下:Husband 为 singleten ,Wife 为 prototype

在这里插入图片描述

至于,三个 Bean ,需要任意两个为 singleten ,才不会报异常,就大家自行测试了。理论上就是:n 个 就需要 N-1个为 singleten 。

1.4 singleton下的构造注入产生的循环依赖

如果是基于构造注入(进行赋值),很明显,要调用构造方法进行赋值就一定要完完整整的进行一次性赋值+实例化,没有分段的,所以会产生循环依赖并且无法解决的,
所以编写代码时一定要注意。同样是报: BeanCreationException 报错:当前的Bean正在处于创建中异常

我们来测试一下。

在这里插入图片描述

1.5 Spring 解决循环依赖的原理(源码解析)

Spring 为什么可以解决 set+sigleton 模式下循环依赖呢?

根本原因在于:这种方式可以做到将 “实例化 Bean” 和“给 Bean 属性赋值” 这两个动作分开去完成。实例化Bean的时候:调用无参数构造方法来完成此时可以先不给属性赋值(因为在 singleton 单例模式下,bean 是唯一的一个,独一无二的,并且早晚都要进行赋值操作。提前曝光,后面再进行赋值也是无妨的。因为你弄来弄去,就是那唯一的一个 bean),可以提前将Bean 对象“曝光”给外界

给Bean 属性赋值的时候:调用 setter()方法来完成(set注入完成,调用其中 bean对象当中的 set()方法,所以千万要记得写 set()方法)。

两个步骤是完全可以分离去完成的,并且这两步不要求在同一个时间点上完成。

也就是说,Bean 都是单例的,我们可以先把所有的单例 Bean 实例化出来,放到一个集合当中(我们可以将其称之为缓存),所有的单例 Bean 全部实例化完成之后,以后我们再慢慢的调用 setter()方法给属性赋值,这样就解决了循环依赖的问题。

那么在 Spring 框架底层源码级别上是如何实现的呢?如下:

我们先来分析一下:AbstractAutowireCapableBeanFactory类下的doCreateBean() 方法

在这里插入图片描述
doCreateBean() 方法 下调用的:addSingletonFactory() 方法,这里源码上使用了正则表达式,关于Lambda 表达式,由于设置的内容较多,想要了解更多的,大家可以移步至✏️✏️✏️ 函数式编程:Lambda 表达式_(ws, bs)>-CSDN博客

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

在这里插入图片描述

下面这个DefaultSingletonBeanRegistry类,才是我们真正要探究的源码内容

在这里插入图片描述
在这个DefaultSingletonBeanRegistry 类当中中包含三个重要的属性同时也是三个Map集合:

在这里插入图片描述

	/** Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name to ObjectFactory. */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

这三个缓存其实本质上是三个Map集合。

  • Cache of singleton objects: bean name to bean instance. 单例对象的缓存:key存储bean名称,value存储Bean对象【一级缓存】
  • Cache of early singleton objects: bean name to bean instance. 早期单例对象的缓存:key存储bean名称,value存储早期的Bean对象【二级缓存】
  • Cache of singleton factories: bean name to ObjectFactory.单例工厂缓存:key存储bean名称,value存储该Bean对应的ObjectFactory对象【三级缓存】
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); 一级缓存
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16); 二级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); 三级缓存
这个三个缓存都是Map集合
Map集合的key 存储的都是bean的name(bean id)
> 一级缓存存储的是:单例Bean对象,完整的单例Bean对象,也就是这个缓存中的Bean对象的属性都已经赋值了,是一个完整的Bean对象
> 二级缓存存储的是: 早期的案例Bean对象,这个缓存中的单例Bean对象的属性灭有赋值,只是一个早期的实例对象
> 三级缓存存储的是: 单例工厂对象,这个里面存储了大力的“工厂对象”,每一个单例Bean对象都会对应一个单例工厂对象。
> 这个集合中存储的是,创建该单例对象时对应的那个单例工厂对象。    

我们再来看,在该类中有这样一个方法 addSingletonFactory(),这个方法的作用是:将创建Bean对象的ObjectFactory对象提前曝光。这里我们Debug 调试看看。

在这里插入图片描述

在这里插入图片描述
再分析对应下面的源码:

在这里插入图片描述

在这里插入图片描述
从源码中可以看到:spring 会先从一级缓存中获取Bean 对象,如果获取不到,则再从二级缓存当中获取 Bean 对象,如果二级缓存还是获取不到,则最后从三级缓存当中获取之前曝光的ObjectFactory 对象,通过ObjectFactory 对象获取到对应 Bean 实例,这样就解决了循环依赖的问题。

总结:

Spring只能解决setter方法注入的单例bean之间的循环依赖。ClassA依赖ClassB,ClassB又依赖ClassA,形成依赖闭环。Spring在创建ClassA对象后,不需要等给属性赋值,直接将其曝光到bean缓存当中。在解析ClassA的属性时,又发现依赖于ClassB,再次去获取ClassB,当解析ClassB的属性时,又发现需要ClassA的属性,但此时的ClassA已经被提前曝光加入了正在创建的bean的缓存中,则无需创建新的的ClassA的实例,直接从缓存中获取即可。从而解决循环依赖问题。

2. 总结:

  1. Bean的循环依赖:A对象中有B属性。B对象中有A属性。这就是循环依赖。我依赖你,你也依赖我。

  2. singletion 下的 set 注入下的 Bean 的循环依赖能够被解决。主要原因是:在这个 singleton 单例模式下,在Spring 容器中的 bean 对象是独一无二的对象,是唯一的一个。同志在该 singleton 单例模式下:Spring 对 Bean 的管理主要分为清晰的两个阶段

    1. 第一个阶段:在Spring 容器加载的时候,实例Bean ,只要其中任意一个 Bean 实例化之后,马上进行一个==“曝光”== (注意:曝光不等于属性赋值,曝光了,但是属性并没有附上值的)
    2. 第二个阶段:Bean ==“曝光”==之后,再进行属性的赋值操作(调用 set()方法实现对属性的赋值操作)

    核心解决方案是:实例化对象和对象的属性赋值分为两个阶段来完成,并不是一次性完成的。

  3. prototype下的 set 注入下的 Bean 的循环依赖;并不能解决循环依赖,原因是:prototype 是多例的存在,多个 Bean 对象,不是唯一的一个Bean,无法确定是具体是哪个,Bean无法提前曝光。

  4. 特别的:当两个bean的scope都是prototype的时候,才会出现异常,如果其中任意一个是singleton的,就不会出现异常了。是其中的任意一个 就行,就不会出现异常了。如果是三个 bean 的话,那就需要其中的任意两个 是为singleton才行。

    1. 至于,三个 Bean ,需要任意两个为 singleten ,才不会报异常,就大家自行测试了。理论上就是:n 个 就需要 N-1个为 singleten 。
    2. 注意报错信息:org.springframework.beans.factory.BeanCreationException: 当前的Bean正在处于创建中异常
  5. singleton下的构造注入产生的循环依赖;是基于构造注入(进行赋值),很明显,要调用构造方法进行赋值就一定要完完整整的进行一次性赋值+实例化,没有分段的,所以会产生循环依赖并且无法解决的,

  6. Spring 解决循环依赖的原理(源码解析):一级缓存,二级缓存,三级缓存的存在。提前“曝光”机制

3. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MouseBoost PRO for Mac激活版:强大的 鼠标增强软件

在追求高效工作的今天&#xff0c;MouseBoost PRO for Mac成为了许多Mac用户的得力助手。这款功能强大的鼠标增强软件&#xff0c;以其独特的智能化功能和丰富的实用工具&#xff0c;让您的电脑操作更加便捷、高效。 MouseBoost PRO for Macv3.4.0中文激活版下载 MouseBoost PR…

Hotcoin Research | 市场洞察:2024年4月22日-28日

加密货币市场表现 本周内加密大盘整体呈现出复苏状态&#xff0c;在BTC减半后进入到震荡上行周期。BTC在$62000-66000徘徊&#xff0c;ETH在$3100-3300徘徊&#xff0c;随着港交所将于 4 月 30 日开始交易嘉实基金的比特币和以太坊现货 ETF&#xff0c;周末行情有一波小的拉升…

帮助 Python 用户构建 CLI 界面:直观易写、简单高效 | 开源日报 No.240

tiangolo/typer Stars: 13.7k License: MIT typer 是一个构建出色命令行界面&#xff08;CLI&#xff09;的库&#xff0c;基于 Python 类型提示。它旨在让开发者轻松创建用户喜欢使用的 CLI 应用程序。其主要功能和核心优势包括&#xff1a; 直观易写&#xff1a;强大编辑器…

vue3 jspdf,element table 导出excel、pdf,横板竖版分页

多个表格需要&#xff0c;pdf需要的格式与原本展示的表格样式不同 1.创建一个新的表格&#xff0c;设置pdf需要的样式&#xff0c;用vue的h函数放入dom中 2.excel用xlxs插件直接传入新建el-table的dom,直接导出 3.pdf导出类似excel黑色边框白底黑字的文件&#xff0c;把el-t…

FFmpeg开发笔记(二十三)使用OBS Studio开启RTMP直播推流

OBS是一个开源的直播录制软件&#xff0c;英文全称叫做Open Broadcaster Software&#xff0c;广泛用于视频录制、实时直播等领域。OBS不但开源&#xff0c;而且跨平台&#xff0c;兼容Windows、Mac OS、Linux等操作系统。 OBS的官网是https://obsproject.com/&#xff0c;录制…

STM32利用硬件I2C读取MPU6050陀螺仪数据

有了前面的基本配置&#xff0c;这节读取MPU6050的数据还算是简单&#xff0c;主要就是初始化时给MPU6050一些配置&#xff0c;取消睡眠模式&#xff0c;MPU6050开机是默认睡眠模式的&#xff0c;读写无效&#xff0c;所以上来就要先更改配置&#xff1a; MPU6050寄存器初始化…

mongodb卸载(win)

关闭服务 &#xff08;或者cmd卸载服务&#xff1a;&#xff09; net stop 服务名称卸载应用 至此&#xff0c;卸载完成&#xff01;

微隔离实施五步法,让安全防护转起来

前言 零信任的最核心原则→最小权限 安全的第一性原理→预防 零信任的最佳实践→微隔离 “零信任”这个术语的正式出现&#xff0c;公认是在2010年由Forrester分析师John Kindervag最早提出。时至今日&#xff0c;“零信任”俨然已成安全领域最热门的词汇&#xff0c;做安全…

实验报告5-Spring MVC实现页面

实验报告5-SpringMVC实现页面 一、需求分析 使用Spring MVC框架&#xff0c;从视图、控制器和模型三方面实验动态页面。模拟实现用户登录&#xff0c;模拟的用户名密码以模型属性方式存放在Spring容器中&#xff0c;控制器相应用户请求并映射参数&#xff0c;页面收集用户数据或…

设计模式-01 设计模式单例模式

设计模式-01 设计模式单例模式 目录 设计模式-01 设计模式单例模式 1定义 2.内涵 3.使用示例 4.具体代码使用实践 5.注意事项 6.最佳实践 7.总结 1 定义 单例模式是一种设计模式&#xff0c;它确保一个类只能被实例化一次。它通过在类内部创建类的唯一实例并提供一个全…

uniapp + uView动态表单校验

项目需求&#xff1a;动态循环表单&#xff0c;并实现动态表单校验 页面&#xff1a; <u--form label-position"top" :model"tmForm" ref"tmForm" label-width"0px" :rulesrules><div v-for"(element, index) in tmForm…

(详细整理!!!!)Tensorflow与Keras、Python版本对应关系!!!

小伙伴们大家好&#xff0c;不知道大家有没有被tensorflow框架困扰过 今天我就给大家整理一下tensorflow和keras、python版本的对应关系 大家这些都可以在官网找到&#xff0c;下面我把官网的连接给大家放在这里&#xff1a;在 Windows 环境中从源代码构建 | TensorFlow (g…

搭建大型分布式服务(三十七)SpringBoot 整合多个kafka数据源-取消限定符

系列文章目录 文章目录 系列文章目录前言一、本文要点二、开发环境三、原项目四、修改项目五、测试一下五、小结 前言 本插件稳定运行上百个kafka项目&#xff0c;每天处理上亿级的数据的精简小插件&#xff0c;快速上手。 <dependency><groupId>io.github.vipjo…

基于 React 的图形验证码插件

react-captcha-code NPM 地址 &#xff1a; react-captcha-code - npm npm install react-captcha-code --save 如下我自己的封装&#xff1a; import Captcha from "react-captcha-code";type CaptchaType {captchaChange: (captchaInfo: string) > void;code…

前端发起网络请求的几种常见方式(XMLHttpRequest、FetchApi、jQueryAjax、Axios)

摘要 前端发起网络请求的几种常见方式包括&#xff1a; XMLHttpRequest (XHR)&#xff1a; 这是最传统和最常见的方式之一。它允许客户端与服务器进行异步通信。XHR API 提供了一个在后台发送 HTTP 请求和接收响应的机制&#xff0c;使得页面能够在不刷新的情况下更新部分内容…

Flutter笔记:Widgets Easier组件库(2)阴影盒子

Flutter笔记 Widgets Easier组件库&#xff08;2&#xff09;&#xff1a;阴影盒子 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress o…

Python中的动态数据可视化Bokeh库实战

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 Python 中的动态数据可视化Bokeh库实战 在数据科学和可视化领域&#xff0c;动态数据可视化…

windows下安装onlyoffice

文章目录 1、 安装ErLang2、 安装rabbitmq3、 安装postgresql4、 安装onlyoffice(社区版) 1、 安装ErLang 下载地址&#xff1a;https://erlang.org/download/otp_win64_24.2.exe opt_wind64_24.2.exe 直接运行&#xff0c;一步一步安装 2、 安装rabbitmq 下载地址&#xf…

【笔记】Simulink与Workbench交互+自定义m函数封装为Simulink模块

以如下三角函数为例&#xff0c;说明建模方法 ya*sin(b*2*pi*uc);0.总模型总代码 总模型 总代码&#xff1a; clc clear close allt_all10; a10; b1; c0;%pi/2; delta_t0.01; simOutsim(test240430); out_tsimOut.tout; out_y1simOut.yout{1}.Values; out_y2simOut.yout{2}.…

C++-10

1.C一个程序&#xff0c;实现两个类&#xff0c;分别存放输入的字符串中的数字和字母&#xff0c;并按各自的顺序排列&#xff0c; 类中实现-一个dump函数&#xff0c;调C用后输出类中当前存放的字符串结果。 例如&#xff0c;输入1u4y2a3d,输出:存放字母的类&#xff0c;输出a…