Spring中,AOP到底是什么,扮演了一个什么样的角色?
文章内容输出来源:拉勾教育Java高薪训练营
我与拉勾教育不得不说的事 :
我参加拉勾教育Java高薪训练营已经三个月的时间了,回想起三个月前的迷茫与矛盾仍心有余悸。随着年龄的增长,当现实撑不起梦想,阅历追不上年龄的时候,我开始焦虑恐慌,我终于意识到技术这个行业,只有不断学习才能跟上大家的脚步,那些令人羡慕的大牛谁不是不管下班多晚都坚持学到半夜的人呢?比你厉害的人,还比你努力。我后悔这些年碌碌无为,也庆幸我还有机会弥补。
我尝试了很多方式的学习,也在某课堂、某云课堂上听过一些高级课、架构课,对比下来还是拉勾的这个深度对我帮助更大,既有基础知识,融会贯通,又有源码讲解,知识进阶,比如框架阶段会带着手写框架,然后分析整体架构,最后再撸源码,学习起来也很轻松,掌握的很快,肯定比自己啃书本,埋头苦干要容易的多,理解的更加深刻;更重要的是还有老师们的督促,同学间的鼓励,每天都能看到大家对技术的探讨,与大家一起讨论,即加深了理解,又开阔了眼界。在这样的氛围中,每天都想要学习,不知不觉已经坚持了这么久,拉勾教育使我摆脱了温水煮青蛙的状态,期待我会越变越好。
Spring必知必会 ===> AOP,到底代表了什么?
在了解AOP之前,我们要从OOP说起
1、关于OOP
1.1、什么是OOP?
OOP:Object Oriented Programming 面向对象编程。
与其对应的还有OOD(面向对象的设计),OOA(面向对象的分析)。
OOP有三⼤特征:封装、继承和多态
OOP是⼀种垂直继承体系,如下图
1.2、OOP有什么问题呢?
OOP编程思想可以解决⼤多数的代码重复问题,但是有⼀些情况是处理不了的,⽐如下⾯的在顶级⽗类
Animal中的多个⽅法中相同位置出现了重复代码,OOP就解决不了。
如图,这就出现了横切逻辑代码。什么是横切逻辑代码呢,在多个纵向(顺序)流程中出现的相同子流程代码,我们就称之为横切逻辑代码。通俗点来讲就是不同的方法出现了大段同样的代码,一般来讲,横切逻辑代码会出现在一般事务控制、权限校验、日志等功能的代码中。
横切逻辑代码造成两种问题。第一个就是会有大段重复代码;第二则是会造成方法的臃肿,业务代码和横切逻辑代码混杂在一起,造成难以维护的情况出现。
于是就有了AOP。
2、关于AOP
2.1、什么是AOP?
AOP: Aspect oriented Programming ⾯向切⾯编程/⾯向⽅⾯编程。
AOP是OOP的延续,它提出了横向抽取机制,将横切逻辑代码和业务逻辑代码拆分出来。
但如果只是普通的提取出一个公用方法,代码是拆分了,但耦合还是存在,因为每次还要调用这个公共方法,于是要解决的问题就变成了如何将横切逻辑代码悄无声息的加入到业务逻辑中。
AOP本质:在不改变原有业务逻辑的情况下增强横切逻辑,横切逻辑代码往往是权限校验代码、⽇志代
码、事务控制代码、性能监控代码。
2.2、AOP 业务主线
在讲解AOP术语之前,我们先来看⼀下下⾯这张图,它就是典型的OOP场景业务主线,描述的就是未采⽤AOP思想设计的程序,当我们红⾊框中圈定的⽅法时,会带来⼤量的重复劳动。程序中充斥着⼤量的重复代码,使我们程序的独⽴性很差。
下图则是采⽤了AOP思想设计的程序,它把红框部分的代码抽取出来的同时,运⽤动态代理技术,在运⾏期对需要使⽤的业务逻辑⽅法进⾏增强。
2.3、AOP 术语
**Joinpoint(连接点):**它指的是那些可以⽤于把增强代码加⼊到业务主线中的点,那么由上图中我们可以看出,这些点指的就是⽅法。在⽅法执⾏的前后通过动态代理技术加⼊增强的代码。在Spring框架AOP思想的技术实现中,也只⽀持⽅法类型的连接点。
**Pointcut(切⼊点):**它指的是那些已经把增强代码加⼊到业务主线进来之后的连接点。由上图中,我们看出表现层transfer ⽅法就只是连接点,因为判断访问权限的功能并没有对其增强。
**Advice(通知/增强):**它指的是切⾯类中⽤于提供增强功能的⽅法。并且不同的⽅法增强的时机是不⼀样的。⽐如,开启事务肯定要在业务⽅法执⾏之前执⾏;提交事务要在业务⽅法正常执⾏之后执⾏,⽽回滚事务要在业务⽅法执⾏产⽣异常之后执⾏等等。那么这些就是通知的类型。其分类有:前置通知 后置通知 异常通知 最终通知 环绕通知。
**Target(⽬标对象):**它指的是代理的⽬标对象。即被代理对象。
**Proxy(代理):**它指的是⼀个类被AOP织⼊增强后,产⽣的代理类。即代理对象。
**Weaving(织⼊):**它指的是把增强应⽤到⽬标对象来创建新的代理对象的过程。spring采⽤动态代
理织⼊,⽽AspectJ采⽤编译期织⼊和类装载期织⼊。
**Aspect(切⾯):**它指定是增强的代码所关注的⽅⾯,把这些相关的增强代码定义到⼀个类中,这个类就是切⾯类。例如,事务切⾯,它⾥⾯定义的⽅法就是和事务相关的,像开启事务,提交事务,回滚事务等等,不会定义其他与事务⽆关的⽅法。我们前⾯的案例中 TrasnactionManager 就是⼀个切⾯。
而在实际场景中:
**连接点:**⽅法开始时、结束时、正常运⾏完毕时、⽅法异常时等这些特殊的时机点,我们称之为连接
点,项⽬中每个⽅法都有连接点,连接点是⼀种候选点。
**切⼊点:**指定AOP思想想要影响的具体⽅法是哪些,描述感兴趣的⽅法。
Advice增强:
第⼀个层次:指的是横切逻辑
第⼆个层次:⽅位点(在某⼀些连接点上加⼊横切逻辑,那么这些连接点就叫做⽅位点,描述的是具体的特殊时机)
**Aspect切⾯:**切⾯概念是对上述概念的⼀个综合
Aspect切⾯= 切⼊点+增强 = 切⼊点(锁定⽅法) + ⽅位点(锁定⽅法中的特殊时机)+ 横切逻辑
上述所有的术语,⽬的就是为了锁定要在哪个地⽅插⼊什么横切逻辑代码。
3、Spring的AOP实现
3.1、Spring中AOP的代理选择
Spring 实现AOP思想使⽤的是动态代理技术。
默认情况下,Spring会根据被代理对象是否实现接⼝来选择使⽤JDK还是CGLIB。当被代理对象没有实现任何接⼝时,Spring会选择CGLIB。当被代理对象实现了接⼝,Spring会选择JDK官⽅的代理技术,不过我们可以通过配置的⽅式,让Spring强制使⽤CGLIB。
3.2、Spring中AOP的配置方式
在Spring的AOP配置中,也和IoC配置⼀样,⽀持3类配置方式。
第⼀类:使⽤XML配置
第⼆类:使⽤XML+注解组合配置
第三类:使⽤纯注解配置
3.2.1、XML 模式
Spring是模块化开发的框架,使⽤aop就引⼊aop的jar
maven坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
AOP 核⼼配置
<!--
Spring基于XML的AOP配置前期准备:
在spring的配置⽂件中加⼊aop的约束
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
Spring基于XML的AOP配置步骤:
第⼀步:把通知Bean交给Spring管理
第⼆步:使⽤aop:config开始aop的配置
第三步:使⽤aop:aspect配置切⾯
第四步:使⽤对应的标签配置通知的类型
⼊⻔案例采⽤前置通知,标签为aop:before
-->
<!--把通知bean交给spring来管理-->
<bean id="logUtil" class="com.lagou.utils.LogUtil"></bean>
<!--开始aop的配置-->
<aop:config>
<!--配置切⾯-->
<aop:aspect id="logAdvice" ref="logUtil">
<!--配置前置通知-->
<aop:before method="printLog" pointcut="execution(public * com.lagou.service.impl.TransferServiceImpl.updateAccountByCardNo(com.lagou.pojo.Account))"></aop:before>
</aop:aspect>
</aop:config>
关于切⼊点表达式
上述配置实现了对 TransferServiceImpl 的 updateAccountByCardNo ⽅法进⾏增强,在其执⾏之前,输出了记录⽇志的语句。这⾥⾯,我们接触了⼀个⽐较陌⽣的名称:切⼊点表达式。它也称为AspectJ切⼊点表达式,指的是遵循特定语法结构的字符串,其作⽤是⽤于对符合语法格式的连接点进⾏增强。它是AspectJ表达式的⼀部分。
关于AspectJ
AspectJ是⼀个基于Java语⾔的AOP框架,Spring框架从2.0版本之后集成了AspectJ框架中切⼊点表达式的部分,开始⽀持AspectJ切⼊点表达式。
全限定⽅法名 访问修饰符 返回值 包名.包名.包名.类名.⽅法名(参数列表)
全匹配⽅式:
public void com.lagou.service.impl.TransferServiceImpl.updateAccountByCardNo(com.lagou.pojo.Account)
访问修饰符可以省略:
void com.lagou.service.impl.TransferServiceImpl.updateAccountByCardNo(com.lagou.pojo.Account)
返回值可以使⽤“*”,表示任意返回值:
* com.lagou.service.impl.TransferServiceImpl.updateAccountByCardNo(com.lagou.pojo.Account)
包名可以使⽤“.”表示任意包,但是有⼏级包,必须写⼏个
* ....TransferServiceImpl.updateAccountByCardNo(com.lagou.pojo.Account)
包名可以使⽤“..”表示当前包及其⼦包
* ..TransferServiceImpl.updateAccountByCardNo(com.lagou.pojo.Account)
类名和⽅法名,都可以使⽤.表示任意类,任意⽅法
* ...(com.lagou.pojo.Account)
参数列表,可以使⽤具体类型
基本类型直接写类型名称 : int
引⽤类型必须写全限定类名:java.lang.String
参数列表可以使⽤*,表示任意参数类型,但是必须有参数
* *..*.*(*)
参数列表可以使⽤..,表示有⽆参数均可。有参数可以是任意类型
* *..*.*(..)
全通配⽅式:
* *..*.*(..)
3.2.2、XML+注解模式
XML 中开启 Spring 对注解 AOP 的⽀持
<!--开启spring对注解aop的⽀持-->
<aop:aspectj-autoproxy/>
注解使⽤:
- 第⼀步:编写⼀个⽅法
- 第⼆步:在⽅法使⽤@Pointcut注解
- 第三步:给注解的value属性提供切⼊点表达式
3.2.3、注解模式
在使⽤注解驱动开发aop时,开启 Spring 对注解 AOP 的⽀持注解如下:
@Configuration
@ComponentScan("com.lagou")
@EnableAspectJAutoProxy //开启spring对注解AOP的⽀持
public class SpringConfiguration {}
4、Spring 声明式事务的⽀持
**编程式事务:**在业务代码中添加事务控制代码,这样的事务控制机制就叫做编程式事务
**声明式事务:**通过xml或者注解配置的⽅式达到事务控制的⽬的,叫做声明式事务
4.1、事务
4.1.1、事务的概念
事务指逻辑上的⼀组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功。从⽽确保了数据的准确与安全。
例如:A——B转帐,对应于如下两条sql语句:
/*转出账户减钱*/
update account set money=money-100 where name=‘a’;
/**转⼊账户加钱*/
update account set money=money+100 where name=‘b’;
这两条语句的执⾏,要么全部成功,要么全部不成功。
4.1.2、事务的四⼤特性
原⼦性(Atomicity) 原⼦性是指事务是⼀个不可分割的⼯作单位,事务中的操作要么都发⽣,要么都不发⽣。
从操作的⻆度来描述,事务中的各个操作要么都成功要么都失败
⼀致性(Consistency) 事务必须使数据库从⼀个⼀致性状态变换到另外⼀个⼀致性状态。例如转账前A有1000,B有1000。转账后A+B也得是2000。⼀致性是从数据的⻆度来说的,(1000,1000) (900,1100),不应该出现(900,1000)
隔离性(Isolation) 事务的隔离性是多个⽤户并发访问数据库时,数据库为每⼀个⽤户开启的事务,每个事务不能被其他事务的操作数据所⼲扰,多个并发事务之间要相互隔离。
⽐如:事务1给员⼯涨⼯资2000,但是事务1尚未被提交,员⼯发起事务2查询⼯资,发现⼯资涨了2000
块钱,读到了事务1尚未提交的数据(脏读)
持久性(Durability)
持久性是指⼀个事务⼀旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发⽣故障也不应该对其有任何影响。
4.1.3、事务的隔离级别
不考虑隔离级别,会出现以下情况:(以下情况全是错误的,也即为隔离级别在解决事务并发问题)
脏读:⼀个线程中的事务读到了另外⼀个线程中未提交的数据。
不可重复读:⼀个线程中的事务读到了另外⼀个线程中已经提交的update的数据(前后内容不⼀样)
场景:
员⼯A发起事务1,查询⼯资,⼯资为1w,此时事务1尚未关闭
财务⼈员发起了事务2,给员⼯A张了2000块钱,并且提交了事务
员⼯A通过事务1再次发起查询请求,发现⼯资为1.2w,原来读出来1w读不到了,叫做不可重复读
虚读(幻读):⼀个线程中的事务读到了另外⼀个线程中已经提交的insert或者delete的数据(前后条数不⼀样)
场景:
事务1查询所有⼯资为1w的员⼯的总数,查询出来了10个⼈,此时事务尚未关闭
事务2财务⼈员发起,新来员⼯,⼯资1w,向表中插⼊了2条数据,并且提交了事务
事务1再次查询⼯资为1w的员⼯个数,发现有12个⼈,⻅了⻤了
数据库共定义了四种隔离级别:
Serializable(串⾏化):可避免脏读、不可重复读、虚读情况的发⽣。(串⾏化) 最⾼
Repeatable read(可重复读):可避免脏读、不可重复读情况的发⽣。(幻读有可能发⽣) 第⼆该机制下会对要update的⾏进⾏加锁
Read committed(读已提交):可避免脏读情况发⽣。不可重复读和幻读⼀定会发⽣。 第三
Read uncommitted(读未提交):最低级别,以上情况均⽆法保证。(读未提交) 最低
注意:级别依次升⾼,效率依次降低
MySQL的默认隔离级别是:REPEATABLE READ
查询当前使⽤的隔离级别: select @@tx_isolation;
设置MySQL事务的隔离级别: set session transaction isolation level xxx; (设置的是当前mysql连接会话的,并不是永久改变的)
5.1.4 事务的传播⾏为
事务往往在service层进⾏控制,如果出现service层⽅法A调⽤了另外⼀个service层⽅法B,A和B⽅法本身都已经被添加了事务控制,那么A调⽤B的时候,就需要进⾏事务的⼀些协商,这就叫做事务的传播⾏为。
A调⽤B,我们站在B的⻆度来观察来定义事务的传播⾏为
PROPAGATION_REQUIRED 如果当前没有事务,就新建⼀个事务,如果已经存在⼀个事务中,加⼊到这个事务中。这是最常⻅的选择。
PROPAGATION_SUPPORTS ⽀持当前事务,如果当前没有事务,就以⾮事务⽅式执⾏。
PROPAGATION_MANDATORY 使⽤当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED 以⾮事务⽅式执⾏操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER 以⾮事务⽅式执⾏,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执⾏。如果当前没有事务,则执⾏与PROPAGATION_REQUIRED类似的操作。
这不禁让我想到一个好玩的问题,如果A、B都有事务,A调用B,事务传播行为是PROPAGATION_REQUIRED,然后A在调用B的地方包住了一个大的Try-Catch,这种情况下,B出现了异常,事务会回滚么?为什么?
还有一个,就是A、B在同一个类中,A直接调用B,包住了一个大的Try-Catch,这种情况下,B出现了异常,事务会回滚么?为什么?
欢迎在评论区讨论哦(^_−)☆。
4.2、Spring声明式事务控制
声明式事务很⽅便,尤其纯注解模式,仅仅⼏个注解就能控制事务了
思考:这些注解都做了什么?好神奇!
@EnableTransactionManagement @Transactional
4.2.1、@EnableTransactionManagement
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
@EnableTransactionManagement 注解使⽤ @Import 标签引⼊了TransactionManagementConfigurationSelector类,这个类⼜向容器中导⼊了两个重要的组件
4.2.2、加载事务控制组件
AutoProxyRegistrar
AutoProxyRegistrar 类的 registerBeanDefinitions ⽅法中⼜注册了⼀个组件
进⼊ AopConfigUtils.registerAutoProxyCreatorIfNecessary ⽅法
发现最终,注册了⼀个叫做 InfrastructureAdvisorAutoProxyCreator 的 Bean,⽽这个类是AbstractAutoProxyCreator 的⼦类,实现了 SmartInstantiationAwareBeanPostProcessor 接⼝
public class InfrastructureAdvisorAutoProxyCreator extends
AbstractAdvisorAutoProxyCreator
public abstract class AbstractAdvisorAutoProxyCreator extends
AbstractAutoProxyCreator
public abstract class AbstractAutoProxyCreator extends
ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
继承体系结构图如下
它实现了SmartInstantiationAwareBeanPostProcessor,说明这是⼀个后置处理器,⽽且跟
spring AOP 开启@EnableAspectJAutoProxy 时注册的 AnnotationAwareAspectJProxyCreator实
现的是同⼀个接⼝,所以说,声明式事务是 springAOP 思想的⼀种应⽤
ProxyTransactionManagementConfiguration 组件
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.transaction.annotation;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.transaction.config.TransactionManagementConfigUtils;
import org.springframework.transaction.interceptor.BeanFactoryTransactionAttribut
eSourceAdvisor;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;
/**
* {@code @Configuration} class that registers the Spring infrastructure
beans
* necessary to enable proxy-based annotation-driven transaction
management.
*
* @author Chris Beams
* @since 3.1
* @see EnableTransactionManagement
* @see TransactionManagementConfigurationSelector
*/
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor()
{
// 事务增强器
BeanFactoryTransactionAttributeSourceAdvisor advisor = new
BeanFactoryTransactionAttributeSourceAdvisor();
// 向事务增强器中注⼊ 属性解析器 transactionAttributeSource
advisor.setTransactionAttributeSource(transactionAttributeSource());
// 向事务增强器中注⼊ 事务拦截器 transactionInterceptor
advisor.setAdvice(transactionInterceptor());
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
// 属性解析器 transactionAttributeSource
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
// 事务拦截器 transactionInterceptor
public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
ProxyTransactionManagementConfiguration是⼀个容器配置类,注册了⼀个组件transactionAdvisor,称为事务增强器,然后在这个事务增强器中⼜注⼊了两个属性:transactionAttributeSource,即属性解析器ransactionAttributeSource 和 事务拦截器transactionInterceptor
属性解析器 AnnotationTransactionAttributeSource 部分源码如下
属性解析器有⼀个成员变量是annotationParsers,是⼀个集合,可以添加多种注解解析器(TransactionAnnotationParser),我们关注 Spring 的注解解析器,部分源码如下
属性解析器的作⽤之⼀就是⽤来解析@Transaction注解。
TransactionInterceptor 事务拦截器,部分源码如下
上述组件如何关联起来的?
事务拦截器实现了MethodInterceptor接⼝,追溯⼀下上⾯提到的
InfrastructureAdvisorAutoProxyCreator后置处理器,它会在代理对象执⾏⽬标⽅法的时候
获取其拦截器链,⽽拦截器链就是这个TransactionInterceptor,这就把这两个组件联系起
来;
构造⽅法传⼊PlatformTransactionManager(事务管理器)、TransactionAttributeSource(属
性解析器),但是追溯⼀下上⾯贴的ProxyTransactionManagementConfiguration的源码,
在注册事务拦截器的时候并没有调⽤这个带参构造⽅法,⽽是调⽤的⽆参构造⽅法,然后再
调⽤set⽅法注⼊这两个属性,效果⼀样。
invokeWithinTransaction ⽅法,部分源码如下(关注1、2、3、4 标注处)
4.2.3、Spring声明式事务总结
@EnableTransactionManagement 注解
1)通过@import引⼊了TransactionManagementConfigurationSelector类,它的selectImports⽅法导⼊了另外两个类:AutoProxyRegistrar和ProxyTransactionManagementConfiguration。
2)AutoProxyRegistrar类分析
⽅法registerBeanDefinitions中,引⼊了其他类,通过AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)引⼊InfrastructureAdvisorAutoProxyCreator,它继承了AbstractAutoProxyCreator,是⼀个后置处理器类。
3)ProxyTransactionManagementConfiguration 是⼀个添加了@Configuration注解的配置类(注册bean)注册事务增强器(注⼊属性解析器、事务拦截器)。
属性解析器:AnnotationTransactionAttributeSource,内部持有了⼀个解析器集合Set annotationParsers;具体使⽤的是SpringTransactionAnnotationParser解析器,⽤来解析。
@Transactional的事务属性
事务拦截器:TransactionInterceptor实现了MethodInterceptor接⼝,该通⽤拦截会在产⽣代理对象之前和aop增强合并,最终⼀起影响到代理对象
TransactionInterceptor的invoke⽅法中invokeWithinTransaction会触发原有业务逻辑调⽤(增强事务)
现在,大家应该知道上面那两个问题的答案了吧,分享出来吧。
ructureAdvisorAutoProxyCreator,它继承了AbstractAutoProxyCreator,是⼀个后置处理器类。
3)ProxyTransactionManagementConfiguration 是⼀个添加了@Configuration注解的配置类(注册bean)注册事务增强器(注⼊属性解析器、事务拦截器)。
属性解析器:AnnotationTransactionAttributeSource,内部持有了⼀个解析器集合Set annotationParsers;具体使⽤的是SpringTransactionAnnotationParser解析器,⽤来解析。
@Transactional的事务属性
事务拦截器:TransactionInterceptor实现了MethodInterceptor接⼝,该通⽤拦截会在产⽣代理对象之前和aop增强合并,最终⼀起影响到代理对象
TransactionInterceptor的invoke⽅法中invokeWithinTransaction会触发原有业务逻辑调⽤(增强事务)
现在,大家应该知道上面那两个问题的答案了吧,分享出来吧。
转载:https://blog.csdn.net/xin123098/article/details/107873717