spring声明式事务原理01-调用第1层@Transactional方法(事务访问入口)
文章目录
- 【README】
- 【步骤1】UserAppService调用userSupport.saveNewUser()
- 【步骤2】获取到TransactionInterceptor
- 【步骤3】chain不为空,接着执行CglibMethodInvocation#proceed方法
- 【补充】AopContext作用
- 【步骤4】CglibMethodInvocation#proceed方法
- 【步骤5】调用ReflectiveMethodInvocation#proceed方法(反射方法调用类)
- 【步骤6】调用 TransactionInterceptor#invoke(事务拦截器#invoke方法)
- 【补充】TransactionInterceptor-事务拦截器源码
- 【步骤7】调用TransactionAspectSupport#invokeWithinTransaction方法
- 【步骤8】根据事务属性txAttr获取事务管理器,tm=JdbcTransactionManager
- 【补充】事务管理器是什么?
- 【步骤9】TransactionAspectSupport#invokeWithinTransaction()-在事务中执行业务逻辑(非常重要)
- 【步骤9.1】按需创建事务-createTransactionIfNecessary()
- 【补充】TransactionInfo事务信息定义
- 【补充】TransactionStatus事务状态定义
- 【步骤9.2】执行目标方法
【README】
1)声明式事务代码样例:

public interface UserMapper {UserPO qryUserById(@Param("id") String id);@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)void insertUser(UserPO userPO);
}public interface UserAccountMapper {@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)void insertUserAccount(UserAccountPO userAccountPO);
}
【代码解说】
- 代码调用链路:UserAppService -> userSupport.saveNewUser -> userMapper.insertUser + userAccountMapper.insertUserAccount
- userSupport.saveNewUser 带有 @Transactional 注解; 第1层(最外层)@Transactional标注的方法
- userMapper.insertUser 带有 @Transactional 注解; 第2层@Transactional标注的方法1
- userAccountMapper.insertUserAccount 带有 @Transactional 注解; 第2层@Transactional标注的方法2
2)@Transactional:事务注解,用于定义事务元数据,包括事务管理器名称,事务传播行为,超时时间(单位秒),是否只读,回滚的异常类型;
- @Transactional可以标注类与方法,不管是标注类还是方法,@Transactional标注所在的类的bean都会被spring通过aop代理进行增强;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Reflective
public @interface Transactional {@AliasFor("transactionManager")String value() default "";@AliasFor("value")String transactionManager() default "";String[] label() default {};Propagation propagation() default Propagation.REQUIRED;Isolation isolation() default Isolation.DEFAULT;int timeout() default -1;String timeoutString() default "";boolean readOnly() default false;Class<? extends Throwable>[] rollbackFor() default {};String[] rollbackForClassName() default {};Class<? extends Throwable>[] noRollbackFor() default {};String[] noRollbackForClassName() default {};
}
【步骤1】UserAppService调用userSupport.saveNewUser()
1)因为 userSupport中的saveNewUser方法被@Transaction标注,所以该bean被spring增强为aop代理,所以访问aop代理的入口方法intercept(),即CglibAopProxy#DynamicAdvisedInterceptor静态内部类的 intercept方法;

【步骤2】获取到TransactionInterceptor

【步骤3】chain不为空,接着执行CglibMethodInvocation#proceed方法
chain有一个元素: TransactionInterceptor-事务拦截器;
接着执行 467行:retVal = (new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();

【补充】AopContext作用
【补充455行代码】: AopContext实际上是带有ThreadContext的容器对象,用于存储代理对象;
public final class AopContext {private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal("Current AOP proxy");private AopContext() {}public static Object currentProxy() throws IllegalStateException {Object proxy = currentProxy.get();if (proxy == null) {throw new IllegalStateException("Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available, and ensure that AopContext.currentProxy() is invoked in the same thread as the AOP invocation context.");} else {return proxy;}}@Nullablestatic Object setCurrentProxy(@Nullable Object proxy) {Object old = currentProxy.get();if (proxy != null) {currentProxy.set(proxy);} else {currentProxy.remove();}return old;}
}
【步骤4】CglibMethodInvocation#proceed方法
CglibMethodInvocation#proceed方法, 即Cglib方法调用类#proceed方法 (proceed=继续或进行或处理)
【CglibAopProxy#CglibMethodInvocation】
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method, Object[] arguments, @Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);}// 调用proceed @Nullablepublic Object proceed() throws Throwable {try {return super.proceed();} catch (RuntimeException var2) {throw var2;} catch (Exception var3) {if (!ReflectionUtils.declaresException(this.getMethod(), var3.getClass()) && !KotlinDetector.isKotlinType(this.getMethod().getDeclaringClass())) {throw new UndeclaredThrowableException(var3);} else {throw var3;}}}
}
【步骤5】调用ReflectiveMethodInvocation#proceed方法(反射方法调用类)
调用ReflectiveMethodInvocation#proceed方法, ReflectiveMethodInvocation=反射方法调用类
// ReflectiveMethodInvocation=反射方法调用类
// interceptorsAndDynamicMethodMatcher 是一个列表,包含一个元素 TransactionInterceptor
// currentInterceptorIndex 初始值=-1
public Object proceed() throws Throwable {if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return this.invokeJoinpoint();} else {Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// interceptorOrInterceptionAdvice 就是 TransactionInterceptor ,而不是 InterceptorAndDynamicMethodMatcherif (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;Class<?> targetClass = this.targetClass != null ? this.targetClass : this.method.getDeclaringClass();return dm.matcher().matches(this.method, targetClass, this.arguments) ? dm.interceptor().invoke(this) : this.proceed();} else {return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this); // 调用到这里 }}
}

获取到的interceptorOrInterceptionAdvice的属性如下:

【步骤6】调用 TransactionInterceptor#invoke(事务拦截器#invoke方法)
调用 TransactionInterceptor#invoke(ReflectiveMethodInvocation), 传入的入参this是ReflectiveMethodInvocation-反射方法调用对象(包装了 UserSupportImpl#saveNewUser方法的代理对象)
【TransactionInterceptor#invoke】
public Object invoke(MethodInvocation invocation) throws Throwable {Class<?> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;Method var10001 = invocation.getMethod();Objects.requireNonNull(invocation);return this.invokeWithinTransaction(var10001, targetClass, invocation::proceed);
}
上述 invocation::proceed中的invocation实际是 ReflectiveMethodInvocaion-反射方法调用类,ReflectiveMethodInvocaion封装了代理对象proxy,方法method等属性;
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {protected final Object proxy;@Nullableprotected final Object target;protected final Method method;protected Object[] arguments;@Nullableprivate final Class<?> targetClass;@Nullableprivate Map<String, Object> userAttributes;protected final List<?> interceptorsAndDynamicMethodMatchers;private int currentInterceptorIndex = -1;protected ReflectiveMethodInvocation(Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments, @Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {this.proxy = proxy;this.target = target;this.targetClass = targetClass;this.method = BridgeMethodResolver.findBridgedMethod(method);this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;}
【补充】TransactionInterceptor-事务拦截器源码
TransactionInterceptor继承自TransactionAspectSupport;
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {public TransactionInterceptor() {}public TransactionInterceptor(TransactionManager ptm, TransactionAttributeSource tas) {this.setTransactionManager(ptm);this.setTransactionAttributeSource(tas);}@Nullablepublic Object invoke(MethodInvocation invocation) throws Throwable {Class<?> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;Method var10001 = invocation.getMethod();Objects.requireNonNull(invocation);// 调用到这里, 注意最后一个入参是 invocation::proceed;return this.invokeWithinTransaction(var10001, targetClass, invocation::proceed);}private void writeObject(ObjectOutputStream oos) throws IOException {
//...}private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {// ...}
}
【步骤7】调用TransactionAspectSupport#invokeWithinTransaction方法
因为TransactionInterceptor 继承自TransactionAspectSupport; 而invokeWithinTransaction方法的最后一个入参invocation就是封装了目标方法,即UserSupportImpl#saveNewUser方法的包装对象ReflectiveMethodInvocation;

获取到的事务管理器类型是 JdbcTransactionManger, 而事务属性TransactionAttribute保存了注解@Transaction标注的方法的元数据,包括事务传播行为,隔离级别,超时时间,是否只读,事务管理器等属性; 而TransactionAttribute继承自TransactionDefinition-事务定义接口;
【TransactionAttribute】事务属性-TransactionAttribute定义
public interface TransactionAttribute extends TransactionDefinition {@NullableString getQualifier();Collection<String> getLabels();boolean rollbackOn(Throwable ex);
}
【TransactionAspectSupport#invokeWithinTransaction方法】执行到获取PlatformTransactionManager-平台事务管理器;

【步骤8】根据事务属性txAttr获取事务管理器,tm=JdbcTransactionManager
上述第7步执行到145行,接着判断tm(也就是JdbcTransactionManager)是否是ReactiveTransactionManager类型;
JdbcTransactionManager父类是DataSourceTransactionManager,而DataSourceTransactionManager父类是AbstractPlatformTransactionManager,而AbstractPlatformTransactionManager父类是PlatformTransactionManager;结论:tm(JdbcTransactionManager)不是CallbackPreferringPlatformTransactionManager,所以执行到160行;

又160行得到的ptm还是JdbcTransactionManager,与tm指向同一个对象,162行判断是否为CallbackPreferringPlatformTransactionManager类型不通过,接着执行第220行;
【补充】事务管理器是什么?
public class JdbcTransactionManager extends DataSourceTransactionManager;public class DataSourceTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, InitializingBean;public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, ConfigurableTransactionManager, Serializable;
【DataSourceTransactionManager】数据源事务管理器-方法列表
- doBegin-开启事务
- doCommit-提交事务
- doGetTransaction-获取事务
- doResume-恢复事务
- doRollback-回滚事务
- doSuspend-挂起事务;

【DataSourceTransactionManager父类AbstractPlatformTransactionManager】抽象平台事务管理器-部分方法列表
- doBegin 开启事务
- doCommit 提交
- doGetTransation 获取事务
- doResume 恢复事务
- doSuspend 挂起事务
- doRollback 回滚
- setNestedTransactionAllowed -设置允许嵌套事务;
【步骤9】TransactionAspectSupport#invokeWithinTransaction()-在事务中执行业务逻辑(非常重要)
1)TransactionAspectSupport#invokeWithinTransaction()-在事务中执行业务逻辑,具体步骤如下(跳过了分支判断):
- 步骤9.1:调用createTransactionIfNecessary方法,创建事务;
- 步骤9.2:调用invocation.proceedWithInvocation(),执行具体业务逻辑(执行目标方法);
- 步骤9.2.1(或有) : 抛出异常,执行completeTransactionAfterThrowing
- 步骤9.3:执行完成(无论是否抛出异常),调用cleanupTransactionInfo()
- 步骤9.4:判断返回值是否不为null 且 事务属性是否不为null
- 步骤9.5:调用commitTransactionAfterReturning(),提交事务;
【TransactionAspectSupport#invokeWithinTransaction()】 在事务中调用;上游是TransactionInterceptor,而TransactionInterceptor是TransactionAspectSupport的子类; 源码如下。
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable {TransactionAttributeSource tas = this.getTransactionAttributeSource();TransactionAttribute txAttr = tas != null ? tas.getTransactionAttribute(method, targetClass) : null;TransactionManager tm = this.determineTransactionManager(txAttr);if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager rtm) {// tm类型是JdbcTransactionManager,所以不会执行到这里// ... return txSupport.invokeWithinTransaction(method, targetClass, invocation, txAttr, rtm);} else {PlatformTransactionManager ptm = this.asPlatformTransactionManager(tm);String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);if (txAttr != null && ptm instanceof CallbackPreferringPlatformTransactionManager cpptm) {// ptm类型是JdbcTransactionManager,所以不会执行到这里// ...} else {// 程序执行到这里 // 1 创建事务,【非常重要】 TransactionInfo txInfo = this.createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);Object retVal;try {// 2 通过反射执行具体业务逻辑, invocation就是包装了业务方法UserSuuportImpl#saveUser()方法的调用对象 retVal = invocation.proceedWithInvocation();} catch (Throwable var22) {// 2.1 抛出异常 (或有)this.completeTransactionAfterThrowing(txInfo, var22);throw var22;} finally {// 3 最后清理事务信息 this.cleanupTransactionInfo(txInfo);}// 4 判断返回值是否不为null 且 事务属性是否不为null if (retVal != null && txAttr != null) {TransactionStatus status = txInfo.getTransactionStatus();if (status != null) {label185: {if (retVal instanceof Future) {// 5 若返回值为 Future类型(异步线程执行结果类)Future<?> future = (Future)retVal;if (future.isDone()) {try {future.get();} catch (ExecutionException var27) {if (txAttr.rollbackOn(var27.getCause())) {status.setRollbackOnly();}} catch (InterruptedException var28) {Thread.currentThread().interrupt();}break label185;}}if (vavrPresent && TransactionAspectSupport.VavrDelegate.isVavrTry(retVal)) {retVal = TransactionAspectSupport.VavrDelegate.evaluateTryFailure(retVal, txAttr, status);}}}}// 5 提交事务 this.commitTransactionAfterReturning(txInfo);return retVal;}}
}
【步骤9.1】按需创建事务-createTransactionIfNecessary()
TransactionAspectSupport#createTransactionIfNecessary()详情参见 spring声明式事务原理02-调用第1层@Transactional方法-按需创建事务createTransactionIfNecessary
根据事务管理器+事务属性+aop连接点(切点)创建事务,如下:
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, final String joinpointIdentification) {if (txAttr != null && ((TransactionAttribute)txAttr).getName() == null) {txAttr = new DelegatingTransactionAttribute((TransactionAttribute)txAttr) {public String getName() {return joinpointIdentification;}};}TransactionStatus status = null;if (txAttr != null) {if (tm != null) {// 通过事务管理器获取事务status = tm.getTransaction((TransactionDefinition)txAttr); } else if (this.logger.isDebugEnabled()) {this.logger.debug("Skipping transactional joinpoint [" + joinpointIdentification + "] because no transaction manager has been configured");}}// 准备事务信息TransactionInfo return this.prepareTransactionInfo(tm, (TransactionAttribute)txAttr, joinpointIdentification, status);
}

【补充】TransactionInfo事务信息定义
1)TransactionInfo是TransactionAspectSupport的 静态内部类,是一个聚合类,封装了事务相关的多个组件:
- transactionManager:事务管理器(封装了事务提交,回滚功能)
- TransactionAttribute:事务属性 (@Transaction注解元数据)
- joinpointIdentification:切点标识(被@Transaction标注的目标方法的全限定名称)
- TransactionStatus:事务状态 (封装获取事务状态的方法,如是否只读,是否回滚,是否保存点,事务是否完成,当前线程是否存在事务等)
- oldTransactionInfo-上一个事务信息对象;
其中 oldTransactionInfo-上一个事务信息对象,是bindToThread()方法与restoreThreadLocalStatus() 需要用到的;
protected static final class TransactionInfo {@Nullableprivate final PlatformTransactionManager transactionManager;@Nullableprivate final TransactionAttribute transactionAttribute;private final String joinpointIdentification;@Nullableprivate TransactionStatus transactionStatus;@Nullableprivate TransactionInfo oldTransactionInfo;public TransactionInfo(@Nullable PlatformTransactionManager transactionManager, @Nullable TransactionAttribute transactionAttribute, String joinpointIdentification) {this.transactionManager = transactionManager;this.transactionAttribute = transactionAttribute;this.joinpointIdentification = joinpointIdentification;}public PlatformTransactionManager getTransactionManager() {Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");return this.transactionManager;}@Nullablepublic TransactionAttribute getTransactionAttribute() {return this.transactionAttribute;}public String getJoinpointIdentification() {return this.joinpointIdentification;}public void newTransactionStatus(@Nullable TransactionStatus status) {this.transactionStatus = status;}@Nullablepublic TransactionStatus getTransactionStatus() {return this.transactionStatus;}public boolean hasTransaction() {return this.transactionStatus != null;}private void bindToThread() {this.oldTransactionInfo = (TransactionInfo)TransactionAspectSupport.transactionInfoHolder.get();TransactionAspectSupport.transactionInfoHolder.set(this);}private void restoreThreadLocalStatus() {TransactionAspectSupport.transactionInfoHolder.set(this.oldTransactionInfo);}
}// 事务信息持有器(transactionInfoHolder)是一个ThreadLocal对象,
// 用于保存当前事务信息,及上一个事务信息(挂起时),以便恢复上一个事务信息;
private static final ThreadLocal<TransactionInfo> transactionInfoHolder = new NamedThreadLocal("Current aspect-driven transaction");
事务信息持有器(transactionInfoHolder):是一个ThreadLocal对象,用于保存当前事务信息,及上一个事务信息(挂起时),以便恢复上一个事务信息;
【补充】TransactionStatus事务状态定义
1)TransactionStatus继承自 TransactionExecution, SavepointManager
2)TransactionStatus封装了事务状态方法,包括是否有保存点,当前线程是否存在事务,当前线程是否存在新事务,是否只读,设置回滚状态或判断是否回滚,事务是否完成等状态方法;
3)封装的事务方法包括:
- 保存点相关方法:包括 hasSavepoint , createSavepoint, rollbackToSavepoint, releaseSavepoint
- 事务相关方法: 包括hasTransaction, isNewTransaction, isReadOnly, setRollbackOnly, isRollbackOnly, isCompleted;
- 嵌套传播模式相关方法:isNested (嵌套模式底层原理是保存点)
public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {default boolean hasSavepoint() {return false;}default void flush() {}
}
// 事务执行
public interface TransactionExecution {default String getTransactionName() {return "";}default boolean hasTransaction() {return true;}default boolean isNewTransaction() {return true;}default boolean isNested() {return false;}default boolean isReadOnly() {return false;}default void setRollbackOnly() {throw new UnsupportedOperationException("setRollbackOnly not supported");}default boolean isRollbackOnly() {return false;}default boolean isCompleted() {return false;}
}
// 保存点管理器
public interface SavepointManager {Object createSavepoint() throws TransactionException;void rollbackToSavepoint(Object savepoint) throws TransactionException;void releaseSavepoint(Object savepoint) throws TransactionException;
}
【步骤9.2】执行目标方法
1)调用 invocation.proceedWithInvocation() 调用目标方法; invocation的类是 CglibMethodInvocation,即cglib代理方法调用类;

2)invocation.proceedWithInvocation():调用CglibMethodInvocation#proceed() 方法,又CglibMethodInvocation是封装了目标方法的cglib方法调用代理对象,所以接着会调用目标方法,即UserSupportImpl#saveNewUser()方法;

3)接着调用父类ReflectiveMethodInvocation的proceed()方法;

4)接着执行ReflectiveMethodInvocation#invokeJoinpoint方法,如下。

5)接着执行 AopUtils#invokeJoinpointUsingReflection() 方法
其中 originalMethod.invoke(target, args) 是通过反射调用具体的目标方法;

相关文章:
spring声明式事务原理01-调用第1层@Transactional方法(事务访问入口)
文章目录 【README】【步骤1】UserAppService调用userSupport.saveNewUser()【步骤2】获取到TransactionInterceptor【步骤3】chain不为空,接着执行CglibMethodInvocation#proceed方法【补充】AopContext作用 【步骤4】CglibMethodInvocation#proceed方法【步骤5】调…...
Qt-D指针与Q指针的设计哲学
文章目录 前言PIMLP与二进制兼容性D指针Q指针优化d指针继承Q_D和Q_Q 前言 在探索Qt源码的过程中会看到类的成员有一个d指针,d指针类型是一个private的类,这种设计模式称为PIMPL(pointer to implementation),本文根据Q…...
数据结构——单链表list
前言:大家好😍,本文主要介绍数据结构——单链表 目录 一、单链表 二、使用步骤 1.结构体定义 2.初始化 3.插入 3.1 头插 3.2 尾插 3.3 按位置插 四.删除 4.1头删 4.2 尾删 4.3 按位置删 4.4按值删 五 统计有效值个数 六 销毁…...
java 的标记接口RandomAccess使用方法
在 Java 中,RandomAccess 是一个标记接口(marker interface),用于标识实现该接口的 List 实现类支持快速(通常是常数时间复杂度 O(1))的随机访问。常见的实现类包括 ArrayList,而不包括 LinkedL…...
基于PHP的网店进销存管理系统(源码+lw+部署文档+讲解),源码可白嫖!
摘要 相比于以前的传统进销存管理方式,智能化的管理方式可以大幅降低进销存管理的运营人员成本,实现了进销存管理的标准化、制度化、程序化的管理,有效地防止了商品信息及仓库信息的随意管理,提高了信息的处理速度和精确度&#…...
Vue3 Pinia $subscribe localStorage的用法 Store的组合式写法
Vue3 Pinia $subscribe 可以用来监视Stroe数据的变化 localStorage的用法 localStorage中只能存字符串,所有对象要选转成json字符串 定义store时,从localStorage中读取数据talkList可能是字符串也可能是空数组 Store的组合式写法 直接使用reactiv…...
【PHP】获取PHP-FPM的状态信息
文章目录 一、前言二、环境三、过程1)修改PHP-FPM配置文件2)修改Nginx配置文件3)访问页面4)修改状态页面端口 一、前言 PHP-FPM内置有一个状态页面,通过这个页面可以获取到FPM的一些状态信息(见下图&#…...
(性能测试)性能测试工具 2.jmeter的环境搭建 3jmeter元件和4使用实例 5jmeter元件和参数化
目录 性能测试工具 性能测试工具 jemeter环境搭建 jmeter的常用目录介绍 jmeter修改语言和主题--jmeter界面的汉化 jmeter元件 jmeter元件和组件的介绍 jmeter的作用域原则 jmeter的执行顺序 案例:执行顺序 jmeter使用案例 jmeter线程组的介绍 jmeter…...
Java 大视界 -- 基于 Java 的大数据实时流处理中的窗口操作与时间语义详解(135)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
数据库的基本知识
目录 一、创建数据库和数据表1.1 创建数据库相关代码1.2 创建数据表1.3 约束条件1.3.1 主键约束1.3.2 非空约束1.3.3 唯一性约束1.3.4 默认约束1.3.5 自增字段 1.4 手工建表 二、数据查询功能2.1 sql 查询的7个关键词2.1.1 select2.1.2 from2.1.3 where2.1.4 group by2.1.5 hav…...
失败的面试经历(ʘ̥∧ʘ̥)
一.面向对象的三大特性 1.封装:将对象内部的属性私有化,外部对象不能够直接访问,但是可以提供一些可以使外部对象操作内部属性的方法。 2.继承:类与类之间会有一些相似之处,但也会有一些异处,使得他们与众…...
【Jmeter】使用教程
下载及安装 参考链接: JMeter下载及安装(附插件及中文包超详细) 参考链接: 【Jmeter】win 10 / win 11:Jmeter 下载、安装、汉化、新机迁移、版本更新(Jmeter 4 以上版本均适用) 分辨率的调整 参考链接: Jmeter5.3字…...
Android 7 及以上夜神模拟器,Fiddler 抓 https 包
文章目录 问题描述解决方案环境准备操作步骤1、导出 Fiddler 证书并修改成 .pem 和 .0 文件2、修改夜神模拟器配置3、打开夜神模拟器设备的 USB 调试选项4、将0725b47c.0证书放入夜神模拟器系统证书目录5、夜神模拟器 cmd 环境配置6、给 0725b47c.0 证书赋予权限7、打开 fiddle…...
全国医院数据可视化分析系统
【大数据】全国医院数据可视化分析系统 (完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 🏥 项目名:医疗导航神器!——《基于大数据的微医挂号网医院数据可视…...
音视频入门基础:RTCP专题(1)——RTCP官方文档下载
一、引言 实时传输控制协议(Real-time Transport Control Protocol或RTP Control Protocol或简写RTCP)是实时传输协议(RTP)的一个姐妹协议。RTCP由《RFC 3550》定义(取代废弃的《RFC 1889》)。RTP使用一个…...
蓝桥杯专项复习——结构体、输入输出
目录 结构体:排序 输入输出 结构体:排序 [NOIP2007]奖学金 #include<iostream> #include<cstring> #include<algorithm>using namespace std;const int N310; int n;struct Student {int chinese,math,eng,sum;int idx; }Stu[N];//定…...
工作记录 2017-01-06
工作记录 2017-01-06 序号 工作 相关人员 1 协助BPO进行Billing的工作。 修改CSV、EDI837的导入。 修改邮件上的问题。 更新RD服务器。 郝 修改的问题: 1、 In “Full Job Summary” (patient info.), sometime, the Visit->Facility is missed, then …...
探索 Rust 高效 Web 开发:Hyperlane 框架深度解析
探索 Rust 高效 Web 开发:Hyperlane 框架深度解析 在当今的 Web 开发领域,追求高性能、轻量级的框架一直是开发者们的不懈追求。对于 Rust 语言开发者而言,Hyperlane 框架正以其独特的魅力崭露头角,为构建现代 Web 服务提供了一种…...
LLM(2):准备构建 LLM
在了解大语言模型一文中,对 LLM 做了初步介绍,本文接续前一篇文章的内容,简要介绍 LLM 的应用和构建过程。 1.2 LLM 的应用 由于大型语言模型(LLMs)在解析和理解非结构化文本数据方面具备先进能力,它们在…...
pytest+allure+jenkins
本地运行参考:pytestallure 入门-CSDN博客 jenkins运行如下: 安装插件:allure 配置allure安装目录 配置pytest、allure 环境变量 配置流水线 进行build,结果如下 ,点击allure report 查看结果...
[蓝桥杯]花束搭配【算法赛】
题目链接 题意 n朵花 每朵花有两个属性a,b 如果两朵花满足 a i a j > b i b j a_ia_j>b_ib_j aiaj>bibj 就称为完美方案 求一共有多少种完美方案 ( i , j ) 与 ( j , i ) (i,j)与(j,i) (i,j)与(j,i)视为不同组合 思路 数据范围 1 ≤ n ≤ 2 1 0 5 1\…...
大模型架构全景解析:从Transformer到未来计算范式
1. Transformer 架构 核心模型 GPT-4、BERT、T5、LLaMA、通义千问、文心ERNIE 关键技术 多头注意力:GPT-4 使用 96 头注意力位置编码创新:LLaMA 采用 RoPE(旋转位置编码),Claude 3 引入 ALiBi归一化优化࿱…...
【linux篇】--linux常见指令
文章目录 一、Linux基本概念 二、Linux入门 1.目录结构 2.Linux命令 *Linux基础命令 ls命令的选项: 3.目录切换相关命令(cd & pwd) 4.相对&绝对路径和特殊路径符 4.1相对路径 4.2绝对路径 4.3 你特殊路径符 5.创建目录命令(mkdir) 6.…...
Kubernetes的组成和架构
Kubernetes(K8s)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。它由多个组件组成,这些组件可以分为两类:控制平面(Control Plane)组件和节点(Node࿰…...
ElementUI 表格中插入图片缩略图,鼠标悬停显示大图
如何在 ElementUI 的表格组件 Table 中插入图片缩略图,通过鼠标悬停显示大图?介绍以下2种方式: 方法1:直接在模板元素中插入 <template><el-table :data"tableData"><el-table-column label"图片…...
【实战ES】实战 Elasticsearch:快速上手与深度实践-附录-1-常用命令速查表-集群健康检查、索引生命周期管理、故障诊断命令
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 附录-常用命令速查表 1-Elasticsearch 运维命令速查表(集群健康检查、ILM管理、故障诊断)一、集群健康检查与监控1.1 集群健康状态核心命令1.2 节点级健康诊断…...
PlainUSR|LIA: 追求更快的卷积网络实现高效的超分辨率重建
PlainUSR|LIA: 追求更快的卷积网络实现高效的超分辨率重建 引言 在深度学习领域,图像处理始终是一个热门话题。而超分辨率重建(Super-Resolution Reconstruction, SR)作为其中一个重要的研究方向,旨在通过算法将低分辨率图像恢复…...
Linux 命令学习记录
Linux 命令详解与进阶指南 Linux 是一种广泛使用的开源操作系统,掌握 Linux 命令是开发者和系统管理员的必备技能。本文将详细介绍 Linux 的常用命令,并涵盖一些高级进阶技巧,帮助你更高效地使用 Linux。 目录 基础命令 文件与目录操作文本…...
Android之RecyclerView列表拖动排序
文章目录 前言一、效果图二、实现步骤1.xml布局2.activity代码3.adapter 总结 前言 随着需求的变化,很多地方需要加拖动改变顺序的需求,用RecyclerView就可以实现列表拖动排序,列如像朋友圈图片拖动排序,或者音乐播放器列表拖动排…...
C# WPF 基础知识学习(一)
一、WPF 简介 Windows Presentation Foundation(WPF)是微软推出的一款用于构建用户界面的框架,它为开发 Windows 桌面应用程序提供了统一的编程模型、语言和框架。WPF 将用户界面的设计与业务逻辑分离开来,采用了 XAML࿰…...
