Spring Transactional源码分析(一)
1.Spring Transactional源码分析
1.核心类
Spring的事务依赖于一个核心的接口PlatformTransactionManager
。
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
这个接口提供了三个方法,这三个方法见名知意,就是获取事务(开始事务)、提交、回滚。
这个类图展示了它的部分常用的子类,不同的TransactionManager
用于不同的框架,比如DataSourceTransactionManager
用于JDBC
、MyBatis
,JpaTransactionManager
用于JPA
。
还有两个重要的类:TransactionDefinition
和TransactionStatus
。
TransactionDefinition
是事务的定义,包含了事务中常用的属性,比如传播行为、隔离级别、超时时间等。
TransactionAttribute
继承了TransactionDefinition
,主要增加了一个指定异常回滚方法,只配合AOP使用。
TransactionStatus
保存了事务的状态,事务的所有操作都是基于这个状态。
SavepointManager
就是包含了操作savepoint
的三个方法,TransactionStatus
实现了SavepointManager
,再加上本身提供的一些方法,基本包含了事务的所有状态。后续无论是事务的创建、回滚、完成等都是基于该接口。
SavepointManager
还有另外一个重要的子类,JdbcTransactionObjectSupport
抽象类,这个类有很多实现类,并且这些实现类都是各个PlatformManager
实现类的内部类,用于保存了JDBC连接、事务隔离级别以及保存点的回滚。
2.注册BeanDefintion
org.springframework.transaction.config.TxNamespaceHandler
:
public class TxNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
//基于XML
registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
//基于注解
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}
}
对于每种标签提供了相应的BeanDefinitionParser
。
1.基于XML配置
TxAdviceBeanDefinitionParser
用于解析<tx:advice/>
标签。
案例:
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.ly.transactional..*(..))"/>
<aop:advisor advice-ref="transactionInterceptor" pointcut-ref="pointcut"/>
</aop:config>
<tx:advice id="transactionInterceptor" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRES_NEW" isolation="READ_COMMITTED"/>
<tx:method name="get*" propagation="REQUIRED" isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>
事务的基于XML配置的方式是需要<aop:advisor/>
标签进行配合使用的,这里主要看事务标签解析。
<aop:config/>
会被解析Class
为AspectJAwareAdvisorAutoProxyCreator
的BeanDefintion
,在创建代理类的时候会用到;<aop:pointcut/>
会被解析为Class
为AspectJExpressionPointcut
的BeanDefinition
;<tx:advice/>
会被解析为Class
为TransactionInterceptor
的BeanDefintion
;<aop:advisor/>
会被解析为Class
为DefaultBeanFactoryPointcutAdvisor
,这个Advisor
保存了AspectJAwareExpressionPointcut
和TransactionIntercepor
的RuntimeBeanNameReference
,这个Advisor
就是后面执行的时候用的。
org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse
:
@Override
public final BeanDefinition parse(Element element, ParserContext parserContext) {
AbstractBeanDefinition definition = parseInternal(element, parserContext);
return definition;
}
org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal
:
@Override
protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
//委派给TxAdviceBeanDefinitionParser
Class<?> beanClass = getBeanClass(element);
if (beanClass != null) {
builder.getRawBeanDefinition().setBeanClass(beanClass);
}
//委派给TxAdviceBeanDefinitionParser
doParse(element, parserContext, builder);
return builder.getBeanDefinition();
}
这里使用了委派模式,将顶层标签的解析和顶层标签的字标签的解析都交由子类去实现。
org.springframework.transaction.config.TxAdviceBeanDefinitionParser#getBeanClass
:
@Override
protected Class<?> getBeanClass(Element element) {
return TransactionInterceptor.class;
}
这里解析<tx:advice/>
标签Class
为TransactionInterceptor
的BeanDefinition
。
org.springframework.transaction.config.TxAdviceBeanDefinitionParser#doParse
:
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
//1.判断标签是否申明了transaction-manager标签,如果没有申明,则默认查找id为transactionManager的bean作为事务管理器
builder.addPropertyReference("transactionManager", TxNamespaceHandler.getTransactionManagerName(element));
//2.解析<tx:attributes/>标签,正常情况下,<tx:advice/>标签内只能<=1个该标签
List<Element> txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES_ELEMENT);
if (txAttributes.size() > 1) {
parserContext.getReaderContext().error(
"Element <attributes> is allowed at most once inside element <advice>", element);
}
else if (txAttributes.size() == 1) {
// Using attributes source.
Element attributeSourceElement = txAttributes.get(0);
//3.创建了Class为NameMatchTransactionAttributeSource的BeanDefinition
RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext);
builder.addPropertyValue("transactionAttributeSource", attributeSourceDefinition);
}
else {
// 假设使用了注解
builder.addPropertyValue("transactionAttributeSource",
new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"));
}
}
doParse
方法主要做了两件事,第一件事是获取IOC容器中管理的事务管理器(TransactionManager
),第二件事是解析<tx:advice/>
中的<tx:attributes/>
标签,判断是否合法以及该使用何种方法去解析其内部的<tx:method/>
标签。
org.springframework.transaction.config.TxAdviceBeanDefinitionParser#parseAttributeSource
:
/**
* 解析<tx:method/>标签
*/
private RootBeanDefinition parseAttributeSource(Element attrEle, ParserContext parserContext) {
//1.解析<tx:method/>标签,该标签在<tx:attributes/>内部中可以有多个
List<Element> methods = DomUtils.getChildElementsByTagName(attrEle, METHOD_ELEMENT);
ManagedMap<TypedStringValue, RuleBasedTransactionAttribute> transactionAttributeMap =
new ManagedMap<TypedStringValue, RuleBasedTransactionAttribute>(methods.size());
transactionAttributeMap.setSource(parserContext.extractSource(attrEle));
//2.遍历,获取标签申明的属性,这些属性都是事务执行的支持的属性,和@Transactional注解中支持的属性基本一致
//这里使用了一个Map,key为name,value为RuleBasedTransactionAttribute,该类是TransactionBeanDefinition的子类,保存了Transaction的基本属性
for (Element methodEle : methods) {
String name = methodEle.getAttribute(METHOD_NAME_ATTRIBUTE);
TypedStringValue nameHolder = new TypedStringValue(name);
nameHolder.setSource(parserContext.extractSource(methodEle));
RuleBasedTransactionAttribute attribute = new RuleBasedTransactionAttribute();
String propagation = methodEle.getAttribute(PROPAGATION_ATTRIBUTE);
String isolation = methodEle.getAttribute(ISOLATION_ATTRIBUTE);
String timeout = methodEle.getAttribute(TIMEOUT_ATTRIBUTE);
String readOnly = methodEle.getAttribute(READ_ONLY_ATTRIBUTE);
if (StringUtils.hasText(propagation)) {
attribute.setPropagationBehaviorName(RuleBasedTransactionAttribute.PREFIX_PROPAGATION + propagation);
}
if (StringUtils.hasText(isolation)) {
attribute.setIsolationLevelName(RuleBasedTransactionAttribute.PREFIX_ISOLATION + isolation);
}
if (StringUtils.hasText(timeout)) {
try {
attribute.setTimeout(Integer.parseInt(timeout));
}
catch (NumberFormatException ex) {
parserContext.getReaderContext().error("Timeout must be an integer value: [" + timeout + "]", methodEle);
}
}
if (StringUtils.hasText(readOnly)) {
attribute.setReadOnly(Boolean.valueOf(methodEle.getAttribute(READ_ONLY_ATTRIBUTE)));
}
List<RollbackRuleAttribute> rollbackRules = new LinkedList<RollbackRuleAttribute>();
if (methodEle.hasAttribute(ROLLBACK_FOR_ATTRIBUTE)) {
String rollbackForValue = methodEle.getAttribute(ROLLBACK_FOR_ATTRIBUTE);
addRollbackRuleAttributesTo(rollbackRules,rollbackForValue);
}
if (methodEle.hasAttribute(NO_ROLLBACK_FOR_ATTRIBUTE)) {
String noRollbackForValue = methodEle.getAttribute(NO_ROLLBACK_FOR_ATTRIBUTE);
addNoRollbackRuleAttributesTo(rollbackRules,noRollbackForValue);
}
attribute.setRollbackRules(rollbackRules);
transactionAttributeMap.put(nameHolder, attribute);
}
//3.最终使用了一个Class为NameMatchTransactionAttributeSource的BeanDefinition,保存这些源信息
//使用的时候可以通过方法名获取事务信息
RootBeanDefinition attributeSourceDefinition = new RootBeanDefinition(NameMatchTransactionAttributeSource.class);
attributeSourceDefinition.setSource(parserContext.extractSource(attrEle));
attributeSourceDefinition.getPropertyValues().add("nameMap", transactionAttributeMap);
return attributeSourceDefinition;
}
该方法是用来解析<tx:method/>
标签的实现,核心流程也很简单,就是申明了Map
,key
为name
,value
为RuleBasedTransactionAttribute
,该类存储了事务的属性定义,最终申明了一个Class
为NameMatchTransactionAttributeSource
的BeanDefinition
,将上述的map
作为属性。
这里使用到了两个类:RuleBasedTransactionAttribute
和NameMatchTransactionAttributeSource
。
RuleBasedTransactionAttribute
是TransactionDefinition
的实现,用于保存事务的属性定义,方便执行事务的时候获取。
NameMatchTransactionAttributeSource
是TransactionAttributeSource
的子类,TransactionAttributeSource
只提供了一个方法:
TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass);
根据方法获取事物的属性(TransactionAttribute
)。
那么TransactionAttributeSource
这个接口的作用也显而易见了,用于保存标签解析的时候的事务属性,在执行事物的时候,通过方法名从该接口中获取解析的时候保存的事务属性,具体是从之前的nameMap
中获取,以便事务的执行。
2.基于注解
AnnotationDrivenBeanDefinitionParser
用于解析<tx:annotation-driven/>
标签。
案例:
<tx:annotation-driven transaction-manager="transactionManager"/>
org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser#parse
:
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
//1.注册事务监听器工厂
registerTransactionalEventListenerFactory(parserContext);
String mode = element.getAttribute("mode");
//2.aspectj
if ("aspectj".equals(mode)) {
// mode="aspectj"
registerTransactionAspect(element, parserContext);
}
//3.aop
else {
// mode="proxy"
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}
基于注解的方式实现主要有两种方式,第一种是基于AspectJ
,另一种是基于AOP
的,可以通过指定mode
属性决定,默认情况都是基于AOP
的。
org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer#configureAutoProxyCreator
:
/**
* 一个内部类依赖AOP实现的时候使用
*/
private static class AopAutoProxyConfigurer {
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
//1.注入class为InfrastructureAdvisorAutoProxyCreator的BeanDefinition,处理了proxy-target-class
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
Object eleSource = parserContext.extractSource(element);
//2.创建一个class为AnnotationTransactionAttributeSource的BeanDefinition,用来保存@Transactional注解的内容
RootBeanDefinition sourceDef = new RootBeanDefinition(
"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
sourceDef.setSource(eleSource);
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
//3.创建一个class为TransactionInterceptor的BeanDefinition,这和Aop是一样的,任何通知最终都是转为Interceptor
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
interceptorDef.setSource(eleSource);
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//4.注册TransactionManager的名称,如果没有指定,默认是transactionManager
registerTransactionManager(element, interceptorDef);
interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
//5.创建一个class为BeanFactoryTransactionAttributeSourceAdvisor的BeanDefinition,保存了上述两个BeanDefinition
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);
}
}
}
首先把<tx:annotation-driven/>
标签解析Class
为InfrastructureAdvisorAutoProxyCreator
的BeanDefinition
,后续创建代理的时候使用这个;然后创建了一个Class
为AnnotationTransactionAttributeSource
的BeanDefintiion
,这个类和NameMatchTransactionAttributeSource
功能是一样的,只不过一个服务于注解,一个服务于XML
;然后创建了一个Class
为TransasactionInterceptor
的BeanDefinition
,这和基于注解的是一样的,并且注册IOC容器管理的TransasctionManager
;最后创建了一个Class
为BeanFactoryTransactionAttributeSourceAdvisor
的BeanDefinition
,这个BeanDefinition
将上述的TransactionAttributeSource
和TransactionInterceptor
的作为属性,后面进行拦截的时候就会使用这个Advisor
。
两种事务定义的方式使用了不同的自动创建方式,InfrastructureAdvisorAutoProxyCreator
只服务于Spring
内部的基础设施类。AspectJAwareAdvisorAutoProxyCreator
定义了Advisor
扩展以及同一切面的不同建议的执行顺序。
AnnotationTransactionAttributeSource
继承了AbstractFallbackTransactionAttributeSource
,AbstractFallbackTransactionAttributeSource
实现了TransactionAttributeSource
。AbstractFallbackTransactionAttributeSource
中有一个Map
用于缓存TransactionAttribute
。
private final Map<Object, TransactionAttribute> attributeCache =
new ConcurrentHashMap<Object, TransactionAttribute>(1024);
这个attributeCache
的key
为MethodClassKey
,当从AnnotationTransactionAttributeSource
中获取TransactionAttribute
的时候,就是从这个缓存中获取。在NameMatchTransactionAttributeSource
也有一个相似的缓存,只不过key
为方法名。
TransactionInterceptor
和AOP
的五种通知的Interceptor
是一样的,都是MethodInterceptor
的子类,实现了invoke
方法,执行事务拦截的时候会执行。
3.创建代理
上面解析BeanDefinition
的时候,已经知道了基于XML
的时候使用的是AspectJAwareAdvisorAutoProxyCreator
,而基于注解的使用的是InfrastructureAdvisorAutoProxyCreator
,这两个类都是AbstractAutoProxyCreator
的子类,事务创建代理的入口,也就是在这个类中。
1.postProcessBeforeInstantiation
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation
:
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
//1.不需要创建代理
if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//2.如果是基础设施或者应该跳过的类,则说明这个类不需要创建代理,缓存起来
//默认shouldSkip是false,都不应该跳过
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
//2.对于自定义的TargetSource会立即创建代理,并缓存
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
//如果不是TargetSource,一般不会走到这里
if (targetSource != null) {
this.targetSourcedBeans.add(beanName);
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
}
return null;
}
这个方法实现了InstantiationAwareBeanPostProcessor
的方法,用于在Bean
实例化之前做处理。这里的是为了判断某个Bean
是否需要创建代理,如果Bean
是基础设施类(Advisor
、Advice
、Pointcut
、AopInfrastructureBean
)或者应该跳过,则这些Bean
不需要被创建代理。
注解:
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
return false;
}
XML
:
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
//1.获取容器中所有的Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
//对于<aop:aspect/>是AspectJPointcutAdvisor
if (advisor instanceof AspectJPointcutAdvisor) {
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
return true;
}
}
}
return super.shouldSkip(beanClass, beanName);
}
是否应该跳过,在AbstractAutoProxyCreator
中默认都是false
,InfrastructureAdvisorAutoProxyCreator
没有重写整个方法;AspectJAwareAdvisorAutoProxyCreator
重写了该方法,会判断切面是否是当前的Bean
,如果是,则应该跳过,但是由于<aop:advisor/>
使用的是DefaultBeanFactoryPointcutAdvisor
,所以这里正常情况下也是返回false
,这里还调用了一个findCandidateAdvisors
方法,这个方法用于获取容器管理的Advisor
,然后进行缓存,相对于注解的方式来说Advisor
实例化的时间要提前了一点。
org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans
:
public List<Advisor> findAdvisorBeans() {
//1.缓存的通知器的名称
String[] advisorNames = this.cachedAdvisorBeanNames;
//2.如果cachedAdvisorBeanNames为空,则到容器中查找
//并设置缓存,后续直接使用缓存即可
if (advisorNames == null) {
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<Advisor>();
}
List<Advisor> advisors = new ArrayList<Advisor>();
//3.遍历所有的通知器名称
for (String name : advisorNames) {
if (isEligibleBean(name)) {
//4.忽略正在创建的advisor
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping currently created advisor '" + name + "'");
}
}
else {
//5.从容器中获取Advisor,并添加到advisors中,在这个时候Advisor就被实例化了
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
}
}
return advisors;
}
最后,对于不需要代理的Bean
进行缓存,以便在后面创建代理的时候用作判断,这里只放了核心代码。
2.postProcessAfterInitialization
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
:
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//如果需要,为bean生成代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
这个方法实现了BeanPostProcessor
的方法,这里只放了核心代码,在Bean
初始化方法之后执行,这里的作用就是为Bean
创建代理。
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//1.直接使用上面的缓存判断
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//2.这里再判断一次,方式和之前是一样的,防止之前缓存中没有
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//3.为目标Bean查找合适的通知和通知器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//4.如果通知存在,则生成代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//5.创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
//6.通知不存在,直接返回bean
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
逻辑也很简单,首先判断这个Bean
是否之前已经被缓存了应该跳过或者重新使用之前的判断方式再判断一遍,确保当前的Bean
是需要创建代理的;然后就是为目标Bean
获取符合该Bean
可用的Advisor
;最后创建代理。
获取候选Advisor
:
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
:
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//1.查找所有的通知器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//2.筛选可以在该bean上应用的通知器,通过ClassFilter和MethodMatcher对目标类和方法进行匹配
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
//3.扩展操作
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
首先查找所有的通知器,这里对于XML
形式的由于之前shouldSkip
的时候已经实例化了Advisor
,所以直接可以从缓存中获取实例,而对于注解的方式,就需要现在实例化容器中所有的Advisor
,拿到其实例;然后判断获取到的Advisor
哪些适用于当前Bean
,这里会使用到Pointcut
的ClassFilter
和MethodMatch
;最后是扩展Advisor
,对于XML
会在列表头部加入一个ExposetInvocationInterceptor
,使用线程单例记录当前执行的MethodInvocation
,对于注解形式不会进行扩展。
匹配当前Bean
的Advisor
:
org.springframework.aop.support.AopUtils#canApply
:
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
//1.从通知器中获取ClassFilter,并调用matches进行匹配
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
//2.对于普通Advisor,这里继续调用重载方法进行筛选
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
无论是DefaultBeanFactoryPointcutAdvisor
还是BeanFactoryTransactionAttributeSourceAdvisor
都是PointcutAdvisor
,这里会拿Pointcut
去匹配。
XML
:
org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#getPointcut
:
public class DefaultBeanFactoryPointcutAdvisor extends AbstractBeanFactoryPointcutAdvisor {
private Pointcut pointcut = Pointcut.TRUE;
public void setPointcut(Pointcut pointcut) {
this.pointcut = (pointcut != null ? pointcut : Pointcut.TRUE);
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
虽然该类默认是Pointcut.TRUE
,但是这里拿到的是AspectJExpressionPointcut
,因为该Advisor
使用的是AspectJExpressionPointcut
,默认值被覆盖了,后面匹配就会使用AspectJExpressionPointcut
的ClassFilter
和MethodMatcher
。
注解:
org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor
:
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
对于DeafultBeanFactoryPointcutAdvisor
在这一步只是简单的进行匹配,具体的匹配过程比较复杂;BeanFactoryTransactionAttributeSourceAdvisor
使用的是TransactionAttributeSourcePointcut
去匹配,TransactionAttributeSourcePointcut
使用了ClassFilter.TRUE
,也就是说只用方法匹配,类匹配始终都会成功。
org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut#matches
:
@Override
public boolean matches(Method method, Class<?> targetClass) {
//如果已经是代理了,则不需要代理了
if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
/**
* 交给子类去实现
*/
protected abstract TransactionAttributeSource getTransactionAttributeSource();
BeanFactoryTransactionAttributeSourceAdvisor
通过匿名内部类的方式重写了getTransactionAttributeSource
方法。
org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute
:
@Override
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
//1.从缓存中获取,开始肯定为NULL
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
}
else {
//2.获取@Transactional的属性值,并放入缓存
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
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.isDebugEnabled()) {
logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
这个方法就是用来获取@Transactional
注解的属性值,并放入缓存,后面执行事务的时候可以直接获取属性值来决定事物的执行。
org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#computeTransactionAttribute
:
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
//1.不允许非公共方法
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
//2.获取真正的目标类
Class<?> userClass = ClassUtils.getUserClass(targetClass);
//3.给定的方法如果在接口中,并且目标类在通过反射调用,则获取目标类的方法,否则方法不变
Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
//4.如果要处理泛型参数,则需要找到原始方法
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
//5.尝试在目标方法上查找@Transactional注解
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
//6.目标方法上没找到,则去目标类查找
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
//7.如果传入的方法不等于指定的方法,上面都没获取到,则回滚到原始方法获取
if (specificMethod != method) {
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
首先根据传入的方法找到真正的目标方法,比如传入的方法在接口中,则需要找到正在调用的接口的实现类重写的方法;然后先从方法中获取@Transactional
注解的属性值,如果方法中没有,则在方法对应的类上获取@Transactional
注解的属性值;如果都没有获取到,并传入的方法不等于获取的目标方法,则使用传入的方法在方法上获取@Transactional
注解的属性值,如果没有获取到,则从传入的方法的类中获取@Transactional
注解的属性值;最终都没有,则返回null
。
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#findTransactionAttribute
:
Override
protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
return determineTransactionAttribute(clazz);
}
@Override
protected TransactionAttribute findTransactionAttribute(Method method) {
return determineTransactionAttribute(method);
}
这里申明了两个重载方法,分别对应根据类和根据方法获取。最终都是调用一个核心方法determineTransactionAttribute
。
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#determineTransactionAttribute
:
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
if (element.getAnnotations().length > 0) {
//TransactionAnnotationParser一般都是SpringTransactionAnnotationParser
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
}
return null;
}
遍历所有的事务注解解析器,如果有其中一个能解析成功,则说明拿到了当前事务的事务属性值,直接返回即可。这里的TransactionAnnotationParser
一般都是SpringTransactionAnnotationParser
。
org.springframework.transaction.annotation.SpringTransactionAnnotationParser#parseTransactionAnnotation
:
@Override
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
//这个AnnotationAttributes本质上就是个LinkedHashMap,添加了注解相关的几个属性,以及根据key方便获取枚举的方法
//这里面比较复杂,知道把@Transactional注解属性值解析成了一个Map就成
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(
element, Transactional.class);
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
org.springframework.transaction.annotation.SpringTransactionAnnotationParser#parseTransactionAnnotation
:
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
Propagation propagation = attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());
Isolation isolation = attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
rbta.setTimeout(attributes.getNumber("timeout").intValue());
rbta.setReadOnly(attributes.getBoolean("readOnly"));
rbta.setQualifier(attributes.getString("value"));
List<RollbackRuleAttribute> rollbackRules = new ArrayList<RollbackRuleAttribute>();
for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
rbta.setRollbackRules(rollbackRules);
return rbta;
}
可以看到最终也是RuleBasedTransactionAttribute
,这和基于XML
是一样的,拿到值之后,一路返回,进行缓存,方便执行事务的获取,也说明了当前Advisor
和目标方法匹配成功。
3. 创建代理
拿到了适合当前Bean
的Advisor
,接下来就是创建代理了,这里基于XML
和注解的都是一模一样的了,当然和AOP
创建代理的方式也是一模一样的。
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
:
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
//1.默认情况下,proxy-target-class=false,使用jdk动态代理
if (!proxyFactory.isProxyTargetClass()) {
//判断proxy-target-class属性
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
//2.检查目标类是否实现了接口,如没有,则设置proxy-target-class=true,使用cglib动态代理
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//3.将specificInterceptors中含有的Advice转为Advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//4.创建代理
return proxyFactory.getProxy(getProxyClassLoader());
}
使用了一个代理工厂ProxyFactory
去创建代理对象,设置了如targetSource
、Advisor
、proxyTargetClass
等属性,为后面的创建代理做准备。
判断使用何种代理方式:
org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy
:
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//1.是否需要优化||代理类型(前面已经设置过了)||是否实现了接口
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);
}
//2.使用cglib动态代理
return new ObjenesisCglibAopProxy(config);
}
else {
//3.使用jdk动态代理
return new JdkDynamicAopProxy(config);
}
}
这里会判断使用何种方式去创建代理,在Java
中主要有两种创建代理的的方式:1.JDK
;2.CGLIB
。默认情况下使用JDK
方式,当然如果目标Bean
没有实现接口,则会使用CGLIB
,也可通过设置proxy-target-class
属性决定使用何种代理方式。
JDK
:
@Override
public Object getProxy(ClassLoader classLoader) {
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
CGLIB
:
@Override
public Object getProxy(ClassLoader classLoader) {
//1.从TargetSource获取target的class
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
//2.判断是否已经是代理类了
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
validateClassIfNecessary(proxySuperClass, classLoader);
//3.CGLIB
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));
//4.各种回调
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
//5.回调过滤
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
//6.创建代理实例
return createProxyClassAndInstance(enhancer, callbacks);
}
这两种方式基本上都是标准的实现。
代理Bean
创建完成并返回,后续执行都是通过代理Bean
来实现的。
转载自:https://juejin.cn/post/6871417737290186760