javascript
Spring提取@Transactional事务注解的源码解析
聲明:本文是自己在學習spring注解事務處理源代碼時所留下的筆記; 難免有錯誤,敬請讀者諒解!!!
1、事務注解標簽
<tx:annotation-driven />2、tx 命名空間解析器?
事務tx命名空間解析器TxNamespaceHandler?
org.springframework.transaction.config.TxNamespaceHandler#init
3、AnnotationDrivenBeanDefinitionParser#parse 解析事務標簽
(1)、以下方法的核心邏輯主要是選擇是否使用 Aspect 方式實現代理,默認方式為 JDK 的動態代理。?
org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser#parse
(2)、進入如下方法,該方法的核心邏輯通過硬編碼的方式配置 Aop 動態代理的解析器?
AopAutoProxyConfigurer#configureAutoProxyCreator?
通過硬編碼,Spring 為我們定義了如下的 Spring BeanDefinition 對象?
(a)、AnnotationTransactionAttributeSource.class 事務注解屬性解析器BeanDefinition 對象。?
AnnotationTransactionAttributeSource 構造方法會初始化:
(b)、TransactionInterceptor.class 事務攔截器BeanDefinition 對象?
(c)、BeanFactoryTransactionAttributeSourceAdvisor.class 事務切面解析器?
(d)、TransactionInterceptor.class 事務攔截器BeanDefinition 對象?
(e)、容易忽略的第一行代碼:AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element); 在這個方法內部 Spring 為我們的注入了:InfrastructureAdvisorAutoProxyCreator.class?
4、Spring Bean 實例化創建代理對象?
(a)、AbstractAutowireCapableBeanFactory#initializeBean(Java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
(b)、AbstractAutoProxyCreator#postProcessAfterInitialization?
還記得上面我們提到的 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)、獲取到的事務切面?
(d)、事務切面獲取邏輯?
(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)、最終生成代理對象?
5、代理類執行?
JdkDynamicAopProxy#invoke
7、代理會執行到: ReflectiveMethodInvocation#proceed 方法
8、最終會執行到:TransactionInterceptor#invoke 方法
9、執行 TransactionAspectSupport 事務方法?
TransactionInterceptor#invoke 方法會調用到父類的 TransactionAspectSupport#invokeWithinTransaction 方法
10、業務方法執行?
11、Spring 事務處理的流程?
(a)、開啟事務?
(b)、事務回滾?
(c)、事務提交?
?
?
聲明:本編文章是自己在查看spring提取@Transactional注解的源碼過程中隨手記下的筆記,只做了大概流程的記錄,未做詳細分析,如有錯誤還請諒解。
1、事務切面匹配處理類
AopUtils#canApply(Pointcut, Class , boolean)?
方法中會調用到 TransactionAttributeSourcePointcut#matches 方法
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);}@Overridepublic 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());}@Overridepublic int hashCode() {return TransactionAttributeSourcePointcut.class.hashCode();}@Overridepublic 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() {@Overrideprotected 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;}}3、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);}} }4、TransactionAttributeSource#getTransactionAttribute 方法的調用過程
通過以上的分析,我們可以確定?
TransactionAttributeSourcePointcut#getTransactionAttributeSource 返回的是:AnnotationTransactionAttributeSource 實例,AnnotationTransactionAttributeSource繼承自:AbstractFallbackTransactionAttributeSource, 故此TransactionAttributeSourcePointcut#matches 最終會調用到 AbstractFallbackTransactionAttributeSource#getTransactionAttribute 方法
再看 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;} }5、事務屬性的推算過程:
// 推算事務屬性,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; }6、事務注解屬性的解析
AnnotationTransactionAttributeSource#findTransactionAttribute(Java.lang.Class
7、獲取事務注解
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;}@Overridepublic boolean equals(Object other) {return (this == other || other instanceof SpringTransactionAnnotationParser);}@Overridepublic int hashCode() {return SpringTransactionAnnotationParser.class.hashCode();}}http://blog.csdn.net/dalinsi/article/details/53215041
轉載于:https://www.cnblogs.com/softidea/p/6854982.html
總結
以上是生活随笔為你收集整理的Spring提取@Transactional事务注解的源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 11.python并发入门(part8
- 下一篇: 解Bug之路-Druid的Bug