当前位置: 首页 > article >正文

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不为空&#xff0c;接着执行CglibMethodInvocation#proceed方法【补充】AopContext作用 【步骤4】CglibMethodInvocation#proceed方法【步骤5】调…...

Qt-D指针与Q指针的设计哲学

文章目录 前言PIMLP与二进制兼容性D指针Q指针优化d指针继承Q_D和Q_Q 前言 在探索Qt源码的过程中会看到类的成员有一个d指针&#xff0c;d指针类型是一个private的类&#xff0c;这种设计模式称为PIMPL&#xff08;pointer to implementation&#xff09;&#xff0c;本文根据Q…...

数据结构——单链表list

前言&#xff1a;大家好&#x1f60d;&#xff0c;本文主要介绍数据结构——单链表 目录 一、单链表 二、使用步骤 1.结构体定义 2.初始化 3.插入 3.1 头插 3.2 尾插 3.3 按位置插 四.删除 4.1头删 4.2 尾删 4.3 按位置删 4.4按值删 五 统计有效值个数 六 销毁…...

java 的标记接口RandomAccess使用方法

在 Java 中&#xff0c;RandomAccess 是一个标记接口&#xff08;marker interface&#xff09;&#xff0c;用于标识实现该接口的 List 实现类支持快速&#xff08;通常是常数时间复杂度 O(1)&#xff09;的随机访问。常见的实现类包括 ArrayList&#xff0c;而不包括 LinkedL…...

基于PHP的网店进销存管理系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 相比于以前的传统进销存管理方式&#xff0c;智能化的管理方式可以大幅降低进销存管理的运营人员成本&#xff0c;实现了进销存管理的标准化、制度化、程序化的管理&#xff0c;有效地防止了商品信息及仓库信息的随意管理&#xff0c;提高了信息的处理速度和精确度&#…...

Vue3 Pinia $subscribe localStorage的用法 Store的组合式写法

Vue3 Pinia $subscribe 可以用来监视Stroe数据的变化 localStorage的用法 localStorage中只能存字符串&#xff0c;所有对象要选转成json字符串 定义store时&#xff0c;从localStorage中读取数据talkList可能是字符串也可能是空数组 Store的组合式写法 直接使用reactiv…...

【PHP】获取PHP-FPM的状态信息

文章目录 一、前言二、环境三、过程1&#xff09;修改PHP-FPM配置文件2&#xff09;修改Nginx配置文件3&#xff09;访问页面4&#xff09;修改状态页面端口 一、前言 PHP-FPM内置有一个状态页面&#xff0c;通过这个页面可以获取到FPM的一些状态信息&#xff08;见下图&#…...

(性能测试)性能测试工具 2.jmeter的环境搭建 3jmeter元件和4使用实例 5jmeter元件和参数化

目录 性能测试工具 性能测试工具 jemeter环境搭建 jmeter的常用目录介绍 jmeter修改语言和主题--jmeter界面的汉化 jmeter元件 jmeter元件和组件的介绍 jmeter的作用域原则 jmeter的执行顺序 案例&#xff1a;执行顺序 jmeter使用案例 jmeter线程组的介绍 jmeter…...

Java 大视界 -- 基于 Java 的大数据实时流处理中的窗口操作与时间语义详解(135)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

数据库的基本知识

目录 一、创建数据库和数据表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.封装&#xff1a;将对象内部的属性私有化&#xff0c;外部对象不能够直接访问&#xff0c;但是可以提供一些可以使外部对象操作内部属性的方法。 2.继承&#xff1a;类与类之间会有一些相似之处&#xff0c;但也会有一些异处&#xff0c;使得他们与众…...

【Jmeter】使用教程

下载及安装 参考链接: JMeter下载及安装&#xff08;附插件及中文包超详细&#xff09; 参考链接: 【Jmeter】win 10 / win 11&#xff1a;Jmeter 下载、安装、汉化、新机迁移、版本更新&#xff08;Jmeter 4 以上版本均适用&#xff09; 分辨率的调整 参考链接: Jmeter5.3字…...

Android 7 及以上夜神模拟器,Fiddler 抓 https 包

文章目录 问题描述解决方案环境准备操作步骤1、导出 Fiddler 证书并修改成 .pem 和 .0 文件2、修改夜神模拟器配置3、打开夜神模拟器设备的 USB 调试选项4、将0725b47c.0证书放入夜神模拟器系统证书目录5、夜神模拟器 cmd 环境配置6、给 0725b47c.0 证书赋予权限7、打开 fiddle…...

全国医院数据可视化分析系统

【大数据】全国医院数据可视化分析系统 &#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 &#x1f3e5; 项目名&#xff1a;医疗导航神器&#xff01;——《基于大数据的微医挂号网医院数据可视…...

音视频入门基础:RTCP专题(1)——RTCP官方文档下载

一、引言 实时传输控制协议&#xff08;Real-time Transport Control Protocol或RTP Control Protocol或简写RTCP&#xff09;是实时传输协议&#xff08;RTP&#xff09;的一个姐妹协议。RTCP由《RFC 3550》定义&#xff08;取代废弃的《RFC 1889》&#xff09;。RTP使用一个…...

蓝桥杯专项复习——结构体、输入输出

目录 结构体&#xff1a;排序 输入输出 结构体&#xff1a;排序 [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服务器。 郝 修改的问题&#xff1a; 1、 In “Full Job Summary” (patient info.), sometime, the Visit->Facility is missed, then …...

探索 Rust 高效 Web 开发:Hyperlane 框架深度解析

探索 Rust 高效 Web 开发&#xff1a;Hyperlane 框架深度解析 在当今的 Web 开发领域&#xff0c;追求高性能、轻量级的框架一直是开发者们的不懈追求。对于 Rust 语言开发者而言&#xff0c;Hyperlane 框架正以其独特的魅力崭露头角&#xff0c;为构建现代 Web 服务提供了一种…...

LLM(2):准备构建 LLM

在了解大语言模型一文中&#xff0c;对 LLM 做了初步介绍&#xff0c;本文接续前一篇文章的内容&#xff0c;简要介绍 LLM 的应用和构建过程。 1.2 LLM 的应用 由于大型语言模型&#xff08;LLMs&#xff09;在解析和理解非结构化文本数据方面具备先进能力&#xff0c;它们在…...

pytest+allure+jenkins

本地运行参考&#xff1a;pytestallure 入门-CSDN博客 jenkins运行如下&#xff1a; 安装插件&#xff1a;allure 配置allure安装目录 配置pytest、allure 环境变量 配置流水线 进行build,结果如下 ,点击allure report 查看结果...

[蓝桥杯]花束搭配【算法赛】

题目链接 题意 n朵花 每朵花有两个属性a,b 如果两朵花满足 a i a j > b i b j a_ia_j>b_ib_j ai​aj​>bi​bj​ 就称为完美方案 求一共有多少种完美方案 ( 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 关键技术 多头注意力&#xff1a;GPT-4 使用 96 头注意力位置编码创新&#xff1a;LLaMA 采用 RoPE&#xff08;旋转位置编码&#xff09;&#xff0c;Claude 3 引入 ALiBi归一化优化&#xff1…...

【linux篇】--linux常见指令

文章目录 一、Linux基本概念 二、Linux入门 1.目录结构 2.Linux命令 *Linux基础命令 ls命令的选项&#xff1a; 3.目录切换相关命令&#xff08;cd & pwd) 4.相对&绝对路径和特殊路径符 4.1相对路径 4.2绝对路径 4.3 你特殊路径符 5.创建目录命令&#xff08;mkdir) 6.…...

Kubernetes的组成和架构

Kubernetes&#xff08;K8s&#xff09;是一个开源的容器编排平台&#xff0c;用于自动化部署、扩展和管理容器化应用程序。它由多个组件组成&#xff0c;这些组件可以分为两类&#xff1a;控制平面&#xff08;Control Plane&#xff09;组件和节点&#xff08;Node&#xff0…...

ElementUI 表格中插入图片缩略图,鼠标悬停显示大图

如何在 ElementUI 的表格组件 Table 中插入图片缩略图&#xff0c;通过鼠标悬停显示大图&#xff1f;介绍以下2种方式&#xff1a; 方法1&#xff1a;直接在模板元素中插入 <template><el-table :data"tableData"><el-table-column label"图片…...

【实战ES】实战 Elasticsearch:快速上手与深度实践-附录-1-常用命令速查表-集群健康检查、索引生命周期管理、故障诊断命令

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 附录-常用命令速查表 1-Elasticsearch 运维命令速查表&#xff08;集群健康检查、ILM管理、故障诊断&#xff09;一、集群健康检查与监控1.1 集群健康状态核心命令1.2 节点级健康诊断…...

PlainUSR|LIA: 追求更快的卷积网络实现高效的超分辨率重建

PlainUSR|LIA: 追求更快的卷积网络实现高效的超分辨率重建 引言 在深度学习领域&#xff0c;图像处理始终是一个热门话题。而超分辨率重建&#xff08;Super-Resolution Reconstruction, SR&#xff09;作为其中一个重要的研究方向&#xff0c;旨在通过算法将低分辨率图像恢复…...

Linux 命令学习记录

Linux 命令详解与进阶指南 Linux 是一种广泛使用的开源操作系统&#xff0c;掌握 Linux 命令是开发者和系统管理员的必备技能。本文将详细介绍 Linux 的常用命令&#xff0c;并涵盖一些高级进阶技巧&#xff0c;帮助你更高效地使用 Linux。 目录 基础命令 文件与目录操作文本…...

Android之RecyclerView列表拖动排序

文章目录 前言一、效果图二、实现步骤1.xml布局2.activity代码3.adapter 总结 前言 随着需求的变化&#xff0c;很多地方需要加拖动改变顺序的需求&#xff0c;用RecyclerView就可以实现列表拖动排序&#xff0c;列如像朋友圈图片拖动排序&#xff0c;或者音乐播放器列表拖动排…...

C# WPF 基础知识学习(一)

一、WPF 简介 Windows Presentation Foundation&#xff08;WPF&#xff09;是微软推出的一款用于构建用户界面的框架&#xff0c;它为开发 Windows 桌面应用程序提供了统一的编程模型、语言和框架。WPF 将用户界面的设计与业务逻辑分离开来&#xff0c;采用了 XAML&#xff0…...