ProxyTransactionManagementConfiguration 这个类是一个普通的 Configuration 配置类,在加载它的过程中同样会扫描到它里面的 beanmethod 进行加载,这里面的几个也都比较重要,我们看看它的源码
@Configuration(proxyBeanMethods = false)``@Role(BeanDefinition.ROLE_INFRASTRUCTURE)``//会扫描它内部的beanMethod,进行加载,关于这beanmethod的所用,这里就不展看说了,具体在讲解到事务执行流程的时候再说吧``public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
//注意:这个方法的两个入参是后面两个beanmethod方法的bean对象
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
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
//这个类主要是过滤候选类是否可以被用来事务增强,并返回对应的事务属性对象
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
//这个主要就是事务拦截器,事务相关的就会交给它去处理
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
复制代码
到这里,我们看看主要加载的 bean 都有哪些
- InfrastructureAdvisorAutoProxyCreator,BeanFactoryTransactionAttributeSourceAdvisor 主要是这两个 TransactionAttributeSource,TransactionInterceptor 这两个注入到了 BeanFactoryTransactionAttributeSourceAdvisor 这个对象中,就不单独说了,应该可以通过 BeanFactoryTransactionAttributeSourceAdvisor 这个 bean 对象获取到
2. InfrastructureAdvisorAutoProxyCreator 类
===========================================
我们看看 InfrastructureAdvisorAutoProxyCreator 的继承关系
这个类的继承关系是比较复杂的,我们只挑选我们最关注的来分析吧。
从图上可以看到 InfrastructureAdvisorAutoProxyCreator 类间接实现了 BeanPostProcessor 接口,这个接口主要的所用是对每一个 bean 对象初始化前后做增强。在每一个 bean 初始化前调用 postProcessBeforeInitialization,初始化后调用 postProcessAfterInitialization。
注意:这里说的 bean 初始化前后并不是创建对象前后,这些操作肯定都是在创建对象之后
3.BeanFactoryTransactionAttributeSourceAdvisor 类
================================================
我们现在看看 BeanFactoryTransactionAttributeSourceAdvisor 类,首先看下它的继承关系
可以看到这个类也实现了 Advisor 接口,这个接口主要是用来承载 Advice,而 Advice 主要是用来执行作为拦截器来使用的。
同时这个类也实现了 PointcutAdvisor,可以返回 Pointcut,可以用来筛选哪些方法需要拦截
4.判断 bean 对象是否需要进行事务增强处理
========================
bean 初始化后也会调用到 InfrastructureAdvisorAutoProxyCreator.postProcessAfterInitialization 方法(在 AbstractAutoProxyCreator 这个类中)。继而会调用到 wrapIfNecessary 这个方法。我们去看看这个方法
//AbstractAutoProxyCreator类中的方法
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
//看上面的英文注释也能简单明白 aop就是在这里生成的,对应事务其实也是用aop来完成的,我们重点看看这里的代码。
//我们的@Transactional注解是在UserServiceImpl这个类上,所以我们就只关注这个类的执行过程就可以了,我们进到这个方法里面去看看
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//这个specificInterceptors主要是Advisor,这个不为空,说明当前的bean对象,可以被specificInterceptors来进行aop代理,就会进入里面的createProxy进行aop增强
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//在这里会生成代理类,并返回代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
复制代码
@Override``@Nullable``//这个方法主要是根据我们传入的bean,查找适用的advice和advisor,如果返回的是空,就说明不需要进行AOP增强,``protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();``}
复制代码
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//这句比较简单,主要就是在beanFactory中获取类型是Advisor.class的对应bean,这个也比较简单,就跳进去看了,
//我们这里会返回的List中就会只有org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//这个主要是根据我们传入的bean对象,从candidateAdvisors返回合适的advisor,我们走进去看看
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;``}
复制代码
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
//我们当前传入的BeanFactoryTransactionAttributeSourceAdvisor不是IntroductionAdvisor接口的实现,不会走到这里
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
//真正起所用的是在这里,我们继续跳进去看看
//canApply返回true,就说明当前的candidate能作用于当前clazz,就需要加到列表,后续生成aop代理的时候需要
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
复制代码
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
//PointcutAdvisor 主要是通过getPointcut来获取Pointcut,从目标类上寻找应该被进行aop增强的类和方法
PointcutAdvisor pca = (PointcutAdvisor) advisor;
//会走到这里面,我们继续进去看看,在这里就是去查找对应类的事务属性(简单来说就是获取方法上的@Transactional的相关属性),如果能获取到这里就会返回true,获取不到就会返回false`` return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}``}
复制代码
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
//这个主要是判断类是否有必要pointcut的匹配。
//1. 如果类是TransactionalProxy、TransactionManager、PersistenceExceptionTranslator那就不需要后续匹配了直接从if分支里面返回
//2.或者要找的类是java.开头的,或者org.springframework.core这个接口,也从这里返回`` //我们当前查找的是事务的注解,名字是org.springframework.transaction.annotation.Transactional
//我们当前要匹配的类是com.springboot.transaction.service.impl.UserServiceImpl
//上面两个条件都不匹配,所以不会进入这个分支,继续向下走
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
//会走到这里,将com.springboot.transaction.service.impl.UserServiceImpl加入到classes中
classes.add(ClassUtils.getUserClass(targetClass));
}
//在这里会将当前类实现的接口com.springboot.transaction.service.UserService也加入进来
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
//在下面这里就会去遍历类上的所有方法,查找是否有 @Transactional注解
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
//会走到下面这个匹配条件,我们进到这个方法去看看
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
复制代码
//这个方法在TransactionAttributeSourcePointcut,这是一个抽象类``//当前这个类是BeanFactoryTransactionAttributeSourceAdvisor中的内部匿名类,类实例对象名是pointcut
@Override
public boolean matches(Method method, Class<?> targetClass) {
//这个tas就是在初始化BeanFactoryTransactionAttributeSourceAdvisor这个bean时,注入上去的TransactionAttributeSource的bean
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
复制代码
//这个方法在AbstractFallbackTransactionAttributeSource,``//注入上去的TransactionAttributeSource的bean的实际类型是AnnotationTransactionAttributeSource,它继承了AbstractFallbackTransactionAttributeSource``@Override``@Nullable``public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
// First, see if we have a cached value.
//在这里会生成一个缓存的key
Object cacheKey = getCacheKey(method, targetClass);
//从缓存中查看对应的事务属性是否存在 ,如果存在就直接返回,我们这里是第一次,就会走到后面的获取部分
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// Value will either be canonical value indicating there is no transaction attribute,
// or an actual transaction attribute.
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
}
else {
// We need to work it out.
//在这就是在对应的method上去查看是否有对应Transactional注解,如果有,就封装成TransactionAttribute返回
//这个具体也是通过SpringTransactionAnnotationParser.parseTransactionAnnotation方法来完成的,这个比较简单,就不进去了
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
if (txAttr == null) {
//如果获取不到,为了避免后续重复查找,也会在这里添加缓存`` this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
//我们当前会走到这里,methodIdentification就是类名加方法名的拼接,作为描述
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
if (txAttr instanceof DefaultTransactionAttribute) {
DefaultTransactionAttribute dta = (DefaultTransactionAttribute) txAttr;
dta.setDescriptor(methodIdentification);
dta.resolveAttributeStrings(this.embeddedValueResolver);
}
if (logger.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
//在这里将解析出来的 TransactionAttribute添加到缓存中并返回
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}``}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
学习分享,共勉
这里是小编拿到的学习资源,其中包括“中高级Java开发面试高频考点题笔记300道.pdf”和“Java核心知识体系笔记.pdf”文件分享,内容丰富,囊括了JVM、锁、并发、Java反射、Spring原理、微服务、Zookeeper、数据库、数据结构等大量知识点。同时还有Java进阶学习的知识笔记脑图(内含大量学习笔记)!
资料整理不易,读者朋友可以转发分享下!
Java核心知识体系笔记.pdf
中高级Java开发面试高频考点题笔记300道.pdf
架构进阶面试专题及架构学习笔记脑图
Java架构进阶学习视频分享
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
一起学习成长!**](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算