首页 > 编程语言 >Spring提取@Transactional事务注解的源码解析

Spring提取@Transactional事务注解的源码解析

时间:2022-12-19 13:01:57浏览次数:55  
标签:return Spring Transactional Object class 源码 new null method

声明:本文是自己在学习spring注解事务处理源代码时所留下的笔记; 难免有错误,敬请读者谅解!!!

1、事务注解标签

<tx:annotation-driven />

2、tx 命名空间解析器 
事务tx命名空间解析器TxNamespaceHandler 
org.springframework.transaction.config.TxNamespaceHandler#init

Spring提取@Transactional事务注解的源码解析_ide

3、AnnotationDrivenBeanDefinitionParser#parse 解析事务标签

(1)、以下方法的核心逻辑主要是选择是否使用 Aspect 方式实现代理,默认方式为 JDK 的动态代理。 
org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser#parse

public BeanDefinition parse(Element element, ParserContext parserContext) {
String mode = element.getAttribute("mode");
if ("aspectj".equals(mode)) {
// mode="aspectj"
registerTransactionAspect(element, parserContext);
}
else {
// mode="proxy" 注意 AopAutoProxyConfigurer 为当前内的内部类
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}

(2)、进入如下方法,该方法的核心逻辑通过硬编码的方式配置 Aop 动态代理的解析器 
AopAutoProxyConfigurer#configureAutoProxyCreator 
通过硬编码,Spring 为我们定义了如下的 Spring BeanDefinition 对象 
(a)、AnnotationTransactionAttributeSource.class 事务注解属性解析器BeanDefinition 对象。 
AnnotationTransactionAttributeSource 构造方法会初始化:

public AnnotationTransactionAttributeSource() {
this(true);
}

public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
this.annotationParsers = new LinkedHashSet<TransactionAnnotationParser>(2);
this.annotationParsers.add(new SpringTransactionAnnotationParser());// @Transactional 注解解析器
if (ejb3Present) {
this.annotationParsers.add(new Ejb3TransactionAnnotationParser());// Ejb 解析器
}

(b)、TransactionInterceptor.class 事务拦截器BeanDefinition 对象 

(c)、BeanFactoryTransactionAttributeSourceAdvisor.class 事务切面解析器 

(d)、TransactionInterceptor.class 事务拦截器BeanDefinition 对象 

(e)、容易忽略的第一行代码:AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element); 在这个方法内部 Spring 为我们的注入了:InfrastructureAdvisorAutoProxyCreator.class 

Spring提取@Transactional事务注解的源码解析_sed_02

private static class AopAutoProxyConfigurer {

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {

// 非常重要的一行代码,在这个里面注册了:InfrastructureAdvisorAutoProxyCreator.class 该类实现了Spring BeanProcessor 的扩展接口
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
Object eleSource = parserContext.extractSource(element);

// Create the TransactionAttributeSource definition.
RootBeanDefinition sourceDef = new RootBeanDefinition(AnnotationTransactionAttributeSource.class);// 事务注解解析器
sourceDef.setSource(eleSource);
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

// Create the TransactionInterceptor definition.
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);//事务拦截器
interceptorDef.setSource(eleSource);
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registerTransactionManager(element, interceptorDef);
interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

// Create the TransactionAttributeSourceAdvisor definition.
RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);//事务切面解析器
advisorDef.setSource(eleSource);
advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
if (element.hasAttribute("order")) {
advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
}
parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
parserContext.registerComponent(compositeDef);
}
}
}

4、Spring Bean 实例化创建代理对象 
(a)、AbstractAutowireCapableBeanFactory#initializeBean(Java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

Spring提取@Transactional事务注解的源码解析_spring_03

(b)、AbstractAutoProxyCreator#postProcessAfterInitialization 

Spring提取@Transactional事务注解的源码解析_spring_04

还记得上面我们提到的 InfrastructureAdvisorAutoProxyCreator 的类图吧,最后我们的 @Transactional 注解的类会执行该类中的 postProcessAfterInitialization 方法

(c)、Bean 的初始化后置处理,通过注释可以了解到,当前方法处理后会返回一个 bean 的代理对象

/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.containsKey(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);// 创建代理类的核心方法
}
}
return bean;
}

(d)、AbstractAutoProxyCreator#wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.containsKey(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);

// 创建代理对象,默认的情况下会使用 JDK 的动态代理接口创建代理对象
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;
}

(c)、获取到的事务切面 

Spring提取@Transactional事务注解的源码解析_解析器_05

(d)、事务切面获取逻辑 

Spring提取@Transactional事务注解的源码解析_解析器_06

(e)、委托 ProxyFactory 创建代理对象

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

ProxyFactory proxyFactory = new ProxyFactory();
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
proxyFactory.copyFrom(this);

if (!shouldProxyTargetClass(beanClass, beanName)) {
// Must allow for introductions; can't just set interfaces to
// the target's interfaces only.
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
for (Class<?> targetInterface : targetInterfaces) {
proxyFactory.addInterface(targetInterface);
}
}

Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}

proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);

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

// 最终会使用:JdkDynamicAopProxy 创建事务的Aop 代理对象
return proxyFactory.getProxy(this.proxyClassLoader);
}

(f)、最终生成代理对象 

Spring提取@Transactional事务注解的源码解析_spring_07

5、代理类执行 
JdkDynamicAopProxy#invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;

TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;

try {
// 如果目标方法没有实现equals
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
// 如果目标方法没有实现hashcode
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
// 根据代理对象的配置来调用服务
if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}

Object retVal;

if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}

// May be null. Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
// 获取目标对象
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}

// 获取定义好的拦截器链
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// 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.
// 没有拦截链则直接调用target方法
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
}
else {
// We need to create a method invocation...
//对拦截链进行封装 得到对象ReflectiveMethodInvocation 调用 proceed 方法
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();// 方法内部将执行拦截器的切面直到目标方法被执行
}

// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}

7、代理会执行到: ReflectiveMethodInvocation#proceed 方法

8、最终会执行到:TransactionInterceptor#invoke 方法

Spring提取@Transactional事务注解的源码解析_ide_08

9、执行 TransactionAspectSupport 事务方法 
TransactionInterceptor#invoke 方法会调用到父类的 TransactionAspectSupport#invokeWithinTransaction 方法

Spring提取@Transactional事务注解的源码解析_sed_09

10、业务方法执行 

Spring提取@Transactional事务注解的源码解析_sed_10

11、Spring 事务处理的流程 

Spring提取@Transactional事务注解的源码解析_sed_11

(a)、开启事务 

Spring提取@Transactional事务注解的源码解析_解析器_12

(b)、事务回滚 

Spring提取@Transactional事务注解的源码解析_解析器_13

(c)、事务提交 

Spring提取@Transactional事务注解的源码解析_sed_14

 


声明:本编文章是自己在查看spring提取@Transactional注解的源码过程中随手记下的笔记,只做了大概流程的记录,未做详细分析,如有错误还请谅解。

Spring提取@Transactional事务注解的源码解析_spring_15

1、事务切面匹配处理类

AopUtils#canApply(Pointcut, Class , boolean) 
方法中会调用到 TransactionAttributeSourcePointcut#matches 方法

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();
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}

Set<Class> classes = new HashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
Method[] methods = clazz.getMethods();
for (Method method : methods) {
//methodMatcher.matches(method, targetClass) 方法会匹配对应的处理类,在Transaction提取的过程中会匹配到:TransactionAttributeSourcePointcut
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}

return false;
}

Spring提取@Transactional事务注解的源码解析_解析器_16

2、事务切点匹配

TransactionAttributeSourcePointcut#matches

在阅读TransactionAttributeSourcePointcut内的源代码的时候,我们发现该类是一个抽象,但是他确没有实现的子类!!!那么这个类到底在哪被引用了呢?

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

public boolean matches(Method method, Class targetClass) {

// 该处调用了 getTransactionAttributeSource() 的抽象方法,但是却没有子类实现这个方法,这是怎么一回事呢?
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof TransactionAttributeSourcePointcut)) {
return false;
}
TransactionAttributeSourcePointcut otherPc = (TransactionAttributeSourcePointcut) other;
return ObjectUtils.nullSafeEquals(getTransactionAttributeSource(), otherPc.getTransactionAttributeSource());
}

@Override
public int hashCode() {
return TransactionAttributeSourcePointcut.class.hashCode();
}

@Override
public String toString() {
return getClass().getName() + ": " + getTransactionAttributeSource();
}


/**
* Obtain the underlying TransactionAttributeSource (may be {@code null}).
* To be implemented by subclasses.
*/
protected abstract TransactionAttributeSource getTransactionAttributeSource();

}

3、TransactionAttributeSourcePointcut 抽象类的应用

我们怀着上面的疑问全局搜索 TransactionAttributeSourcePointcut 可以在 BeanFactoryTransactionAttributeSourceAdvisor 里面找到如下的代码:

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

private TransactionAttributeSource transactionAttributeSource;

// 此处利用了匿名内部类的方式实例化了 TransactionAttributeSourcePointcut 对象,在此我们找到了上面问题的答案。
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};


/**
* Set the transaction attribute source which is used to find transaction
* attributes. This should usually be identical to the source reference
* set on the transaction interceptor itself.
* @see TransactionInterceptor#setTransactionAttributeSource
*/
public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
this.transactionAttributeSource = transactionAttributeSource;
}

/**
* Set the {@link ClassFilter} to use for this pointcut.
* Default is {@link ClassFilter#TRUE}.
*/
public void setClassFilter(ClassFilter classFilter) {
this.pointcut.setClassFilter(classFilter);
}

public Pointcut getPointcut() {
return this.pointcut;
}

}

4、TransactionAttributeSource 属性的 Bean 定义过程

其实,在实例化 BeanFactoryTransactionAttributeSourceAdvisor 时,Spring 已经为我们的 BeanFactoryTransactionAttributeSourceAdvisor 设置了 TransactionAttributeSource 属性,可以进入 AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer#configureAutoProxyCreator 方法中看源代码:

private static class AopAutoProxyConfigurer {

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
Object eleSource = parserContext.extractSource(element);

// 注解事务 transactionAttributeSource Spring 定义的Bean为: AnnotationTransactionAttributeSource 实例
// Create the TransactionAttributeSource definition.
RootBeanDefinition sourceDef = new RootBeanDefinition(AnnotationTransactionAttributeSource.class);
sourceDef.setSource(eleSource);
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

// Create the TransactionInterceptor definition.
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
interceptorDef.setSource(eleSource);
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registerTransactionManager(element, interceptorDef);
interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

// create BeanFactoryTransactionAttributeSourceAdvisor Bean 的定义
// Create the TransactionAttributeSourceAdvisor definition.
RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
advisorDef.setSource(eleSource);
advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 设置 transactionAttributeSource 属性
advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
if (element.hasAttribute("order")) {
advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
}
parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
parserContext.registerComponent(compositeDef);
}
}
}

5、TransactionAttributeSource#getTransactionAttribute 方法的调用过程

通过以上的分析,我们可以确定 
TransactionAttributeSourcePointcut#getTransactionAttributeSource 返回的是:AnnotationTransactionAttributeSource 实例,AnnotationTransactionAttributeSource继承自:AbstractFallbackTransactionAttributeSource, 故此TransactionAttributeSourcePointcut#matches 最终会调用到 AbstractFallbackTransactionAttributeSource#getTransactionAttribute 方法

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

public boolean matches(Method method, Class targetClass) {
TransactionAttributeSource tas = getTransactionAttributeSource();

// 最终会调用到 AbstractFallbackTransactionAttributeSource#getTransactionAttribute 方法
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

// 省略其他代码 ……………………
}

再看 AbstractFallbackTransactionAttributeSource#getTransactionAttribute 方法

// 获取事务属性
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
// First, see if we have a cached value.
Object cacheKey = getCacheKey(method, targetClass);
Object 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 (TransactionAttribute) cached;
}
}
else {
// We need to work it out. 根据 method、targetClass 推算事务属性,TransactionAttribute
TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
if (txAtt == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Adding transactional method '" + method.getName() + "' with attribute: " + txAtt);
}
this.attributeCache.put(cacheKey, txAtt);
}
return txAtt;
}
}

6、事务属性的推算过程:

// 推算事务属性,TransactionAttribute 
private TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}

// Ignore CGLIB subclasses - introspect the actual user class.
Class<?> userClass = ClassUtils.getUserClass(targetClass);
// 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 = ClassUtils.getMostSpecificMethod(method, userClass);
// If we are dealing with method with generic parameters, find the original method.
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);

// 通过上面的分析,findTransactionAttribute 该方法最终会调用到:AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.Class<?>)

// First try is the method in the target class. 方式1: 从目标类的方法上找 Transaction注解
TransactionAttribute txAtt = findTransactionAttribute(specificMethod);
if (txAtt != null) {
return txAtt;
}

// Second try is the transaction attribute on the target class. 方式2: 从目标类上找 Transaction注解
txAtt = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAtt != null) {
return txAtt;
}

if (specificMethod != method) {// 以上两种方式如果还没有找到 TransactionAttribute 属性,那就要从目标类的接口开始找
// Fallback is to look at the original method. 方式3:接口的方法上找 Transaction注解
txAtt = findTransactionAttribute(method);
if (txAtt != null) {
return txAtt;
}
// Last fallback is the class of the original method. 方式4:接口的类上找 Transaction注解
return findTransactionAttribute(method.getDeclaringClass());
}
return null;
}

7、事务注解属性的解析

AnnotationTransactionAttributeSource#findTransactionAttribute(​​Java​​.lang.Class

8、获取事务注解

public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {

public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
//获取 Transactional 注解
Transactional ann = AnnotationUtils.getAnnotation(ae, Transactional.class);
if (ann != null) {
//从 @Transactional 注解上获取事务属性值,并包装成 TransactionAttribute 返回
return parseTransactionAnnotation(ann);
}
else {
return null;
}
}

public TransactionAttribute parseTransactionAnnotation(Transactional ann) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
rbta.setPropagationBehavior(ann.propagation().value());
rbta.setIsolationLevel(ann.isolation().value());
rbta.setTimeout(ann.timeout());
rbta.setReadOnly(ann.readOnly());
rbta.setQualifier(ann.value());
ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<RollbackRuleAttribute>();
Class[] rbf = ann.rollbackFor();
for (Class rbRule : rbf) {
RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
String[] rbfc = ann.rollbackForClassName();
for (String rbRule : rbfc) {
RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
Class[] nrbf = ann.noRollbackFor();
for (Class rbRule : nrbf) {
NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
String[] nrbfc = ann.noRollbackForClassName();
for (String rbRule : nrbfc) {
NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
rbta.getRollbackRules().addAll(rollBackRules);
return rbta;
}

@Override
public boolean equals(Object other) {
return (this == other || other instanceof SpringTransactionAnnotationParser);
}

@Override
public int hashCode() {
return SpringTransactionAnnotationParser.class.hashCode();
}

}



标签:return,Spring,Transactional,Object,class,源码,new,null,method
From: https://blog.51cto.com/u_15147537/5951898

相关文章

  • springboot+postgresql集成anyline试水
    anyline是什么简单讲就是一个工具可以让你抛开常规的机械性建mapper、dao、sql,用通用的语句查询和操作数据库表。目前也在初步探索中,感受还不深。官网文档:http://doc.any......
  • 5. MinIO与springboot的集成
    MinIO与springboot的集成搭建一个springboot的项目,集成MinIO实现文件的管理。一、搭建springboot环境IntelliJIDEAJDK17gradle-7.5.1springboot2.7.6项目地址:g......
  • Spring Cloud 应用 Proxyless Mesh 模式探索与实践
    作者:十眠ServiceMesh简介ServiceMesh早已不是一个新兴的概念,目前已经有许多关于ServiceMesh的探索以及实践。2016年可以说是ServiceMesh的元年,Buoyant公司CEO......
  • Spring AMQP项目(四)
    4.1.12.代理事件侦听器启用事件交换插件后,如果将类型的Bean添加到应用程序上下文中,它将选定的代理事件发布为实例,这些实例可以使用普通的Spring或方法使用。事件由代......
  • Spring Cloud 应用 Proxyless Mesh 模式探索与实践
    作者:十眠ServiceMesh简介ServiceMesh早已不是一个新兴的概念,目前已经有许多关于ServiceMesh的探索以及实践。2016年可以说是ServiceMesh的元年,Buoyant公司......
  • Spring boot —— 创建parent工程
    方式一<parent>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-parent</artifactId>      <versio......
  • springboot实现AOP切面编程
    概述AOP(AspectOrientedProgramming)即面向切面编程。面向切面是面向对象中的一种方式而已。在代码执行过程中,动态嵌入其他代码,叫做面向切面编程(将交叉业务逻辑封装成成......
  • Spring boot 入门 ---(一)
    环境JavaSDKv1.6或更高版本。这里使用maven作为构建工具下面是一个典型的pom.xml文件:配置pom.xml文件<?xmlversion="1.0"encoding="utf-8"?><projectxmlns="http://mav......
  • spring boot 整合 FastDFS_Client
    FastDFS-Client使用方式1.在项目Pom当中加入依赖Maven依赖为<dependency><groupId>com.github.tobato</groupId><artifactId>fastdfs-client</artifactId><vers......
  • Spring boot整合 Swagger2 以及遇到的坑
    一、引入依赖:<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.5.0</version></dependency><dependency><gro......