日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

springboot事务回滚源码_002 | 搭上SpringBoot事务源码分析专车

發布時間:2023/12/19 javascript 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 springboot事务回滚源码_002 | 搭上SpringBoot事务源码分析专车 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

發車啦,發車啦,上車要求:

點擊左上方的“java進階架構師”進入頁面

選擇右上角的“置頂公眾號”上車

專車介紹

該趟專車是開往Spring Boot事務源碼分析的專車

專車問題

  • 為什么加上@Transactional注解就可以實現事務?

  • 分析事務源碼之后我們可以學到什么?

專車名詞

事務

程序中通常使用事務來達到數據的一致性,從而避免臟數據

編程式事務

在業務方法開頭開啟事務,然后對我們的業務進行try-catch,假設沒有異常則提交事務,如果出現異常,則在catch模塊回滾事務

聲明式事務由來

如果采用編程式事務,那么在任何需要事務的地方都要開啟事務、try-catch、提交或者回滾事務,會導致重復編碼、編寫與業務無關的代碼。基于Spring Aop思想,我們可以利用Aop的方式,對需要使用事務的方法進行增強,將公用的部分提取出來,那么就實現了聲明式事務。

Spring提供的聲明式事務

在需要使用事務的業務方法上添加@Transactional注解,那么就可以使用事務的特性,要么成功,要么失敗

Spring Aop核心概念

  • 切面:切面是由切點和通知組成

  • 切點:用來匹配符合條件類或方法

  • 通知:需要執行的操作

專車分析

基于Spring Boot自動配置原理,我們應該尋找xxxAutoConfiguration自動配置類,此處要尋找和事務相關的,那么自然是TransactionAutoConfiguration

自動配置

打開TransactionAutoConfiguration自動配置類

@Configuration
@ConditionalOnBean(PlatformTransactionManager.class)
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
public static class EnableTransactionManagementConfiguration {

@Configuration
@EnableTransactionManagement(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
public static class JdkDynamicAutoProxyConfiguration {

}

@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
public static class CglibAutoProxyConfiguration {

}

}

可以看到開啟事務管理器的注解@EnableTransactionManagement

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {}

查看TransactionManagementConfigurationSelector導入的類

protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}

可以看到導入了AutoProxyRegistrar和ProxyTransactionManagementConfiguration

首先看看AutoProxyRegistrar,該類實現了ImportBeanDefinitionRegistrar

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set annoTypes = importingClassMetadata.getAnnotationTypes();for (String annoType : annoTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);if (candidate == null) {continue;
}
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;if (mode == AdviceMode.PROXY) {// 注冊自動代理創建器
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);return;
}
}
}
}
}

注冊自動代理創建器,AopConfigUtils#registerAutoProxyCreatorIfNecessary

public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 注冊了InfrastructureAdvisorAutoProxyCreator到IOC容器中
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

InfrastructureAdvisorAutoProxyCreator是AbstractAutoProxyCreator的子類,AbstractAutoProxyCreator又實現了BeanPostProcessor接口,那么在bean初始化完畢后就會調用postProcessAfterInstantiation()方法,postProcessAfterInstantiation()定義在AbstractAutoProxyCreator類中

BeanPostProcessor后置處理

打開AbstractAutoProxyCreator

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// 如果滿足條件對bean進行包裹
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

該方法調用了wrapIfNecessary()方法

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// Create proxy if we have advice.
// 獲取bean的切面和通知
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 需要代理
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;
}

根據注釋的意思就是如果存在advice,那么就創建代理,

尋找切面

進入AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean

protected Object[] getAdvicesAndAdvisorsForBean(
Class> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 查找符合條件的切面
List advisors = findEligibleAdvisors(beanClass, beanName);// 不存在符合條件的切面,則不生成代理if (advisors.isEmpty()) {return DO_NOT_PROXY;
}return advisors.toArray();
}

該代碼第一句最重要,如果不存在符合條件的切面,那么最終的結果返回null,根據上面分析的,如果為null就不創建代理,否則創建代理。接下來看看第一句的實現

protected ListfindEligibleAdvisors(Class> beanClass, String beanName) {
// 獲取所有候選的切面,也就是類型為Advisor的切面,此處獲取到的候選切面為BeanFactoryTransactionAttributeSourceAdvisor
List candidateAdvisors = findCandidateAdvisors();// 從候選的切面中獲取可以解析當前bean的切面,最終符合條件的切面為BeanFactoryTransactionAttributeSourceAdvisor
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}return eligibleAdvisors;
}

為什么上面獲取到的切面是BeanFactoryTransactionAttributeSourceAdvisor?是否還記得之前導入配置類的時候還有一個配置類沒有分析?那就是ProxyTransactionManagementConfiguration

打開ProxyTransactionManagementConfiguration

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

// 創建BeanFactoryTransactionAttributeSourceAdvisor
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
// 設置切面對應的通知,后面分析會用到
advisor.setAdvice(transactionInterceptor());
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.getNumber("order"));
}return advisor;
}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionAttributeSource transactionAttributeSource() {return new AnnotationTransactionAttributeSource();
}// 創建通知@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource());if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}return interceptor;
}
}

通過上面的自動配置,可得知獲取到的候選切面為什么是BeanFactoryTransactionAttributeSourceAdvisor

接下來看看如何從候選切面中找到可以解析當前bean的切面?

protected ListfindAdvisorsThatCanApply(
List candidateAdvisors, Class> beanClass, String beanName) {

ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 查找可以解析當前bean對應的切面
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}

查找可以解析當前bean對應的切面,AopUtils#findAdvisorsThatCanApply

public static ListfindAdvisorsThatCanApply(List candidateAdvisors, Class> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List eligibleAdvisors = new ArrayList<>();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor) {// already processedcontinue;
}// 當前切面是否可以解析beanif (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}return eligibleAdvisors;
}

候選切面是否可以解析bean

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) {
// 由上面分析知道最終的候選切面為BeanFactoryTransactionAttributeSourceAdvisor
// 該類實現了PointcutAdvisor
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}

候選切面是否可以解析bean

public static boolean canApply(Pointcut pc, Class> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
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> classes = new LinkedHashSet<>();if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));for (Class> clazz : classes) {// 通過反射獲取當前類所有的Method對象
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#matches

public boolean matches(Method method, Class> targetClass) {
if (TransactionalProxy.class.isAssignableFrom(targetClass) ||
PlatformTransactionManager.class.isAssignableFrom(targetClass) ||
PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
// 如果事務屬性源對象為空或者事務屬性對象不為null返回true,代表匹配成功;否則返回false,匹配失敗
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

獲取事務屬性對象,AbstractFallbackTransactionAttributeSource#getTransactionAttribute

public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}

// First, see if we have a cached value.
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 {
// 計算事務屬性對象
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
if (txAttr instanceof DefaultTransactionAttribute) {
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
}
if (logger.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}

計算事務屬性對象

protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}

// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

// First try is the method in the target class.
// 首先根據Method對象獲取事務屬性對象
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}

// Second try is the transaction attribute on the target class.
// 如果根據Method對象獲取不到事務屬性對象,那么根據Class來獲取屬性對象
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}

if (specificMethod != method) {
// Fallback is to look at the original method.
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// Last fallback is the class of the original method.
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}

return null;
}

獲取屬性對象AnnotationTransactionAttributeSource#findTransactionAttribute

protected TransactionAttribute findTransactionAttribute(Class> clazz) {
return determineTransactionAttribute(clazz);
}

決定事務屬性對象

protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
return null;
}

解析事務屬性對象,SpringTransactionAnnotationParser#parseTransactionAnnotation

public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
// 判斷元素是否含有@Transactional注解,通過前面的分析我們可以得出如下結論:
// 1、首選判斷類的方法上是否含有@Transactional注解,如果有就解析
// 2、如果所有的方法都不含有@Transactional注解,那么判斷當前類是否含有@Transactional注解,如果有就解析
// 3、如果類或者類的某個方法含有@Transactional注解,那么事務屬性對象就不為空,則說明次切面可以解析當前bean
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}

回到AbstractAutoProxyCreator#wrapIfNecessary

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.
// 此處有值返回,進行代理,否則不進行代理
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 需要進行代理
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;
}

創建代理

創建代理AbstractAutoProxyCreator#createProxy

protected Object createProxy(Class> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {

if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}

// 創建代理工廠
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);

if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}

// 構建切面,此處的切面為BeanFactoryTransactionAttributeSourceAdvisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 設置切面
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);

proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}

return proxyFactory.getProxy(getProxyClassLoader());
}

獲取代理ProxyFactory#getProxy

public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}

創建aop代理

protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 此處的this實際上就是ProxyFactory
return getAopProxyFactory().createAopProxy(this);
}

aop代理工廠創建aop代理DefaultAopProxyFactory#createAopProxy

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 創建cglib aop代理
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}

實例化ObjenesisCglibAopProxy對象

public ObjenesisCglibAopProxy(AdvisedSupport config) {
super(config);
}

父類實例化

public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
// 此處的config就是之前的ProxyFactory
this.advised = config;
this.advisedDispatcher = new AdvisedDispatcher(this.advised);
}

回到之前獲取代理的地方

public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}

通過上面的分析可以得知createAopProxy()返回的是CglibAopProxy

通過CglibAopProxy獲取代理,CglibAopProxy#getProxy

public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}

try {
Class> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

Class> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class>[] additionalInterfaces = rootClass.getInterfaces();
for (Class> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}

// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);

// Configure CGLIB Enhancer...
// 創建Enhancer對象
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
// 設置父類
enhancer.setSuperclass(proxySuperClass);
// 設置接口
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

// 獲取回調,重點分析
Callback[] callbacks = getCallbacks(rootClass);
Class>[] types = new Class>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
// 設置回調類型
enhancer.setCallbackTypes(types);

// Generate the proxy class and create a proxy instance.
// 生成代理并創建代理實例
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}

獲取回調

private Callback[] getCallbacks(Class> rootClass) throws Exception {
// Parameters used for optimization choices...
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();

// Choose an "aop" interceptor (used for AOP calls).
// 實例化回調,在調用目標對象方法的時候執行
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
return callbacks;
}

實例化回調部分

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

private final AdvisedSupport advised;

public DynamicAdvisedInterceptor(AdvisedSupport advised) {
// 設置切面信息,也就是之前的ProxyFactory
this.advised = advised;
}

@Override
@Nullable
// 調用目標方法的時候執行
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class> targetClass = (target != null ? target.getClass() : null);
// 獲取通知,此處的通知為TransactionInterceptor
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;// Check whether we only have one InvokerInterceptor: that is,// no real advice, but just reflective invocation of the target.if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {// We can skip creating a MethodInvocation: just invoke the target directly.// Note that the final invoker must be an InvokerInterceptor, so we know// it does nothing but a reflective operation on the target, and no hot// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}else {// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);return retVal;
}finally {if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}if (setProxyContext) {// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}@Overridepublic boolean equals(Object other) {return (this == other ||
(other instanceof DynamicAdvisedInterceptor &&this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));
}/**
* CGLIB uses this to drive proxy creation.
*/@Overridepublic int hashCode() {return this.advised.hashCode();
}
}

調用invocation的處理方法,ReflectiveMethodInvocation#proceed

public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}

// 此處的通知TransactionInterceptor
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
// 調用TransactionInterceptor#invoke
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}

調用TransactionInterceptor#invoke

public Object invoke(MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

// Adapt to TransactionAspectSupport's invokeWithinTransaction...
// 以事務的方式進行調用
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}

事務方式調用

protected Object invokeWithinTransaction(Method method, @Nullable Class> targetClass,final InvocationCallback invocation) throws Throwable {

// If the transaction attribute is null, the method is non-transactional.
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
// 創建事務信息對象
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
// 調用被代理對象方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
// 業務方法執行異常,進行事務回滾
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 清除事務信息對象
cleanupTransactionInfo(txInfo);
}
// 提交事務
commitTransactionAfterReturning(txInfo);
return retVal;
}

else {
final ThrowableHolder throwableHolder = new ThrowableHolder();

// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
try {
return invocation.proceedWithInvocation();
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new ThrowableHolderException(ex);
}
}
else {
// A normal return value: will lead to a commit.
throwableHolder.throwable = ex;
return null;
}
}
finally {
cleanupTransactionInfo(txInfo);
}
});

// Check result state: It might indicate a Throwable to rethrow.
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
}
return result;
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
catch (TransactionSystemException ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);
}
throw ex2;
}
catch (Throwable ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw ex2;
}
}
}

到此事務的源碼分析就結束了

專車總結

  • 導入AutoProxyRegistrar、ProxyTransactionManagementConfiguration配置類

  • AutoProxyRegistrar用來注冊InfrastructureAdvisorAutoProxyCreator到IOC中,InfrastructureAdvisorAutoProxyCreator實現了BeanPostProcessor

  • 執行BeanPostProcessor的后置處理

  • 獲取由ProxyTransactionManagementConfiguration配置類創建的切面

  • 通過切面解析bean是否需要創建代理,需要就創建代理

  • 執行代理的回調,在回調中拿到通知

  • 執行通知,通知里面邏輯:開啟事務、執行目標方法、提交或回滾事務

專車回顧

回顧下開頭的兩個問題:

  • 為什么加上@Transactional注解就可以實現事務?

  • 分析事務源碼之后我們可以學到什么?

通過以上分析,第一個問題應該就迎刃而解了,那么通過以上學到的知識我們可以實現什么功能呢?在下一篇我們會在此基礎上進行實戰,通過@SystemLog注解實現系統日志功能。感謝各位擼友乘坐此趟專車,歡迎下次繼續乘坐

————??e n d?————

微服務、高并發、JVM調優、面試專欄等20大進階架構師專題請關注公眾號Java進階架構師后在菜單欄查看

看到這里,說明你喜歡本文

你的轉發,是對我最大的鼓勵!在看亦是支持

總結

以上是生活随笔為你收集整理的springboot事务回滚源码_002 | 搭上SpringBoot事务源码分析专车的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。