96SEO 2026-02-19 17:59 0
本篇文章我们看下当一个类里面包含了Transactional注解#xff0c;Spring如…上一篇文章我们介绍了事务开启注解EnableTransactionManagement源码解析《Spring-事务源码解析1》

里面提到了2个关键组件这里我们分析下Spring如何利用这2个组件来给Bean创建代理对象。
本篇文章我们看下当一个类里面包含了Transactional注解Spring如何利用上面说的2个组件来实例化Bean如何让这个Bean带有事务功能。
1、Bean如何创建具有事务功能的代理类这里就用到上面2个组件
创建Bean当然是看Spring非常经典的doCreateBean方法这里最终就得到目标类的代理对象这中间就包含了Spring如何利用后置处理器控制目标类代理对象创建如何利用切点匹配要添加通知的方法。
因为doCreateBean内容有点多这里我也就贴我认为比较重要的一部分代码。
//假设我们的业务类AService带有Transactional注解,下面通过doCreateBean创建AService的代理对象
{........1、下面一块代码就是通过反射得到AService的实例对象这个还只是通过反射拿到了普通的实例对象不是代理对象。
BeanWrapper
this.factoryBeanInstanceCache.remove(beanName);}if
instanceWrapper.getWrappedInstance();................2、把普通实例对象封装ObjectFactory对象存入三级缓存在AOP依赖注入和循环依赖会用到这里我们先忽略。
boolean
isSingletonCurrentlyInCreation(beanName));if
getEarlyBeanReference(beanName,
bean));}................3、通过AService普通实例对象生成AService的代理对象也利用了前面提到的2个组件这里的代理对象就包含了事务功能。
逻辑都在初始化Object
instanceWrapper);//属性填充exposedObject
mbd);//初始化................4、利用三级缓存解决依赖注入和循环依赖这里先忽略。
if
earlySingletonReference;}}}........return
exposedObject;//返回AService的代理对象
bean;//这里Bean还只是AService的普通实例对象//执行所有后置处理器的Before方法本次忽略wrappedBean
applyBeanPostProcessorsBeforeInitialization(wrappedBean,
beanName);//如果AServcie实现了InitializingBean接口,执行inint方法本次忽略invokeInitMethods(beanName,
mbd);//重点执行所有后置处理器的After方法这里会生成AService的代理对象。
wrappedBean
applyBeanPostProcessorsAfterInitialization(wrappedBean,
}Spring里面包含了很多后置处理器那么生成AService代理类的后置处理器也就是我们前面提到的2个组件
1、AutoProxyRegistrar组件会往Spring容器中注册InfrastructureAdvisorAutoProxyCreator后置处理器
2、ProxyTransactionManagementConfiguration组件会往Spring容器中注册切面进去
在执行到InfrastructureAdvisorAutoProxyCreator后置处理器的After方法里面主要是为通过调用wrapIfNecessary方法来创建AService代理对象。
postProcessAfterInitialization(Nullable
{//根据Bean的信息来获取AService所有的AdvisorAdvisor可以近似的把他理解成切面当然Advisor和切面不是一个东西为了方便理解就近似把他看做是切面。
//这里拿到的切面是符合AService的切面就Spring会有很多事务相关的切面每个切面有自己定义的切点规则比如有的切面处理X注解的,有的切面只处理Transactional//这里只返回AService符合切点规则的那个切面。
为什么要拿切面因为Spring在创建代理类的时候就是要基于切面里面的通知来对目标方法进行拦截。
Object[]
getAdvicesAndAdvisorsForBean(bean.getClass(),
{//利用Advices来生成AService的代理对象。
Object
SingletonTargetSource(bean));return
getAdvicesAndAdvisorsForBean是如何获取符合规则的Advisor
getAdvicesAndAdvisorsForBean(Class?
findEligibleAdvisors(beanClass,
findCandidateAdvisors();//2、过滤出AService符合切点规则ListAdvisor
findAdvisorsThatCanApply(candidateAdvisors,
}上面包含2块内容第一块是获取所有切面第二块是过滤出符合规则的切面下面我们分别看下如何获取所有切面。
//获取所有的Advisor这里的Advisor就包含了我们前面提到的组件ProxyTransactionManagementConfiguration
//ProxyTransactionManagementConfiguration会往Spring容器里面注册3个Bean。
//其中切面BeanFactoryTransactionAttributeSourceAdvisor,
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory,
false);this.cachedAdvisorBeanNames
{........advisors.add(this.beanFactory.getBean(name,
Advisor.class));//通过Name获取Advisor对应的Bean这里就是BeanFactoryTransactionAttributeSourceAdvisor........}return
//从Advisor集合中挑选出beanClass符合的Advisor
findAdvisorsThatCanApply(ListAdvisor
AopUtils.findAdvisorsThatCanApply(candidateAdvisors,
findAdvisorsThatCanApply(ListAdvisor
ArrayList();//定义符合规则的Advisor集合同以最终返回。
//引介切面过滤for
{//如果Advisor是引介切面并且符合规则引介切面是基于类层面判断是否符合规则if
{eligibleAdvisors.add(candidate);}}//切点切面过滤boolean
!eligibleAdvisors.isEmpty();for
{continue;}//进到这里说明这个Advisor是切点切面切面切面是基于方法层面判断是否符合规则。
if
{eligibleAdvisors.add(candidate);}}return
advisor).getClassFilter().matches(targetClass);}
//通过方法层面判断其实就是判断方法是否有Transactional注解当然每个切点的实现不一样判断逻辑也会有差异
(!Proxy.isProxyClass(targetClass))
{classes.add(ClassUtils.getUserClass(targetClass));}classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));//拿到目标类for
ReflectionUtils.getAllDeclaredMethods(clazz);for
{//判断方法是否匹配这里其实通过切点类判断是否方法是否包含特定注解。
比如Transactionalif
这一段我们讲了如何利用getAdvicesAndAdvisorsForBean拿到目标类的advisor因为Spring在整个启动过程中会存在很多advisor不是所有的advisor都能给AService来用我们需要通过切面中的切点规则来判断是否符合规则。
再回到wrapIfNecessary方法的第二块内容生成代理对象。
getAdvicesAndAdvisorsForBean(bean.getClass(),
{//2、结合advisor生成AService的代理对象。
Object
SingletonTargetSource(bean));return
{//创建ProxyFactory用来生成代理对象ProxyFactory
ProxyFactory();proxyFactory.copyFrom(this);//拿到切面添加进去Advisor[]
specificInterceptors);proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);proxyFactory.setFrozen(this.freezeProxy);...省略部分代理return
proxyFactory.getProxy(getProxyClassLoader());
}上面最终调用getProxy方法来生成代理对象那么JDK和Cglib都实现了getProxy方法这里我们分别看下他们如何创建对象。
AopProxyUtils.completeProxiedInterfaces(this.advised,
true);...省略部分代理//这里的this是JdkDynamicAopProxy//生成代理对象代理对象需要实现proxiedInterfaces集合所有接口//当目标对象被调用的时候会先进到JdkDynamicAopProxy的invoke方法里面return
Proxy.newProxyInstance(classLoader,
this.advised.getTargetClass();Class?
(rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR))
rootClass.getSuperclass();Class?[]
{this.advised.addInterface(additionalInterface);}}Enhancer
createEnhancer();enhancer.setSuperclass(proxySuperClass);
//代理类的父类也就是目标类AServcieenhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
//代理类需要实现的接口enhancer.setStrategy(new
ClassLoaderAwareGeneratorStrategy(classLoader));//添加回调方法这些回调类都实现了MethodInterceptor接口当AService的方法被调用时会进到MethodInterceptor里面的intercept方法里面去Callback[]
getCallbacks(rootClass);Class?[]
Class?[callbacks.length];enhancer.setCallbackFilter(new
ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(),
this.fixedInterceptorOffset));。
。
。
。
。
。
省略部分代码return
createProxyClassAndInstance(enhancer,
}getCallbacks会拿到很多MethodInterceptor的实现类作为回调添加到代理类里面去当AService有方法被调用时就会进被MethodInterceptor的intercept方法拦截在intercept里面调用切面里面的通知方法。
这里MethodInterceptor的实现类就包含DynamicAdvisedInterceptor。
通过JDK和Cglib创建代理类并添加拦截方法在AService方法被执行时被invoke方法或者intercept方法拦截。
上面我们介绍了如何创建代理对象并且在创建代理对象时拦截目标方法这里我们看下当目标方法被执行在拦截里面做了什么操作。
当目标方法被调用时会被JdkDynamicAopProxy的invoke方法拦截或者是MethodInterceptor的intercept方法拦截在invoke和intercept里面会通过切面拿到通知在挨个的执行通知最后在执行目标方法
{//获取符合目标方法的拦截器MethodInterceptor集合ListObject
this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,
AopProxyUtils.adaptArgumentsIfNecessary(method,
AopUtils.invokeJoinpointUsingReflection(target,
argsToUse);//如果拦截器集合为空就直接调用目标方法}
ReflectiveMethodInvocation(proxy,
targetSource.getTarget();Class?
null);//1、获取符合目标方法的拦截器MethodInterceptor集合。
这里是拿切里的通知通知是MethodInterceptor类型ListObject
this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,
Modifier.isPublic(method.getModifiers()))
argsToUse);//如果拦截器集合为空就直接调用目标方法}
{//2、生成拦截器链使用的是责任链设计模式。
在挨个调用拦截器。
最后调用目标方法retVal
}关于获取拦截器集合和调用拦截器链可以看到我的这篇文章《代理生成拦截器和调用拦截器》
然后执行拦截器链中的最开始的拦截器后面一次遍历但是此时的拦截器就只有一个就是TransactionInterceptor事务方法拦截器
进到TransactionInterceptor就会执行TransactionInterceptor的invoke方法,下面看下invoke的流程
1、先拿到事务管理器的事务类型PROPAGATION_REQUIRED,ISOLATION_DEFAULT;
2、在拿到事务的管理器也就是DataSourceTransactionManager
AopUtils.getTargetClass(invocation.getThis())
invokeWithinTransaction(invocation.getMethod(),
getTransactionAttributeSource().getTransactionAttribute(method,
targetClass);//2、事务管理器DataSourceTransactionManagerfinal
determineTransactionManager(txAttr);//生成事务txInfo里面包含本次事务状态隔离级别事务处理器当本次事务执行完后需要关闭本次事务TransactionInfo
createTransactionIfNecessary(tm,
invocation.proceedWithInvocation();}catch
{//更改txInfo里面的状态completeTransactionAfterThrowing(txInfo,
{cleanupTransactionInfo(txInfo);}commitTransactionAfterReturning(txInfo);//根据状态是否commitreturn
1、前面我们在Bean的实例化时用到了第一个组件InfrastructureAdvisorAutoProxyCreator用来触发wrapIfNecessary方法。
2、在wrapIfNecessary方法里面我们利用了第二个组件ProxyTransactionManagementConfiguration生成的切面BeanFactoryTransactionAttributeSourceAdvisor通过BeanFactoryTransactionAttributeSourceAdvisor的切点AnnotationTransactionAttributeSource来判断AService是否符合切点规则也就是解读AService类的方法是否包含Transactional注解。
1、带有Transaction注解的Bean实例化的时候怎么如果判断该Bean带有Transaction方法
1、InfrastructureAdvisorAutoProxyCreator#postProcessAfterInitialization
—2、BeanFactoryTransactionAttributeSourceAdvisor
—3、AnnotationTransactionAttributeSource
—4、SpringTransactionAnnotationParser判断Transaction
最终通过SpringTransactionAnnotationParser来判断Bean的方法是否带有Transaction注解
InfrastructureAdvisorAutoProxyCreator里面有个advisedBeans属性在Bean的创建过程会判断Bean里面
是否是带有事务注解Transaction的方法如果有就会被加到advisedBeans里面去。
1、BeanFactoryTransactionAttributeSourceAdvisor事务增强器在advisedBeans是false的形式存在
2、transactionInterceptor也是false
2、带有Transaction注解的代理Bean在哪个流程被创建
在执行BeanPostProcess处理器链的时候由InfrastructureAdvisorAutoProxyCreator#postProcessAfterInitialization方法执行创建该方法会调用wrapIfNecessary方法完成代理创建
{.......//这里是拿到BeanFactoryTransactionAttributeSourceAdvisor也就是“事务增强器”Object[]
getAdvicesAndAdvisorsForBean(bean.getClass(),
{this.advisedBeans.put(cacheKey,
Boolean.TRUE);//key就是带有Transaction的BeanNameObject
SingletonTargetSource(bean));return
proxyFactory.setTargetSource(目标对象LLServcieImpl);
proxyFactory.setInterfaces(目标接口LLServcie);
proxyFactory.addAdvisor(事务增强器BeanFactoryTransactionAttributeSourceAdvisor);
proxyFactory.getProxy(getProxyClassLoader())//调用下面的代码//2、生成动态代理对象
proxiedInterfacesAopProxyUtils.completeProxiedInterfaces(事务增强器,
//设置代理对象要实现接口和InvocationHandler对象
Proxy.newProxyInstance(classLoader,
JdkDynamicAopProxy类);其中proxiedInterfaces包含接口
cn.tedu.sample2.util.LLServcie”
org.springframework.aop.SpringProxy”
org.springframework.aop.framework.Advised”
org.springframework.core.DecoratingProxy”
4、InfrastructureAdvisorAutoProxyCreator类的作用
1、postProcessBeforeInstantiation方法主要是针对所有要创建的Bean,判断存到advisedBeans里面是false还是true
2、postProcessAfterInitialization方法处理带有Transcation的Bean创建代理Bean
1、先通过EnableTransactionManagement引入TransactionManagementConfigurationSelector
2、通过TransactionManagementConfigurationSelector导入AutoProxyRegistrarProxyTransactionManagementConfiguration
3、AutoProxyRegistrar会向容器中注册InfrastructureAdvisorAutoProxyCreator
4、ProxyTransactionManagementConfiguration会向容器定义三个Bean事务增强器、Transaction注解解析器、事务方法拦截器
5、执行Bean的后置处理器时通过InfrastructureAdvisorAutoProxyCreator的postProcessAfterInitialization方法创建代理对象
6、创建代理对象时通过事务增强器BeanFactoryTransactionAttributeSourceAdvisor来得到代理类要实现的接口SpringProxy、Advised、DecoratingProxy最终生成代理对象
7、当请求进来时先进入JdkDynamicAopProxy的invoke方法
8、invoke里面会调用TransactionInterceptor的invoke方法里面会调用invokeWithinTransaction方法
9、invokeWithinTransaction里面会在调用目标方法前开启事务catch失败设置状态然后finally根据状态来确认是否commit
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback