电脑做服务器上传网站,贵阳建设工程招聘信息网站,404网站怎么打开,免费网站怎么做排名声明式事务和编程式事务对比#xff1a;
声明式事务#xff1a; 使用注解或XML配置的方式#xff0c;在代码中声明事务的属性和行为。通过AOP和代理模式实现#xff0c;将事务管理与业务逻辑代码解耦。适用于大多数情况#xff0c;简化了代码#xff0c;提高了可维护性和…声明式事务和编程式事务对比
声明式事务 使用注解或XML配置的方式在代码中声明事务的属性和行为。通过AOP和代理模式实现将事务管理与业务逻辑代码解耦。适用于大多数情况简化了代码提高了可维护性和可读性。常用的注解是Transactional可以应用在方法或类级别。 编程式事务 在代码中显式编写事务管理的代码逻辑。需要手动控制事务的开启、提交和回滚等操作。适用于需要更细粒度控制事务的情况或者在声明式事务不适用的情况下使用。可以使用编程式事务的API如Spring的TransactionTemplate或JDBC的事务API。
Spring 事务的本质其实就是数据库对事务的支持没有数据库的事务支持Spring 是无法提供事务功能的。对于纯 JDBC 操作数据库想要用到事务可以按照以下步骤进行编程式事务同理
1、获取连接 Connection con DriverManager.getConnection()2、开启事务 con.setAutoCommit(true/false);3、执行 CRUD4、提交事务/回滚事务 con.commit() / con.rollback();5、关闭连接 conn.close();当使用Spring的声明式事务后我们可以只要写CRUD即可其他由Spirng 自动完成。 本文主要讲解声明式事务 生效原理
下面是一个简单的示例用于说明 Spring 事务的生效原理
Service
public class MyService {Transactionalpublic void transferMoney(Account sourceAccount, Account targetAccount, double amount) {//省略逻辑处理}
}声明式事务就是使用我们常见的Transactional注解完成的声明式事务优点就在于让事务代码与业务代码解耦通过Spring中提供的声明式事务使用我们也可以发觉我们只需要编写业务代码即可而事务的管理基本不需要我们操心Spring就像使用了魔法一样帮我们自动完成了。
之所以那么神奇本质还是依靠Spring框架提供的Bean生命周期相关回调接口和AOP结合完成的简述如下: 这里思考下如何保证同个线程请求时数据库多个操作使用的是同个Connection 通过自动代理创建器依次尝试为每个放入容器中的bean尝试进行代理尝试进行代理的过程对于事务管理来说就是利用事务管理涉及到的增强器advisor,即TransactionAttributeSourceAdvisor判断当前增强器是否能够应用与当前bean上怎么判断呢 — advisor内部的pointCut喽 如果能够应用那么好为当前bean创建代理对象返回并且往代理对象内部添加一个TransactionInterceptor拦截器。此时我们再从容器中获取拿到的就是代理对象了当我们调用代理对象的方法时首先要经过代理对象内部拦截器链的处理处理完后最终才会调用被代理对象的方法。(这里其实就是责任链模式的应用)当TransactionInterceptor的invoke()方法被执行时它会先开启一个事务然后再调用目标方法。如果目标方法执行成功那么就会提交事务否则就会回滚事务。在整个事务过程中Spring会保证操作数据库时使用的是同一个连接。它是通过将一个数据库连接与一个ThreadLocal对象绑定起来然后在需要操作数据库时通过该ThreadLocal对象来获取连接的。这样就可以避免多个连接导致的数据不一致问题。 这里说下SpringBoot底层实现有一个AutoProxyRegistrar简单来说,AutoProxyRegistrar顾名思义就是开启了AOP代理 ProxyTransactionManagementConfiguration是一个配置类它又定义了另外三个bean BeanFactoryTransactionAttributeSourceAdvisor一个Advisor就是一个切面AnnotationTransactionAttributeSource相当于PointcutTransactionInterceptor相当于中的 Advice事务的拦截方法 AnnotationTransactionAttributeSource就是用来判断某个类上是否存在Transactional注解 或者判断某个方法上是否存在Transactional注解的。 TransactionInterceptor就是代理逻辑当某个类中存在Transactional注解时到时就产生一个 代理对象作为Bean代理对象在执行某个方法时最终就会进入到TransactionInterceptor的 invoke()方法。 对于被事务增强器TransactionAttributeSourceAdvisor代理的bean而言代理对象内部会存在一个TransactionInterceptor该拦截器内部构造了一个事务执行的模板流程:
protected Object invokeWithinTransaction(Method method, Nullable Class? targetClass,final InvocationCallback invocation) throws Throwable {//TransactionAttributeSource内部保存着当前类某个方法对应的TransactionAttribute---事务属性源//可以看做是一个存放TransactionAttribute与method方法映射的池子TransactionAttributeSource tas getTransactionAttributeSource();//获取当前事务方法对应的TransactionAttributefinal TransactionAttribute txAttr (tas ! null ? tas.getTransactionAttribute(method, targetClass) : null);//定位TransactionManagerfinal TransactionManager tm determineTransactionManager(txAttr);.....//类型转换为局部事务管理器PlatformTransactionManager ptm asPlatformTransactionManager(tm);final String joinpointIdentification methodIdentification(method, targetClass, txAttr);if (txAttr null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {//TransactionManager根据TransactionAttribute创建事务后返回//TransactionInfo封装了当前事务的信息--包括TransactionStatusTransactionInfo txInfo createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);Object retVal;try {//继续执行过滤器链---过滤链最终会调用目标方法//因此可以理解为这里是调用目标方法retVal invocation.proceedWithInvocation();}catch (Throwable ex) {//目标方法抛出异常则进行判断是否需要回滚completeTransactionAfterThrowing(txInfo, ex);throw ex;}finally {//清除当前事务信息cleanupTransactionInfo(txInfo);}...//正常返回,那么就正常提交事务呗(当然还是需要判断TransactionStatus状态先)commitTransactionAfterReturning(txInfo);return retVal;}...事务拦截器TransactionInterceptor的处理过程总结如下 方法调用前的处理事务拦截器在目标方法调用前执行一些预处理操作。这包括检查当前是否存在事务上下文TransactionContext如果不存在则创建新的事务上下文。事务上下文包含了事务的相关信息如事务的传播行为、隔离级别、超时设置等。事务拦截器还会根据事务定义的属性决定是否开启新的事务或者加入已有的事务。 方法调用事务拦截器将目标方法调用传递给实际的目标对象并执行目标方法。 方法调用后的处理在目标方法执行完成后事务拦截器会根据方法的执行结果决定是提交事务还是回滚事务。如果方法执行过程中发生了异常事务拦截器会触发事务回滚将事务恢复到调用该方法之前的状态。如果方法执行成功事务拦截器会触发事务提交将事务的操作永久保存到数据库。
事务拦截器通过使用事务管理器TransactionManager 来协调和控制事务的开始、提交和回滚操作。事务管理器负责和底层的数据访问框架如JDBC、Hibernate进行交互确保事务的一致性和隔离性。
事务拦截器是通过配置切面Aspect和切入点Pointcut 的方式与目标方法进行关联。切面定义了在何时何地应用事务拦截器而切入点则定义了哪些方法会被事务拦截器拦截。通过配置切面和切入点可以灵活地控制事务的应用范围。