Spring ⑦ 循环引用问题

news2025/2/28 12:00:39

spring-logo-0.jpg

Spring ⑦ 循环引用问题

Spring 源码系列文章会遵循由浅入深,由易到难,由宏观到微观的原则,目标是尽量降低学习难度,而不是一上来就迷失在源码当中. 文章会从一个场景作为出发点,针对性的目的性极强的针对该场景对 Spring 的实现原理,源码进行探究学习。该系列文章会让你收获什么? 从对 Spring 的使用者成为 Spring 专家。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。

Bean 的实例化初始化顺序

场景
public class CircularReferenceExp1 {

    public static void main(String[] args) {

        // 循环引用实验

        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(factory);
        factory.addBeanPostProcessor(processor);

        factory.registerBeanDefinition("bean1" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean1.class)
                .getBeanDefinition());

        factory.registerBeanDefinition("bean2" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean2.class)
                .getBeanDefinition());

        factory.registerBeanDefinition("bean3" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean3.class)
                .getBeanDefinition());

        Bean3 bean3 = factory.getBean(Bean3.class);
        System.out.println("bean1 -> " + bean3);
    }

    static class Bean1 {

        @Autowired
        Bean3 bean3;

        public Bean1() {
            System.out.println("======================== bean1 实例化");
        }

    }

    static class Bean2 {

        @Autowired
        Bean1 bean1;

        public Bean2() {
            System.out.println("++++++++++++++++++++++++++ bean2 实例化");
        }
    }

    static class Bean3 {

        @Autowired
        Bean2 bean2;

        public Bean3() {
            System.out.println("++++++++++++++++++++++++++ Bean3 实例化");
        }
    }
}
运行日志输出:
20:56:41.417 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean3'
++++++++++++++++++++++++++ Bean3 实例化
20:56:41.476 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean2'
++++++++++++++++++++++++++ bean2 实例化
20:56:41.477 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean1'
======================== bean1 实例化
bean1 -> org.devx.spring.certified.professional.edu.hp.experiment.CircularReferenceExp1$Bean3@22635ba0

spring 在创建 Bean 的过程中是从外到内的去创建 Bean 。在解析 Bean 中依赖项的时候便会去实例化该依赖项对应的 Bean 并完成 spring 对 Bean 的初始化发布过程。

image.png

构造器依赖注入时循环引用

先说结论构造器依赖注入时存在循环引用的情况下会导致 Bean 创建失败抛出异常. 要想知道原因只要理解了构造器依赖注入与属性、方法依赖注入的区别是什么就很容易理解了。构造器依赖注入时需要先找到依赖项才能实例化当前 Bean ,属性和方法依赖注入时是先实例化当前 Bean 再去寻找依赖项实例。

image.png

场景
public class CircularReferenceExp2 {

    public static void main(String[] args) {

        // 循环引用实验

        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(factory);
        factory.addBeanPostProcessor(processor);

        factory.registerBeanDefinition("bean1" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean1.class)
                .getBeanDefinition());

        factory.registerBeanDefinition("bean2" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean2.class)
                .getBeanDefinition());


        Bean1 bean1 = factory.getBean(Bean1.class);
        System.out.println("bean1 -> " + bean1);
    }

    static class Bean1 {

        final Bean2 bean2;

        public Bean1(Bean2 bean2) {
            this.bean2 = bean2;
            System.out.println("======================== bean1 实例化 , bean2 is = " + bean2);
        }

    }

    static class Bean2 {

        final Bean1 bean1;

        public Bean2(Bean1 bean1) {
            this.bean1 = bean1;
            System.out.println("++++++++++++++++++++++++++ bean2 实例化 , bean1 is = " + bean1);
        }
    }

}

观察输出的日志发现,输出了两次 Creating shared instance of singleton bean 'bean1' , 在创建 bean2 的过程中因为工厂内还没有 bean1 所以又去创建了一次. 在第二次创建 bean1 的过程中, spring 发现 bean1 其实正在被创建的过程中(首次创建 bean1 的过程), 所以 spring 抛出了 BeanCurrentlyInCreationException 异常。 假设如果 spring 允许第二次创建 bean1 成功的话, 那么首次创建 bean1 的过程也可以成功.这样工厂中就会存在两个 bean1 实例,或者是只存在一个其中一个被覆盖,那么 bean2 中究竟应该持有那个 bean1 的实例呢?问题变得更为复杂了.

image.png

运行日志输出:
21:23:06.516 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean1'
21:26:01.837 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean2'
21:29:03.383 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean1'
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bean1': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bean2': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'bean1': Requested bean is currently in creation: Is there an unresolvable circular reference?
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:233)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1282)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1243)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:494)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
	at org.devx.spring.certified.professional.edu.hp.experiment.CircularReferenceExp2.main(CircularReferenceExp2.java:32)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bean2': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'bean1': Requested bean is currently in creation: Is there an unresolvable circular reference?
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1389)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1309)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
	... 15 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'bean1': Requested bean is currently in creation: Is there an unresolvable circular reference?
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:355)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:227)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1389)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1309)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
	... 29 more

属性方法依赖注入时循环引用

在前面内容中已经介绍了属性、方法注入与构造器注入时循环引用问题的区别,接下来重点讲解在属性、方法注入时 spring 如何处理循环引用问题。

场景
public class CircularReferenceExp3 {

    public static void main(String[] args) {

        // 循环引用实验
        
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        Logger logger = loggerContext.getLogger(DefaultListableBeanFactory.class);
        logger.setLevel(Level.TRACE);

        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(factory);
        factory.addBeanPostProcessor(processor);

        factory.registerBeanDefinition("bean1" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean1.class)
                .getBeanDefinition());

        factory.registerBeanDefinition("bean2" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean2.class)
                .getBeanDefinition());


        Bean1 bean1 = factory.getBean(Bean1.class);
        System.out.println("bean1 -> " + bean1);
    }

    static class Bean1 {

        @Autowired
        Bean2 bean2;

        public Bean1() {
            System.out.println("======================== bean1 实例化 ");
        }

    }

    static class Bean2 {

        @Autowired
        Bean1 bean1;

        public Bean2() {
            System.out.println("++++++++++++++++++++++++++ bean2 实例化 ");
        }
    }

}
运行日志输出:

从输入的日志中可以观察到在创建了实列对象 ( Creating shared instance ) 后,该实例就被添加到了缓存当中 ( Eagerly caching bean ) . 目的就是为了解决可能存在的循环引用场景。而 bean2 在注入 bena1 的时候获取的 bean1 是从缓存中获取的实例对象 ( Returning eagerly cached instance of singleton bean ).

17:34:34.328 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean1'
17:34:34.332 [main] TRACE org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'bean1'
======================== bean1 实例化 
17:34:34.385 [main] TRACE org.springframework.beans.factory.support.DefaultListableBeanFactory - Eagerly caching bean 'bean1' to allow for resolving potential circular references
17:34:34.390 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean2'
17:34:34.390 [main] TRACE org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'bean2'
++++++++++++++++++++++++++ bean2 实例化 
17:34:34.391 [main] TRACE org.springframework.beans.factory.support.DefaultListableBeanFactory - Eagerly caching bean 'bean2' to allow for resolving potential circular references
17:34:34.391 [main] TRACE org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning eagerly cached instance of singleton bean 'bean1' that is not fully initialized yet - a consequence of a circular reference
17:34:34.393 [main] TRACE org.springframework.beans.factory.support.DefaultListableBeanFactory - Finished creating instance of bean 'bean2'
17:34:34.393 [main] TRACE org.springframework.beans.factory.support.DefaultListableBeanFactory - Finished creating instance of bean 'bean1'
bean1 -> org.devx.spring.certified.professional.edu.hp.experiment.CircularReferenceExp3$Bean1@22635ba0

从图中分析出在循环引用时注入的依赖 bean 是刚刚完成创建过程的 bean 并没有完成整体的初始化过程.因为在没有执行 populateBean 方法和 initializeBean 就被放入了 singletonFactories 缓存当中.也就是说这时候注入的 bean 实例并没有经过 BeanPostProcessor 的处理, 也没有执行 InitializingBean afterPropertiesSet 方法. 其实这时候被放入 singletonFactories 缓存中的是一个 ObjectFactory 的匿名内部类其中指向了 AbstractAutowireCapableBeanFactory#etEarlyBeanReference 方法。其中会去调用 SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference 方法, 比如 AnnotationAwareAspectJAutoProxyCreator 就保证了我们获取到的是一个代理对象。下面会附上一些关键部分源码帮助读者理解图示.

属性和方法注入循环引用.drawio.png

getSingleton
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   // Quick check for existing instance without full singleton lock
   Object singletonObject = this.singletonObjects.get(beanName);
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      singletonObject = this.earlySingletonObjects.get(beanName);
      if (singletonObject == null && allowEarlyReference) {
         synchronized (this.singletonObjects) {
            // Consistent creation of early reference within full singleton lock
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               singletonObject = this.earlySingletonObjects.get(beanName);
               if (singletonObject == null) {
                  ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                  if (singletonFactory != null) {
                     singletonObject = singletonFactory.getObject();
                     this.earlySingletonObjects.put(beanName, singletonObject);
                     this.singletonFactories.remove(beanName);
                  }
               }
            }
         }
      }
   }
   return singletonObject;
}
doCreateBean

image.png

addSingletonFactory
/**
 * Add the given singleton factory for building the specified singleton
 * if necessary.
 * <p>To be called for eager registration of singletons, e.g. to be able to
 * resolve circular references.
 * @param beanName the name of the bean
 * @param singletonFactory the factory for the singleton object
 */
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(singletonFactory, "Singleton factory must not be null");
   synchronized (this.singletonObjects) {
      if (!this.singletonObjects.containsKey(beanName)) {
         this.singletonFactories.put(beanName, singletonFactory);
         this.earlySingletonObjects.remove(beanName);
         this.registeredSingletons.add(beanName);
      }
   }
}
getEarlyBeanReference
/**
 * Obtain a reference for early access to the specified bean,
 * typically for the purpose of resolving a circular reference.
 * @param beanName the name of the bean (for error handling purposes)
 * @param mbd the merged bean definition for the bean
 * @param bean the raw bean instance
 * @return the object to expose as bean reference
 */
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
   Object exposedObject = bean;
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
         exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
      }
   }
   return exposedObject;
}
addSingleton

在 bean 完成了整个创建和初始化过程后 , bean 会被加入到 singletonObjects 缓存中,并从 singletonFactories earlySingletonObjects 缓存中清除.

/**
 * Add the given singleton object to the singleton cache of this factory.
 * <p>To be called for eager registration of singletons.
 * @param beanName the name of the bean
 * @param singletonObject the singleton object
 */
protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
      this.singletonObjects.put(beanName, singletonObject);
      this.singletonFactories.remove(beanName);
      this.earlySingletonObjects.remove(beanName);
      this.registeredSingletons.add(beanName);
   }
}

到这里 spring 是如何处理循环引用的原理我们就讲完了,接下来看如果在使用过程中出现了循环引用该如何解决. (最好的办法就是不要循环引用,这个就涉及到项目结构设计,编码规范等等方面,这里并不展开。).

解决循环引用

解决循环引用的思路是 延迟加载 让 bean 在真正被使用时再去加载,这样做的缺点是会有一点性能损耗一般情况下可以忽略不计. 可以通过使用 @Lazy 注解的方式或者注入 ObjectFactory ObjectProvider jsr-330 Provider 的方式实现懒加载.

属性和方法注入循环引用.drawio (1).png

总结

本章讲解了 构造器依赖注入时循环引用 属性方法依赖注入时循环引用 的场景。在构造器注入时得到的依赖项是经过了完整的初始化过程的,可以说是得到的一个完整的 bean 。而属性或方法注入的场景得到的 bean 是没有经过完全初始化的,所以在使用 bean 时需要警惕.

抱歉最近没有更新因为我在追剧,我最近在考虑要不要转行卖鱼了 : )

image.png


DevX 会持续分享 Java 技术干货,如果你觉得本文对你有帮助希望你可以分享给更多的朋友看到。该文章会同步在微信公众号 【 DevXJava 】, 方便在微信客户端阅读。

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

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

相关文章

时间轮(TimingWheel)

一、什么是时间轮时间轮其实就是一种环形的数据结构&#xff0c;可以想象成时钟&#xff0c;分成很多格子&#xff0c;一个格子代表一段时间&#xff08;这个时间越短&#xff0c;Timer的精度越高&#xff09;。并用一个双向链表存储放在该格子上的延时任务&#xff0c;同时一个…

下一个排列-力扣31-java

一、题目描述整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。例如&#xff0c;arr [1,2,3] &#xff0c;以下这些都可以视作 arr 的排列&#xff1a;[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地&…

记一次20撸240的沙雕威胁情报提交(2019年老文)

0x01 起因 这是一篇沙雕文章&#xff0c;没什么技术含量&#xff0c;大家娱乐一下就好 前几个月&#xff0c;我的弟弟突然QQ给我发来了一条消息&#xff0c;说要买个QQ飞车的cdk&#xff0c;我作为一个通情达理的好哥哥&#xff0c;自然不好意思回绝&#xff0c;直接叫他发来…

跟着团子学SAP PSS: 如何实现物质在不同法规下的准入管理(配置篇)

全球各地针对化学品的监管出台了很多法规&#xff0c;有相当一部分的法规都是输入准入制&#xff1a;只有在法规中列示的化学物质在当地才具有适销性&#xff0c;未列示的物质只有在一些特殊条件下才能销售。加拿大的DSL&#xff08;加拿大本国物质清单&#xff09;&#xff0c…

【Python入门第九天】Python 字符串

字符串字面量 python 中的字符串字面量由单引号或双引号括起。 ‘hello’ 等同于 “hello”。 可以使用 print() 函数显示字符串字面量&#xff1a; 实例 print("Hello") print(Hello)运行实例 用字符串向变量赋值 通过使用变量名称后跟等号和字符串&#xff0…

yolov3-tiny模型转trt的一个实例

感谢作者分享&#xff0c;仓库地址&#xff1a;https://github.com/zombie0117/yolov3-tiny-onnx-TensorRT?tdsourcetags_pcqq_aiomsg该仓库的代码没有使用现有的神经网络框架&#xff0c;如pytorch&#xff0c;tensorflow等&#xff0c;因此环境搭建相对比较容易。仓库作者是…

Docker逃逸

文章目录原理环境搭建Docker 环境判断Docker 容器逃逸特权模式逃逸如何判断是否为特权模式逃逸docker.sock挂载逃逸逃逸Remote API未授权访问未授权访问逃逸容器服务缺陷逃逸影响版本环境搭建逃逸脏牛漏洞逃逸参考原理 docker其实就是一个linux下的进程&#xff0c;它通过Name…

RV1126笔记二十八:RKNN上部署OCR测试

若该文为原创文章,转载请注明原文出处。 本篇文章只是记录下测试OCR的效果,想了解全过程,参考: 【工程部署】手把手教你在RKNN上部署OCR服务(上)_opencv rknn_ocr_三叔家的猫的博客-CSDN博客 【工程部署】手把手教你在RKNN上部署OCR服务(下)_三叔家的猫的博客-CSDN博…

ROS2中使用gazebo仿真时找不到libgazebo_ros_openni_kinect.so

因为ros2的gazebo_ros_pkgs中&#xff0c;已经将该插件移除&#xff0c;或者说将该插件的功能合并到libgazebo_ros_camera.so中&#xff0c; 这里是作者的说明。 合并后&#xff0c;深度相机的用法参考这里。 主要是将type改成depth。还有其他类型的相机&#xff0c;可以参考具…

如何优雅的实现回调函数?

本篇文章又是一期优雅的代码编程介绍———回调函数。 传统的nodejs编程都是这样的 const fs require(fs) fs.readFile(test.txt,utf8, function(err, dataStr){if(err){} }) 嵌套层级如果多了就成回调地狱了。如果我们将这种风格的代码转换成这样呢&#xff1f; const fs …

Word论文排版(1)样式设定

前言&#xff1a;现在很多学校都有 LaTeX 模板了&#xff0c;但是也有很多渣渣学校/学院没提供&#xff0c;而且要求必须提供 Word 版本的大论文&#xff01;那就只能从 Word 下手了。 Requirements Windows11、Word2016 样式设定 为什么要设置&#xff1a;和 LaTeX 一样&am…

MobaXterm详细使用教程

这一篇MobaXterm详细使用教程&#xff0c;我们来介绍一下如何设置并用MobaXterm来连接Linux服务器。MobaXterm 又名 MobaXVT&#xff0c;是一款增强型终端、X 服务器和 Unix 命令集(GNU/ Cygwin)工具箱。MobaXterm 可以开启多个终端视窗&#xff0c;以最新的 X 服务器为基础的 …

【笔试强训】Day_01

目录 一、选择题 1、 2、 3、 4、 5、 6、 7、 8、 9、 10、 二、编程题 1、组队竞赛 2、删除公共字符 一、选择题 1、 以下for循环的执行次数是&#xff08;&#xff09; for(int x 0, y 0; (y 123) && (x < 4); x); A 、是无限循环 B 、循环次…

从零开始学C

以下是 该如何学习C语言的【思维导图】以及部分重点知识点的【博客链接】。其实C语言并不难&#xff0c;难的是没有人去教&#xff0c;没有耐心去学。不知道从哪下手学习&#xff0c;我将C的知识点做成一个思维导图&#xff0c;以供迷茫的小白参考&#xff0c;哪里不会&#xf…

快速且有效减小代码包的方法

前言当我们在发布一些APP或者小程序等比较小的程序时候&#xff0c;常常会对其主包大小进行一定的规定&#xff0c;若超过推荐的主包大小则性能会被大大影响&#xff0c;或者再严重一点就不给你过审。如微信小程序中也对主包有一定的大小要求。对此一些比较复杂的小程序就需要考…

【机器学习】P1 Cost Function

Cost Functione.g.e.g.e.g. 假设你想要卖一个房子&#xff0c;希望可以用人工智能来算出能卖多少钱。机器学习可以根据提供的数据集合构建出很多模型&#xff0c;但是到底哪种模型最好的拟合你的数据&#xff1f;或者说&#xff0c;哪种模型可以最准确的算出你的卖多少钱&#…

TikTok曝高危漏洞允许一键式帐户劫持,回应称已修复

据The Verge 8月31日消息&#xff0c; TikTok安卓版存在一个高危漏洞&#xff0c;攻击者可能借此实现一键式账户劫持&#xff0c;影响数亿用户 。 微软365防御研究小组在一篇博文中披露了该漏洞的细节&#xff0c; 影响范围为23.7.3之前的安卓版本 。在微软向TikTok报告后&…

如何用 JavaScript 编写你的第一个单元测试

前言 测试代码是使代码安全的第一步。做到这一点的最好方法之一是使用单元测试&#xff0c;确保应用程序中的每个小功能都能发挥其应有的作用–特别是当应用程序处于边缘情况&#xff0c;比如无效的输入&#xff0c;或有潜在危害的输入。 为什么要单元测试 说到单元测试&…

测试开发之Django实战示例 第十章 创建在线教育平台

第十章 创建在线教育平台在上一章&#xff0c;我们为电商网站项目添加了国际化功能&#xff0c;还创建了优惠码和商品推荐系统。在本章&#xff0c;会建立一个新的项目&#xff1a;一个在线教育平台&#xff0c;并创内容管理系统CMS&#xff08;Content Management System&…

OSI模型详解

今天&#xff0c;我们详解OSI&#xff08;Open System Inter-connection Reference Model&#xff09;模型&#xff0c;来看看工业物联网的网络互联和数据互通。 OSI模型 1984年&#xff0c;国际标准化组织&#xff08;International Organization for Standardization&#…