我们总结出AOP公式
本质都是在内存中生成了新的字节码类。
这节我们看看事务是如何利用AOP实现的。
@EnableTransactionManagement的@Import(TransactionManagementConfigurationSelector.class)引入TransactionManagementConfigurationSelector.class。此类
@Override protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String[] { TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME}; default: return null; } } 复制代码
PROXY:情况下,会注册两个类:
实现了ImportBeanDefinitionRegistrar。其接口方法registerBeanDefinitions会向仓库注册Bean定义
InfrastructureAdvisorAutoProxyCreator。 InfrastructureAdvisorAutoProxyCreator
继承了AbstractAdvisorAutoProxyCreator间接继承了 AbstractAutoProxyCreator
在AOP代理生成那一节,我们讲过。 AnnotationAwareAspectJAutoProxyCreator
也是间接继承了 AbstractAutoProxyCreator
。
在AOP实现原理中 AbstractAutoProxyCreator
做了大部分工作。
从这一点看, 事务代理对象创建过程,与AOP代理对象过程是一样的,关键就在这个AbstractAutoProxyCreator类
是一个@Configuration。有三个@Bean注解方法。
@Configuration public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(transactionAttributeSource()); advisor.setAdvice(transactionInterceptor()); advisor.setOrder(this.enableTx.<Integer>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; } } 复制代码
首先:transactionAdvisor()方法会向仓库中注册一个BeanFactoryTransactionAttributeSourceAdvisor。
从其继承关系上看,他是一个Advisor,并且还是PointcutAdvisor.关于Advisor,上节我们分析过他是封装了(Advice+Pointcut)
既然都有了Advisor了,那Advice和Pointcut在哪里呢?
BeanFactoryTransactionAttributeSourceAdvisor有一个pointcut 属性,会new 一个TransactionAttributeSourcePointcut。
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() { @Override protected TransactionAttributeSource getTransactionAttributeSource() { return transactionAttributeSource; } }; 复制代码
从其继承关系,我们可以看出他其实就是一个Pointcut。
至此,就剩下Advice没有被发现。
2.TransactionAttributeSource: 其次:transactionAttributeSource()会向仓库中注册一个AnnotationTransactionAttributeSource。这个AnnotationTransactionAttributeSource干嘛用的呢?
BeanFactoryTransactionAttributeSourceAdvisor.setTransactionAttributeSource(transactionAttributeSource()) 属性值 private TransactionAttributeSource transactionAttributeSource; private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() { @Override protected TransactionAttributeSource getTransactionAttributeSource() { return transactionAttributeSource; } }; TransactionAttributeSourcePointcut的matche方法 @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); } 复制代码
AnnotationTransactionAttributeSource对象会赋值给BeanFactoryTransactionAttributeSourceAdvisor的 transactionAttributeSource
属性。 pointcut
属性初始化时,new 一个 TransactionAttributeSourcePointcut类
并实现 getTransactionAttributeSource()
方法, getTransactionAttributeSource()
方法正好返回了 transactionAttributeSource
属性。
也就是说TransactionAttributeSourcePointcut的getTransactionAttributeSource()方法返回的是 AnnotationTransactionAttributeSource
3.TransactionInterceptor: 最后:transactionInterceptor()方法,会向仓库中注册一个TransactionInterceptor类。
TransactionInterceptor从继承关系看他是一个Advice. 也就是增强器,是对事务真正处理地方。
有了Advice+Pointcut。Advice+Pointcut = Advisor 。 Advisor+TargetSource = Advised
有了Advised ,这样spring事务不正是套用了AOP的基础吗。
在AOP源码分析那一节,我们讲过,postProcessAfterInitialization后置初始化方法中,wrapIfNecessary 满足条件,才创建代理。
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } 复制代码
而这个条件就是:getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); 能够获取适用于当前bean的Advisor
我们回顾上节:
getAdvicesAndAdvisorsForBean 经过 AbstractAdvisorAutoProxyCreator.findEligibleAdvisors
的调用, AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass)
的调用,最终会调用 AopUtils.canApply
来判断某个Advisor是否适用于当前类。
我们来看看canApply方法
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) { PointcutAdvisor pca = (PointcutAdvisor) advisor; return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { // It doesn't have a pointcut so we assume it applies. return true; } } 复制代码
上文提到,
所以此处会走: canApply(pca.getPointcut(), targetClass, hasIntroductions)分支。
pca.getPointcut()
返回的是 TransactionAttributeSourcePointcut
进一步分析重载方法canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions)
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<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); classes.add(targetClass); for (Class<?> clazz : classes) { 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
的父类 StaticMethodMatcherPointcut.classFilter= ClassFilter.TRUE
表示类检查全部通过 abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable { @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); } } 复制代码
matches方法会调用 getTransactionAttributeSource()
获取一个 TransactionAttributeSource
对象,通过 TransactionAttributeSource.getTransactionAttribute(method, targetClass)
,来判断适应性。
关于 getTransactionAttributeSource()
上文讲过。会返回一个 AnnotationTransactionAttributeSource
实例对象。
也就是说: TransactionAttributeSourcePointcut 的 matches()方法是通过AnnotationTransactionAttributeSource.getTransactionAttribute(method, targetClass)来实现的 。
来看看getTransactionAttribute()方法
@Override public TransactionAttribute getTransactionAttribute(Method method, 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 { // We need to work it out. 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.isDebugEnabled()) { logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr); } this.attributeCache.put(cacheKey, txAttr); } return txAttr; } } 复制代码
这里用了一个缓存,但重点在这个 TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) { // Don't allow no-public methods as required. // 非public方法事务不生效。 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); // First try is the method in the target class. //首先查看实现类方法上是否有@Transactional注解 TransactionAttribute txAttr = findTransactionAttribute(specificMethod); if (txAttr != null) { return txAttr; } // Second try is the transaction attribute on the target class. //其次查看实现类方法所在类上是否有@Transactional注解 txAttr = findTransactionAttribute(specificMethod.getDeclaringClass()); if (txAttr != null && ClassUtils.isUserLevelMethod(method)) { return txAttr; } if (specificMethod != method) { // Fallback is to look at the original method. //还不行去看接口方法上是否有@Transactional注解 txAttr = findTransactionAttribute(method); if (txAttr != null) { return txAttr; } // Last fallback is the class of the original method. //最后看接口上是否有@Transactional注解 txAttr = findTransactionAttribute(method.getDeclaringClass()); if (txAttr != null && ClassUtils.isUserLevelMethod(method)) { return txAttr; } } return null; } 复制代码
由此:我们们也终于知道,@Transactional注解的查找顺序,实现类方法--》实现类--》接口方法--》接口 我们在这四个地方添加@Transactional注解都会使事务生效。
在这四个地方任一一个地方找到了@Transactional注解,说明 BeanFactoryTransactionAttributeSourceAdvisor
适用于当前类,getAdvicesAndAdvisorsForBean 的返回不为空。接下来就可以创建动态代理了。
// 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; } 复制代码
createProxy()方法,在 spring源码系列8:AOP源码解析之代理的创建 一节我们一节分析过了。
最终的结果就是通过 CglibAopProxy. getProxy()返回代理对象 或者 JdkDynamicAopProxy. getProxy()返回代理对象
spring事务,就是在spring AOP基础上实现的。 通过定义一个适用于事务的Advisor(Advice+Pointcut)完美的套用AOP的东西,实现了事务。
我们看看这个公式:
试想,如果我们可不可以利用这个公式也能创建出一个类似事务的东西呢?