Spring Bean循环依赖问题及解决
什么是循环依赖
类与类之间的依赖关系形成了闭环,就会导致循环依赖问题的产生。举例来说,假设存在两个服务类A和服务类B,如果A通过依赖注入的方式引用了B,且B通过依赖注入的方式引用了A,那么A和B之间就存在循环依赖。
推广来说,如果涉及多个类,也存在这种依赖关系,那么也是循环依赖问题。
循环依赖问题比较严重,有时会影响服务启动,有时会导致死循环调用(如果线上环境出现循环调用,会导致程序进入死循环,然后服务崩溃,进而导致用户请求无法响应,造成生产事故),应引起足够的重视。
循环依赖的处理现状
Spring 支持解决循环依赖,但是仅能支持特定的场景,对于不支持的场景,会在启动时报错。Spring 提供的能力后面会详细重点说明下,在Spring Boot 2.6.0版本开始,默认禁用对循环依赖的支持。也就是说,Spring Boot 2.6.0版本及之后版本,如果存在循环依赖,不管是何种场景,都会报启动错误。启动报错关键信息如下:
Description:The dependencies of some of the beans in the application context form a cycle:┌─────┐
| a (field private com.github.courage007.springbootstarter.service.B com.github.courage007.springbootstarter.service.A.b)
↑ ↓
| b (field private com.github.courage007.springbootstarter.service.A com.github.courage007.springbootstarter.service.B.a)
└─────┘Action:Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
总结来说,Spring 支持一定程度的循环依赖的解决,但是在2.6.0版本及之后的版本,默认禁用该功能。也就是说,Spring Boot 2.6.0版本及之后版本,如果存在循环依赖,不管是何种场景,都会报启动错误。
那么Spring 都支持哪些循环依赖的场景呢,后续如果出现循环依赖问题,又该如何解决呢?接下来详细介绍这些内容。
Spring IoC简介
在正式介绍 Spring 如何解决 Bean 的循环依赖问题前,先简要介绍下Spring 如何实现Bean的注入。Spring使用IoC技术实现Bean的注入,在具体策略上采用了依赖注入的方式。在Spring中支持的依赖注入实现主要有三种:构造器注入、setter方法注入(也称属性注入)、接口注入等。相对于前两种注入方式,接口注入比繁琐和死板,被注入对象必须声明和实现另外的接口,所以常用的Bean注入方式主要有两种:构造器注入和setter方法注入。
Spring 如何解决循环依赖
根据依赖注入的方式不同,可以将循环依赖的场景进行以下划分:
依赖注入 | A构造器注入 | A属性注入 |
---|---|---|
B构造器注入 | 启动报错,Spring无法自动解决,需要手动解决 | 启动成功,Spring可以自动解决 |
B属性注入 | 启动成功,Spring可以自动解决 | 启动成功,Spring可以自动解决 |
A构造器注入B,B构造器注入A
针对A构造器注入B,B构造器注入A的情况,Spring 无法解决这种循环依赖问题,启动时就会报错,报错内容如下:
***************************
APPLICATION FAILED TO START
***************************Description:The dependencies of some of the beans in the application context form a cycle:┌─────┐
| a defined in file [/spring-boot-example/spring-boot-web-starter/target/classes/com/github/courage007/springbootwebstarter/resource/A.class]
↑ ↓
| b defined in file [/spring-boot-example/spring-boot-web-starter/target/classes/com/github/courage007/springbootwebstarter/resource/B.class]
因为这种循环依赖在启动时就会被发现,所以不会带入到线上环境,影响可控,但错误比较低级。
A构造器注入B,B属性注入A
针对A构造器注入B,B构造器注入A的情况,Spring 可以解决这种循环依赖问题,不会影响Spring应用的启动。示例代码如下:
@Service
public class A {private B b;public A(B a) {this.b = b;}public void test() {System.out.println("A");}
}@Service
public class B {@Autowiredprivate A a;public void test() {System.out.println("B");}
}
虽然Spring可以解决这种循环依赖问题,但是却无法解决方法之间的循环调用,如果同时存在相互调用,则会导致实例不断的被初始化,从而导致栈溢出。示例代码如下:
@Service
public class A {private B b;public A(B a) {this.b = b;}public void test() {System.out.println("A");b.test();}
}@Service
public class B {@Autowiredprivate A a;public void test() {System.out.println("B");a.test();}
}
如果客户端调用了实例A的test方法或实例B的test方法,那么将会触发循环调用,进而导致服务崩溃。异常堆栈示例如下:
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at ./open/src/java.instrument/share/native/libinstrument/JPLISAgent.c line: 872
2023-11-10 16:46:03.497 ERROR 13643 --- [nio-8082-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.StackOverflowError] with root causejava.lang.StackOverflowError: nullat java.base/java.nio.ByteBuffer.position(ByteBuffer.java:1158) ~[na:na]at java.base/java.nio.ByteBuffer.position(ByteBuffer.java:263) ~[na:na]at java.base/sun.nio.cs.UTF_8.updatePositions(UTF_8.java:80) ~[na:na]at java.base/sun.nio.cs.UTF_8$Encoder.encodeArrayLoop(UTF_8.java:509) ~[na:na]at java.base/sun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:564) ~[na:na]at java.base/java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:576) ~[na:na]at java.base/sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:292) ~[na:na]at java.base/sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:281) ~[na:na]at java.base/sun.nio.cs.StreamEncoder.write(StreamEncoder.java:125) ~[na:na]at java.base/java.io.OutputStreamWriter.write(OutputStreamWriter.java:208) ~[na:na]at java.base/java.io.BufferedWriter.flushBuffer(BufferedWriter.java:120) ~[na:na]at java.base/java.io.PrintStream.write(PrintStream.java:605) ~[na:na]at java.base/java.io.PrintStream.print(PrintStream.java:745) ~[na:na]at java.base/java.io.PrintStream.println(PrintStream.java:882) ~[na:na]at com.github.courage007.springbootwebstarter.resource.A.test(A.java:18) ~[classes/:na]at com.github.courage007.springbootwebstarter.resource.B.test(B.java:21) ~[classes/:na]at com.github.courage007.springbootwebstarter.resource.A.test(A.java:19) ~[classes/:na]at com.github.courage007.springbootwebstarter.resource.B.test(B.java:21) ~[classes/:na]
针对这种情况,因为是在运行时才会发现,如果测试用例覆盖该场景,则不会导致问题流出到现网环境,否则会导致服务崩溃,属于生产事故。
A属性注入B,B构造器注入A
针对A属性注入B,B构造器注入A的情况,其分析与A构造器注入B,B构造器注入A一致,保持相同结论即可。
A属性注入B,B属性注入A
针对A属性注入B,B属性注入A的情况,其分析与A构造器注入B,B属性注入A相似,保持相同结论即可。这里给出示例代码:
@Service
public class A {@Autowiredprivate B b;public void test() {System.out.println("A");}
}@Service
public class B {@Autowiredprivate A a;public void test() {System.out.println("B");}
}
源码分析循环依赖
接下来从Spring Bean的创建过程,看看 Spring 是如何解决一定程度的循环依赖问题。首先,定位到AbstractBeanFactory抽象类的createBean方法。这个方法是Bean创建的入口。
进入其实现,会进入到AbstractAutowireCapableBeanFactory抽象类(这里仅展示关键源码,完整代码可以执行查看源码)。
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactoryimplements AutowireCapableBeanFactory {// ...@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {// ...// 优先尝试从代理中获取Bean实例Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}try {Object beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean '" + beanName + "'");}return beanInstance;} catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {// A previously detected exception with proper bean creation context already,// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.throw ex;} catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);}}protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {// 从这几行代码可知,对于多例模式,是会直接创建Bean实例,所以多例模式下,循环依赖问题无法解决BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {// 创建bean实例,主要解决构造器注入的场景instanceWrapper = createBeanInstance(beanName, mbd, args);}// 缓存的单例集合可以用来解决一定程度的循环依赖问题// 启用缓存的场景:(1) 单例场景;(2) 启用允许循环依赖的开关boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// Initialize the bean instance.Object exposedObject = bean;try {// 创建bean实例,主要解决属性注入的场景populateBean(beanName, mbd, instanceWrapper);// bean的实例化exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");}}}}// ...return exposedObject;}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;}
}public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {// .../** 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);/** Set of registered singletons, containing the bean names in registration order. */private final Set<String> registeredSingletons = new LinkedHashSet<>(256);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);}}}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);// 根据是否允许启用allowEarlyReference,再次获取对象if (singletonObject == null && allowEarlyReference) {synchronized (this.singletonObjects) {// Consistent creation of early reference within full singleton locksingletonObject = 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;}// ...
}
经过上述源码分析,可知对于Bean多例(Prototype)场景,Spring 是不支持解决循环依赖的,只支持Bean单例(Singleton)的场景。而且Spring还提供了允许循环依赖的开关(默认是关闭的)。在创建Bean的时候,Spring 使用了三级缓存。Spring优先从一级缓存singletonObjects中获取对象;如果没有,则尝试从二级缓存earlySingletonObjects中获取;如果还是没有,就从三级缓存singletonFactory获取对象,然后将对象放置到二级缓存,并从三级缓存溢出该对象。这里只是Spring Bean对象创建的过程,那么Spring 是如何解决Bean的循环依赖的问题呢?
其实,这里的关键是Spring引入了earlyBeanReference(早期Bean的引用),也就是说在创建Bean的时候,会注入一个还没初始化的对象,从而解决了循环依赖重复创建的问题。这里以A属性注入B,B属性注入A为例,介绍Spring是如何支持循环依赖的。首先在创建A的实例时,会先创建A的对象引用,然后再去查找A依赖的对象,如果不存在,则需要进入依赖对象的创建过程,同样地,会先创建对象的引用,这里是对象B的引用。这样在A中就可以使用B,而B也是类似的操作。
如果仅使用一级缓存和二级缓存就可以解决循环依赖问题,为什么没有这么做呢?这是因为,并不是需要对所有对象都创建二级缓存,这样可以减少不必要的对象创建,从而节省内存。而引入三级缓存后,如果存在允许循环引用的场景,则会基于对象引用工厂创建对象的引用,然后将其存储到二级缓存。可以说,三级缓存的目的就是为了构造二级缓存中的元素,从而达到节省内存的效果。
循环依赖的处理
了解了Spring 支持的循环依赖的解决能力,接下来针对存在循环依赖的场景,给出合适的处理方案。
如果需要Spring Boot版本从低于2.6.0的版本升级到高于2.6.0的版本,如果现有代码存在循环依赖,且无法再短时间内消减掉该问题,则可以先在配置文件中补充下述配置,做临时规避处理:
spring:main:allow-circular-references:true #允许循环依赖
当然,不建议在新写的代码中引入循环依赖问题。接下来根据是否存在方法循环调用,对问题进一步的划分:不存在循环调用的循环依赖,存在循环调用的循环依赖。
注意,这里不再关注循环调用的方式,统一使用A属性注入B,B属性注入A这种方式进行说明。
不存在循环调用的循环依赖
如果存在循环依赖,但是不存在循环调用,如果是在2.6.0以下版本,不会有问题,只是有引入循环调用的风险;如果是在2.6.0以上的版本,如果不主动开启允许循环依赖的特性开关,是会在启动的时候报循环依赖的错误的。但是如果开启允许循环依赖的特性开关,则不会影响启动,只是有引入循环调用的风险。
为消减掉循环调用的风险,应尝试解决掉这种循环依赖,这里给出示例代码:
// 修改前
@Service
public class A {@Autowiredprivate B b;public void test() {System.out.println("A");b.test();}
}@Service
public class B {@Autowiredprivate A a;public void test() {System.out.println("B");}
}
// 修改后// 修改前
@Service
public class A {@Autowiredprivate C c;public void test() {System.out.println("A");c.test();}
}@Service
public class B {@Autowiredprivate A a;
}@Service
public class C {public void test() {System.out.println("B");}
}
可见,这里解决掉循环依赖的方式,就是将被依赖的类中的方法,独立包装成一个类,然后被引用。当然,实际的情况可能更复杂,但是核心的处理策略都是一样的。
存在循环调用的循环依赖
如果存在循环依赖,且存在循环调用,不管是哪一个Spring 版本,都会因循环调用,导致对象重复创建,进而导致堆栈溢出,引发程序崩溃。从直接现象来看,这是开发人员因逻辑思考有问题,写入了死循环的代码导致。且该代码并没有做自测,如果没有测试用例看护,那么这种问题流出到现网环境,将会带来生产事故。
为解决这类Bug,就是要思考现有实现,看看代码逻辑,正常来说,可以先将循环调用消减掉,然后再想办法(参考上一节)消减掉循环调用。这里给出存在循环调用的循环依赖的示例代码(之前已有介绍,这里重复一下,方便阅读):
@Service
public class A {private B b;public A(B a) {this.b = b;}public void test() {System.out.println("A");b.test();}
}@Service
public class B {@Autowiredprivate A a;public void test() {System.out.println("B");a.test();}
}
总结
针对Spring Bean的循环依赖问题,如果情况允许,尽量不使用临时规避的手段容忍循环依赖问题。如果因存量代码的问题,尽量将消除循环依赖作为高优先级历史债务进行解决。循环依赖的引入,要么会影响应用的启动,要么会因方法循环调用陷入死循环,从而导致堆栈溢出,给用户带来影响。
参考
https://blog.csdn.net/wangxuelei036/article/details/104960558 spring 循环依赖以及解决方案
https://www.cnblogs.com/daimzh/p/13256413.html 讲一讲Spring中的循环依赖
https://blog.csdn.net/qq_51076413/article/details/131061348 SpringBoot3.x循环依赖
https://juejin.cn/post/7032910060044943373 Spring Boot 2.6.0正式发布:默认禁止循环依赖、增强Docker镜像构建
https://blog.csdn.net/Microhoo_/article/details/132188824 解决Spring Boot 2.6及之后版本取消了循环依赖的支持的问题
https://zhuanlan.zhihu.com/p/647315070 spring bean 三级缓存
相关文章:
Spring Bean循环依赖问题及解决
什么是循环依赖 类与类之间的依赖关系形成了闭环,就会导致循环依赖问题的产生。举例来说,假设存在两个服务类A和服务类B,如果A通过依赖注入的方式引用了B,且B通过依赖注入的方式引用了A,那么A和B之间就存在循环依赖。…...

Golang源码分析 | 程序引导过程
环境说明 CentOS Linux release 7.2 (Final) go version go1.16.3 linux/amd64 GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7使用gdb查看程序入口 编写一个简单的go程序 // main.go package mainfunc main() {print("Hello world") } 编译go …...

第三章:人工智能深度学习教程-基础神经网络(第四节-从头开始的具有前向和反向传播的深度神经网络 – Python)
本文旨在从头开始实现深度神经网络。我们将实现一个深度神经网络,其中包含一个具有四个单元的隐藏层和一个输出层。实施将从头开始,并实施以下步骤。算法: 1. 可视化输入数据 2. 确定权重和偏置矩阵的形状 3. 初始化矩阵、要使用的函数 4. 前…...

【入门Flink】- 08Flink时间语义和窗口概念
Flink-Windows 是将无限数据切割成有限的“数据块”进行处理,这就是所谓的“窗口”(Window)。 注意:Flink 中窗口并不是静态准备好的,而是动态创建——当有落在这个窗口区间范围的数据达到时,才创建对应的窗…...
【 OpenGauss源码学习 —— 列存储(CStore)(六)】
列存储(CStore)(六) 概述CStore::GetCUDataFromRemote 函数CStore::CheckConsistenceOfCUDescCtl 函数CStore::CheckConsistenceOfCUDesc 函数CStore::CheckConsistenceOfCUData 函数额外补充 声明:本文的部分内容参考…...

MUYUCMS v2.1:一款开源、轻量级的内容管理系统基于Thinkphp开发
MuYuCMS:一款基于Thinkphp开发的轻量级开源内容管理系统,为企业、个人站长提供快速建站解决方案。它具有以下的环境要求: 支持系统:Windows/Linux/Mac WEB服务器:Apache/Nginx/ISS PHP版本:php > 5.6 (…...

SDL2 显示文字
1.简介 SDL本身没有显示文字功能,它需要用扩展库SDL_ttf来显示文字。ttf是True Type Font的缩写,ttf是Windows下的缺省字体,它有美观,放大缩小不变形的优点,因此广泛应用很多场合。 使用ttf库的第一件事要从Windows的…...
c++ future 使用详解
c future 使用详解 std::future 头文件 #include <future>。 类模板,定义如下: template<class T> class future; template<class T> class future<T&>; template<> class future<void>;作用ÿ…...
好用的C C++ 日志宏 OutputDebugStringA 写到文件或界面
日志宏 #include <cstdio> #define OUTPUT_DEBUG_STRING(fmt, ...) do { \char szOutMsgFinal[10240] {0}; \std::snprintf(szOutMsgFinal, sizeof(szOutMsgFinal), "[%s|%d] " fmt "\n", __func__, __LINE__, ##__VA_ARGS__); \OutputDebugString…...

如何在ModelScope社区魔搭下载所需的模型
本篇文章介绍如何在ModelScope社区下载所需的模型。 若您需要在ModelScope平台上有感兴趣的模型并希望能下载至本地,则ModelScope提供了多种下载模型的方式。 使用Library下载模型 若该模型已集成至ModelScope的Library中,则您只需要几行代码即可加载…...

NLP在网安领域中的应用(初级)
NLP在网安领域的应用 写在最前面1. 威胁情报分析1.1 社交媒体情报分析(后面有详细叙述)1.2 暗网监测与威胁漏洞挖掘 2. 恶意软件检测2.1 威胁预测与趋势分析 3. 漏洞管理和响应4. 社交工程攻击识别4.1 情感分析与实时监测4.2 实体识别与攻击者画像构建4.…...
03.UDP套接字与原始套接字
UDP套接字 注意在UDP套接字中,要使用recvfrom和sendto API: recvfrom: 接收数据包,并存储源地址(UDP) 函数原型: int WSAAPI recvfrom([in] SOCKET s,[out] char *buf,[in] int len,[...

「NLP+网安」相关顶级会议期刊 投稿注意事项+会议等级+DDL+提交格式
「NLP网安」相关顶级会议&期刊投稿注意事项 写在最前面一、会议ACL (The Annual Meeting of the Association for Computational Linguistics)IH&MMSec (The ACM Workshop on Information Hiding, Multimedia and Security)CCS (The ACM Conference on Computer and Co…...

Python开源项目RestoreFormer(++)——人脸重建(Face Restoration),模糊清晰、划痕修复及黑白上色的实践
有关 Python 和 Anaconda 及 RestoreFormer 运行环境的安装与设置请参阅: Python开源项目CodeFormer——人脸重建(Face Restoration),模糊清晰、划痕修复及黑白上色的实践https://blog.csdn.net/beijinghorn/article/details/134…...
设计模式 -- 命令模式(Command Pattern)
命令模式:一种数据驱动的设计模式也属于行为型模式,请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。你认为是命令的地方都可以使用…...

【数据分享】2021-2023年我国主要城市逐月轨道交通运营数据
以地铁为代表的轨道交通是大城市居民的主要交通出行方式之一,轨道交通的建设和运营情况也是一个城市发展水平的重要体现。本次我们为大家带来的是2021-2023年我国主要城市的逐月的轨道交通运营数据! 数据指标包括:运营线路条数(条…...
大数据-之LibrA数据库系统告警处理(ALM-12034 周期备份任务失败)
告警解释 周期备份任务执行失败,则上报该告警,如果下次备份执行成功,则恢复告警。 告警属性 告警ID 告警级别 可自动清除 12034 严重 是 告警参数 参数名称 参数含义 ServiceName 产生告警的服务名称。 RoleName 产生告警的角色…...
tx-前端笔试题记录
目录 目录 1.你最熟悉的前端框架是什么说说你对它的理解。 2.请简单实现一下js对象深度拷贝。 3.CSS 有几种方法实现垂直水平居中?请简要写一下。 4.这段程序执行之后控制台会打印什么内容? 5.下列程序的输出结果是多少?为什么? 6.有ABCDE 五个火车站,单向…...

详解Redis持久化(上篇——RDB持久化)
Redis持久化的作用和意义 Redis 持久化是一种机制,用于将内存中的数据写入磁盘,以保证数据在服务器重启时不会丢失。持久化是为了解决内存数据库(如 Redis)在服务器关闭后,数据丢失的问题。 Redis 持久化的主要作用和…...
爬虫常见风控
一.ip风控 单位时间内接口访问频率。 二.设备指纹风控 设备注册时候设备特征是否完整,信息主要包含硬件、网络、系统三部分。 硬件属性:设备品牌、型号、IMEI(国际移动设备识别码)、处理器、内存、分辨率、亮度、摄像头、电池、…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...

04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...