spring源码分析-事务的底层源码-1

这里写自定义目录标题

  • spring事务的源码分析
    • 阅读spring事务源码的前置知识
    • JDBC的事务
    • spring当中和事务相关的对象
    • spring应用程序编码
    • spring事务的源码如何开始研究
    • spring源码当中如何代理bean

spring事务的源码分析

最近在研究seata;看了一下spring当中的事务有一点心得故而来写篇文章分享一下;另外对于seata框架的视频讲解在b站上;如果对seata比较感兴趣的可以去三连一下;还有就是关于这篇文章对应的视频讲解我也传到这个b站账号上;
https://space.bilibili.com/419779862

阅读spring事务源码的前置知识

spring事务这块代码写的有点复杂;如果需要完全看懂需要一点点前置知识;

  • JDK动态代理的知识
  • spring bean生命周期和后置处理器的一些知识
  • spring Aop的原理

当然如果你不具备这些知识也没关系知识读起来会难一点;其中关于JDK动态代理的知识我曾经录过一个2小时的手写JDK动态代理的视频;如果你对JDK动态代理不是很了解可以评论区问一下看完一定会非常清晰;当然你如果嫌麻烦就可以直接看下图;记住图中的结论(如果你懂动态代理可以不用看图了);

在这里插入图片描述

JDBC的事务

正常情况下spring的事务是基于jdbc的事务来的;那么我们现在回顾一下jdbc的事务代码;其实非常简单;

onnection connection = getConnection();
connection.setAutoCommit(false);
//执行sql等等操作
//执行完成之后提交
connection.commit();
connection.rollback();

其实你仔细想一下会发现事务他是一个非常难以抽象的概念;比如一个苹果你去抽象可以定义一个类Apple;然后定义一些属性——产地、颜色、价格、口味等等;但是事务这个东西他不是一个名词,严格意义上他是一个动作,甚至不是一个动作是一些列动作(提交、或者回滚);那么作为spring作者他该如何在spring源码当中来抽象呢?——说白了就是该定义一个怎样的类来描述事务这个东西呢?诚如前面说的事务是一个动作spring框架要抽象出来比较困难;所以如果想搞懂spring源码当这块的代码需要先搞明白关于事务的一些对象在spring当中;

spring当中和事务相关的对象

这块相当重要;如果想把spring源码当中对事务的操作代码看懂就一定得先好好看看这一章节;当然这里可能阅读起来很麻烦甚至你看不懂;但是你一定硬着头皮看下去我尽量写详细一点;

1、首先spring如果需要操作事务离不开JDBC那一套——也就是首先的需要获取连接;但是spring当中默认认为你是使用了数据源;也就是DataSource;spring当中定义了一个类TransactionManager——事务管理器里面保存了数据源;这里面的dataSouce需要程序员手动配置给他;相信你如果做过spring开发就写过这行代码
在这里插入图片描述
2、数据源不代表连接;具体的连接对象spring当中有一个类DataSourceTransactionObject这个当中包含了Connetion对象;下面是我对这个类属性的总结,实际spring源码当中封装了很多层;后面再来详细说;这里只是先列举出来方便我们理解spring作者在设计事务这块的思路和类的设计

DataSourceTransactionObject{previousIsolationLevel;隔离级别savepointAllowed;是否允许savepointcurrentConnection;连接transactionActive;事务是否活跃mustRestoreAutoCommit;是否需要重置自动提交Connection currentConnection;连接信息
}

3、事务状态的包装;spring当中事务是否只读;事务是否完成;事务是否同步;事务是否是一个新的事务等等这些信息用了一个TransactionStatus的类来封装

TransactionStatus{//事务的状态boolean rollbackOnly = false;//是否只读事务boolean completed = false;//是否完成Object savepoint;底层数据库支持newTransaction; 是否新开的事务newSynchronization 是否同步
}	

4、事务的属性,也就是程序在定义事务指定的特点,比如传播机制、比如事务的回滚异常;是否需要指定隔离级别等等在sping当中定义了一个类TransactionAttribute来封装

5、上面四个类怎么关联起来呢?spring当中定义了一个类TransactionInfo他把上面四个类关联起来了;如果上面你没用看懂;你现在就记住一个结论;就是spring在操作事务的时候他最后需要得到一个TransactionInfo的对象;通过这个对象去作判断,比如传播机制是否合理,比如异常是否匹配等等行为去提交事务或者回滚事务;这五个类的关系大体如下面

	TranscationInfo{ //事务信息 包含了事务的所有操作和信息TransactionAttr;//事务属性--程序员配置TransactionManager//事务管理器,包含了数据源TransactionStatus{//事务的状态boolean rollbackOnly = false;//是否只读事务boolean completed = false;//是否完成Object savepoint;底层数据库支持private final Object transaction;//newTransaction; 是否新开的事务newSynchronization 是否同步	DataSourceTransactionObject//和数据源关联的事务对象DataSourceTransactionObject{previousIsolationLevel;隔离级别savepointAllowed 是否允许savepointcurrentConnection;连接transactionActive;事务是否活跃mustRestoreAutoCommit;是否需要重置自动提交}}
}

之所以现在就列举这几个对象,是因为这几个对象很重要了,spring底层源码关于事务这块基本就是操作这几个对象,读者可以先看个大概,如果看不懂可以直接记住我上面的结论——就是spring在操作事务的时候他最后需要得到一个TransactionInfo的对象;通过这个对象去作判断,比如传播机制是否合理,比如异常是否匹配等等行为去提交事务或者回滚事务;

spring应用程序编码

当然要研究事务需要一个案例;spring+mybatisplus+mysql;代码我传到文章末尾——需要说明的是我是基于spring源码这个项目搭建的环境所以是gradle,如果下载我的代码需要改对应的比如maven;这里对代码做一个简单介绍
1、数据源代码–使用spring自带的需要在配置类当中写代码;mybatis的配置就不在文章当中说明了,参考我传的附件demo

@Beanpublic DataSource dataSource(){DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/cloud_demo?useUnicode=true&rewriteBatchedStatements=true");dataSource.setUsername("root");dataSource.setPassword("aaa111");return dataSource;}

2、如果要开启spring的声明式事务的支撑需要配置一个事务管理器;事务管理器需要设计一个数据源给他;原因上文做了说明

@Beanpublic DataSourceTransactionManager dataSourceTransactionManager(){DataSourceTransactionManager dstm = new DataSourceTransactionManager();dstm.setDataSource(dataSource());return dstm;}

3、在配置类上面开启允许事务;

@Configuration
@EnableTransactionManagement
public class Appconfig {
}

@EnableTransactionManagement这个注解底层原理非常重要,下文会详细说明

4、在对应的方法上面加上@Transcation注解

@Service
public class InventoryAtService{}@Transactional(propagation = Propagation.REQUIRED)public boolean save(InventoryEntity entity) {}
}

那么InventoryAtService这个类就会被spring代理,增强其中的save方法在save方法当中加上事务的逻辑

spring事务的源码如何开始研究

其实研究spring是的事务原理无非两个大的问题
1、spring是如何完成拦截和增强的;譬如上面InventoryAtService sprring是如何拦截到这个类的;如何完成增强的

2、增强的逻辑是什么?也就是他怎么开启事务,怎么提交事务,怎么回滚事务?

首先解决第一个问题;spring是如何拦截到需要被增强的类——换句话说spring是如何拦截到方法上加了@Transactional的类并且增强的;但凡有点spring知识肯定知道这是springaop机制;关键是aop需要配置切面、切点、通知、连接点等等;而我们这里是没有配置切面、没有配置切点、没有配置通知的;

1、首先通知其实是不需要我们配置的,因为事务这块的通知肯定spring框架自己写的——关于开启提交事务的代码;这块业务代码不可能交给程序员去写;所以通知肯定是spring内置的;

2、那么切面和切点呢?回滚一下如果程序员自己定义切面的Aspectj语法是需要新建一个类,然后再里面写代码去配置;然后spring会把这些切面当中的信息——通知、切点、连接点封装成为一个Advisor对象;所以如果你不手动配置切面你也可以给spring提供一个Advisor对象也能完成aop的定义

3、spring事务增强这块就是他提供了一个Advisor对象里面把切面的各种信息封装了,所以不需要你手动去写Aspectj语法风格的切面了;

4、那么这个对象在哪里呢?怎么生效的呢?—@EnableTransactionManagement;查看这个注解的源码
在这里插入图片描述

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
}

5、EnableTransactionManagement 当中会Import一个类TransactionManagementConfigurationSelector.class;查看这个类的源码

在这里插入图片描述

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {/*** Returns {@link ProxyTransactionManagementConfiguration} or* {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}* and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},* respectively.*/@Overrideprotected String[] selectImports(AdviceMode adviceMode) {switch (adviceMode) {case PROXY:return new String[] {AutoProxyRegistrar.class.getName(),ProxyTransactionManagementConfiguration.class.getName()};case ASPECTJ:return new String[] {determineTransactionAspectClass()};default:return null;}}

6、TransactionManagementConfigurationSelector 这个类一看就是实现了ImportSelector接口;这个接口有一个方法 selectImports会返回一个字符串数组;如果字符串数组的内容是一个符合标准的全限定类名;那么spring会把这个类当做一个bean去进行实例化和初始化到容器当中——其实springboot的自动装配功能就是利用了这个spring提供的扩张点;关于ImportSelector我曾经讲过一个50小时的spring源码视频可以直接找博主要这里不在累述;你只需要记住一个结论——selectImports方法当中返回的字符串如果是正常的全限定类名则会被容器识别

7、观察TransactionManagementConfigurationSelector 当中的selectImports方法

return new String[] {AutoProxyRegistrar.class.getName(),ProxyTransactionManagementConfiguration.class.getName()	}

主要返回了两个类AutoProxyRegistrar和ProxyTransactionManagementConfiguration;接下来一个一个分析

8、AutoProxyRegistrar 查看源码
在这里插入图片描述
在他的registerBeanDefinitions方法当中注册了一个beanDefintion

在这里插入图片描述

接着点进去查看源码

在这里插入图片描述

这里主要注册了一个类InfrastructureAdvisorAutoProxyCreator;查看这个类的源码;
在这里插入图片描述

发现他其实是一个BeanPostProcessor并且他是集成至AbstractAutoProxyCreator;那么就是一个完成代理的后置处理器;和AOP类似——说白了InfrastructureAdvisorAutoProxyCreator理论上会对所有的bean进行代理、为什么是理论上呢?因为实际过程中他在处理bean的时候会做一些条件判断;所以是理论上;那么做什么判断呢?其实这属于AOP的知识,也就是springAOP在完成代理的时候会进行切面当中的连接点信息判断是否需要增强;这里也是一样——判断bean是否符合连接点的配置,至于连接点的信息在下一个类当中;至此导入的第一个类AutoProxyRegistrar的作用解释清楚了

return new String[] {AutoProxyRegistrar.class.getName(),//解释清楚了ProxyTransactionManagementConfiguration.class.getName()	}

9、连接点在哪里设置的?InfrastructureAdvisorAutoProxyCreator会增强bean;但是需要提供连接点或者切点信息;这些信息就是第二个类ProxyTransactionManagementConfiguration当中去设置的

查看这个类的源码;这个类的源码比较多,我们一点点解释

在这里插入图片描述

@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource);advisor.setAdvice(transactionInterceptor);if (this.enableTx != null) {advisor.setOrder(this.enableTx.<Integer>getNumber("order"));}return advisor;}

首先这个类当中第一个方法是一个加了@Bean的方法 返回一个 BeanFactoryTransactionAttributeSourceAdvisor类型的bean;我们先不去关系这个bean;先看这个方法的参数;他有两个参数;
1、TransactionAttributeSource transactionAttributeSource,
2、TransactionInterceptor transactionInterceptor

在这里插入图片描述
由于这是个@Bean方法所以这两个参数也是回去spring容器获取;所以这两个参数对应肯定也是一个bean;spring在下面又写了两个@Bean方法来实例化这两个bean

在这里插入图片描述

这两个bean是干嘛的?
第一个 TransactionAttributeSource 这个bean的作用主要将来用来获取事务属性的;比如你配置的传播机制,异常信息等等;这个bean当中提供了一个方法来获取这些信息

第二个:TransactionInterceptor ;这个相当重要;他是一个方法拦截器;他里面有个invoke方法;——相当于通知;也就是将来你对bean进行代理,对方法进行增强的时候的增强逻辑——放到这里就是事务的开启、提交、回滚都会写在这对象的invoke方法当中;当然这里他仅仅是个bean;他是怎么成为一个通知的呢?

回到BeanFactoryTransactionAttributeSourceAdvisor这个bean,我们前面说了他需要两个参数,上面解释了他两个参数的作用;接下来解释这个类,这个类去查看他的源码发现他就是一个advisor;也就是他里面应该包含切点、通知、连接点信息;所以他需要一个TransactionInterceptor 类型的参数,作为他的通知;
在这里插入图片描述
那么他的切点和连接点在哪里呢?查看这个类的源码他里面定义了一个属性

在这里插入图片描述

这个切点对象就是后续spring在增强时候需要用到的,他提供的一个匹配方法,来判断当前bean是否符合切点信息——而且这个切点对象当中的规则就是判断方法是否加了Transactional注解——这个判断逻辑下文分析 这里给出一个spring源码截图的证据
在这里插入图片描述

至此:@EnableTransactionManagement 这个注解的功能都搞清楚了;
总结一下这个注解主要两个作用
1、导入了一个后置处理器对象来增强bean ——InfrastructureAdvisorAutoProxyCreator
2、导入了一个Advisor对象;主要是定义好了哪些bean需要增强,增强的逻辑是什么;接下来分析如何应用起来的

spring源码当中如何代理bean

在这里插入图片描述
上图所示当调用inventoryService的save方法的时候,假设inventoryService没有实例化,那么spring容器会实例化这个bean,会走他的生命周期,当走到BeanPostProcessor的postProcessAfterInitialization方法的时候会从容器当中拿出所有的后置处理器依次执行他们的postProcessAfterInitialization方法;关于这块属于bean的生命周期知识可以参考我前面写的循环依赖文章;前文已经分析过了@EnableTransactionManagement 注解会往容器当中注册一个后置处理器——InfrastructureAdvisorAutoProxyCreator那么这个后置处理会在这里起到作用;
在这里插入图片描述
getBeanPostProcessors()就是获取到所有的后置处理器;我们前面通过@EnableTransactionManagement 导入的那个后置处理器就会出现在这里;换言之如果不加那个注解,那么你的@Transcation注解就不会生效,因为你不加注解容量当中没有InfrastructureAdvisorAutoProxyCreator这后置处理器,就无法对bean进行代理;
在这里插入图片描述
那么在InfrastructureAdvisorAutoProxyCreator的postProcessAfterInitialization当中如何对bean进行代理的呢?

在这里插入图片描述
InfrastructureAdvisorAutoProxyCreator会调用父类的postProcessAfterInitialization方法内部会调用wrapIfNecessary方法完成代理;这里说明一下其实循环依赖当中不止三个map也就是网上所谓的三级缓存其实不够严谨,严格意义是四个map还有就是上图我写了注释的地方——earlyProxyReferences;这里不在详细说了将来可以再写一篇文章来详细说说这个问题;

接下来查看wrapIfNecessary方法;里面代码属于aop源码的部分;我曾经在讲过spring源码这里不在详细说只拎取和本文相关的代码作说明

在这里插入图片描述

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

getAdvicesAndAdvisorsForBean方法非常重要;顾名思义就是通过当前bean(inventoryService)找到与之对应的Advisor——说白了就是找到定义了需要增强当前bean的Advisor;前文说了Advisor相当于切面,里面定义了切点和连接点,如果连接点符合当前bean,那么就会把这个Advisor找出来;那么这里能不能找到呢?看一下源码

在这里插入图片描述
调用AbstractAdvisorAutoProxyCreator当中getAdvicesAndAdvisorsForBean方法,改方法里面继续调用findEligibleAdvisors

在这里插入图片描述
findEligibleAdvisors方法里面的内容有点多,我们逐行解释;
1、首先调用List candidateAdvisors = findCandidateAdvisors();找到所有的Advisor;不管符不符合当前bean都找出来;比如你定义了一个Advisor可能是给OrderSerivice服务的但是也会在这里找出来;可以查看他里面的源码
在这里插入图片描述
2、找打所有的Advisor之后把他们存入一个List当中然后返回;并且把这个list在进行遍历找出符合当前bean需求的advisor
在这里插入图片描述
findAdvisorsThatCanApply方法就是遍历并判断哪些Advisor对象能服务当前对象;里面代码最核心

在这里插入图片描述
上面是个空壳方法继续调用findAdvisorsThatCanApply
在这里插入图片描述

这里有一个是否IntroductionAdvisor类型的判断;关于Introduction——AOP我有讲过这里不在累述;你可以理解这个基本不会成立;所以会进到322行的if当中执行canApply方法

在这里插入图片描述
继续执行289行代码

在这里插入图片描述
这里的代码比较复杂;首先获取了一个MethodMatcher对象;是通过pc对象获取的,这里的pc对象其实就是我们前面通过@EnableTransactionManagement这个注解导入的Advisor对象——BeanFactoryTransactionAttributeSourceAdvisor当中的切点对象;怎么理解呢?看懂下面这幅图

在这里插入图片描述

最后methodMatcher.matches(method, targetClass))调用的就是TransactionAttributeSourcePointcut类当中的matches方法

在这里插入图片描述
然后执行
在这里插入图片描述

跟着执行
在这里插入图片描述

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

最后执行
在这里插入图片描述
至此spring就能找到所有加了@Transcation注解的方法所在的类,并且对其进行代理;

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

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

相关文章

第十三届蓝桥杯(C/C++ 大学B组)

目录 试题 A: 九进制转十进制 试题 B: 顺子日期 试题 C: 刷题统计 试题 D: 修剪灌木 试题 E: X 进制减法 试题 F: 统计子矩阵 试题 G: 积木画 试题 H: 扫雷 试题 I: 李白打酒加强版 试题 J: 砍竹子 试题 A: 九进制转十进制 九进制正整数 ( 2022 )转换成十进制等于多…

Hypermesh碰撞安全之安全带缠绕建模

进入安全带建模&#xff08;Analysis→safety→belt routing) ①肩带的创建 注&#xff1a;end types: 表示2D和1D单元的过渡方式 ②腰带的创建 ③修改接触系数

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Tabs)

通过页签进行内容视图切换的容器组件&#xff0c;每个页签对应一个内容视图。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 该组件从API Version 11开始默认支持安全区避让特性(默认值为&#x…

【老旧小区用电安全谁能管?】安科瑞智慧用电安全管理系统解决方案

行业背景 电气火灾指由电气故障引发的火灾。每年以30%的比例高居各类火灾原因之首。以50%到80%的比例高居重特大火灾之首。已成为业界重点关注的对象并为此进行着孜孜不倦的努力。 国务院安委会也于2017年5月至2020年4月年开展了为期3年的电气火灾综合治理工作。在各界努力的…

HJ212协议C#代码解析实现

HJ212协议C#代码解析实现 HJ212协议是环保中一个非常重要的标准协议&#xff08;字符串协议&#xff09;&#xff0c;之前写了两篇C HJ212协议解析的相关博文&#xff1a; 环保 HJ212协议解析基于Qt5.14.2的HJ212 TCP服务端接收解析入库程序 最近在学习C#&#xff0c;所以打算…

接口幂等性问题和常见解决方案

接口幂等性问题和常见解决方案 1.什么是接口幂等性问题1.1 会产生接口幂等性的问题1.2 解决思路 2.接口幂等性的解决方案2.1 唯一索引解决方案2.2 乐观锁解决方案2.3 分布式锁解决方案2.4 Token解决方案(最优方案) 3 Token解决方案落地3.1 token获取、token校验3.2 自定义注解,…

小蓝的漆房——算法思路

题目链接&#xff1a;1.小蓝的漆房 - 蓝桥云课 (lanqiao.cn) 本题只要是通过枚举的方法&#xff0c;算出涂成每一种颜色所需的天数&#xff0c;最后在所有天数中找出最小值&#xff08;由题可知&#xff0c;最多只有60种颜色&#xff0c;所以可以尝试算出每种颜色所需的时间&am…

LeetCode刷题小记 八、【回溯算法】

1.回溯算法 文章目录 1.回溯算法写在前面1.1回溯算法基本知识1.2组合问题1.3组合问题的剪枝操作1.4组合总和III1.5电话号码的字母组合1.6组合总和1.7组合总和II1.8分割回文串1.9复原IP地址1.10子集问题1.11子集II1.12非递减子序列1.13全排列1.14全排列II1.15N皇后1.16解数独 写…

react中hooks使用限制

只能在最顶层使用Hook 不要在循环、条件中调用hook&#xff0c;确保总是在React函数最顶层使用它们 只能React函数中调用Hook 不要在普通的js函数中调用 在React的函数组件中调用Hook 在自定义hook中调用其他hook 原因&#xff1a; 我们每次的状态值或者依赖项存在哪里&…

springCloudeAlibaba的使用

父pom文件&#xff1a; <?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.o…

数据库中逻辑运算符的介绍以及优先级表

简介&#xff1a;逻辑运算符主要判断表达式的真假&#xff0c;返回值为1&#xff0c;0&#xff0c;null 其中包含&#xff1a; 逻辑非&#xff1a;not或&#xff01; 逻辑与&#xff1a;and或&& 逻辑或&#xff1a;or或|| 逻辑异或&#xff1a;XOR 1.逻辑非运算 规则…

mac打开exe文件的三大方法 mac怎么运行exe文件 mac打开exe游戏 macbookpro打开exe

exe文件是Windows系统的可执行文件&#xff0c;虽然Mac系统上无法直接打开exe文件&#xff0c;但是你可以在Mac电脑上安装双系统或者虚拟机来实现mac电脑上运行exe文件。除了这两种方法之外&#xff0c;你还可以在Mac电脑上使用类虚拟机软件打开exe文件&#xff0c;这三种方法各…

双指针 | 移动零 | 复写零

1.移动零 题目描述&#xff1a; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 示例&#xff1a; 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0]解题思路&#xff1a; right指针一直往后移动&#xff0c;当…

欧洲跨境物流仓库视频监控系统开发的解决方案

中国联通针对仓储物流行业的数字化需求&#xff0c;提供全面的解决方案&#xff0c;特别是在海外仓储领域&#xff0c;我们深谙企业面临的挑战&#xff0c;如预算限制、仓储空间需求以及城郊网络覆盖不足等问题。我们利用自身强大的网络资源和技术实力&#xff0c;为出海仓储企…

redis学习-Hash类型相关命令及特殊情况分析

目录 1. hset KEY key1 value1 key2 value2 ... 2. hget KEY key 3. hgetall KEY 4. hmget KEY key1 key2 ... 5. hkeys KEY 6. hvals KEY 7. hdel KEY key1 key2 ... 8. hlen KEY 9. hexists KEY key 10. hincrby KEY key num 11. hsetnx KEY key value Hash的内部…

实时数仓项目《一》-实时数仓架构

目录 1. 实时数仓与离线数仓 2. 实时数仓需求 3. 架构图 3.1 行为日志处理&#xff1a; 3.2 业务库表处理&#xff1a; 4. 面试题&#xff1a; &#x1f9c0;你们的实时数仓有分层吗&#xff1f; &#x1f9c0;那你们的业务数据呢&#xff1f; &#x1f9c0;那你们的O…

字符分类函数(iscntrl、i是space.....)---c语言

目录 一、定义二、字符分类函数2.1 -iscntrl&#xff08;&#xff09;2.1.1定义2.1.2使用举例 2.2 -isspace&#xff08;&#xff09;2.2.1描述2.2.2使用举例 2.3-isdigit()2.3.1描述2.3.2使用举例 2.4-isxdigit()2.4.1描述 2.5-islower()2.5.1描述2.5.2使用举例 2.6-isupper()…

THM学习笔记—Simple CTF

nmap扫描&#xff0c;发现2222端口很奇怪啊&#xff0c;重新换一种方式扫描2222端口 发现是ssh 先用ftp试试&#xff0c;尝试匿名登录 下载所有文件 发现只有一个ForMitch.txt&#xff0c;告诉我们其账号密码为弱密码&#xff0c;我们猜测Mitch为其用户名&#xff0c;尝试暴力…

MechanicalSoup,一个非常实用的 Python 自动化浏览器交互工具库!

目录 前言 什么是 Python MechanicalSoup 库&#xff1f; 核心功能 使用方法 1. 安装 MechanicalSoup 库 2. 创建 MechanicalSoup 客户端 3. 打开网页并与之交互 实际应用场景 1. 网页自动化测试 2. 网络爬虫与数据提取 3. 网页自动化操作 4. 自动化填写和提交多个表单 5.…

V-JEPA模型,非LLM另外的选择,AGI的未来:迈向Yann LeCun先进机器智能(AMI)愿景的下一步

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…