@Transactional标签用于Spring中的事务标记。
先简单说下几个概念:
1)Spring的AOP是应用于Spring管理的bean上并基于代理实现的,代理的方法有java动态代理和CGLib动态代理方式,在不进行任何设置时,如果一个被代理的类实现了接口,就优先使用java动态代理。
2)Spring在bean的创建过程中将代理应用于bean上,代理的创建有这么一个重要的类AbstractAutoProxyCreator,这个类用于自动代理的创建,而这个类实现的接口中有BeanPostProcessor这个接口。但是这个类是一个抽象类,因为系统会根据不同的配置方式创建不同的子类:
对于aop:config的标签,创建的是AspectJAwareAdvisorAutoProxyCreator类,对于aspectj-autoproxy标签,创建的是AnnotationAwareAspectJAutoProxyCreator类。其继承结构如下:
3)BeanPostProcessor的几个方法都是钩子函数,Spring容器管理的bean在创建过程中会调用实现了BeanPostProcessor的类的几个方法,用于修改创建的bean的实例。
4)Spring中aop采用了aopalliance的约定,Advice是一个标记接口,其子接口为Interceptor,事务的实现类就是一个Interceptor。Advisor接口用来包含Advice和其他一些信息,分为IntroductionAdvisor和PointcutAdvisor两个分支,前者只能应用于类层面。事务管理中的Advisor类是BeanFactoryTransactionAttributeSourceAdvisor,是PointcutAdvisor的一个分支。
5)事务的Interceptor为TransactionInterceptor
那么我们从AbstractAutoProxyCreator作为入口进行源代码的分析:
首先看实现的BeanPostProcessor的钩子函数
/**
* 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;
}
这个方法的注释说明了这个方法的作用是:创建代理并应用所配置的interceptor于其上。
沿着这个方法继续查看wrapIfNecessary方法的代码片断:
// Create proxy if we have advice.
// 查找这个bean的adive和advisor
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;
}
可以发现,系统将查找应用于这个bean上的advice和advisor,然后根据此创建代理。getAdvicesAndAdvisorsForBean这个方式是一个模板方法,具体的实现由子类AbstractAdvisorAutoProxyCreator实现。
子类中getAdvicesAndAdvisorsForBean调用了findEligibleAdvisors函数:
//找到所有advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//过滤适用于这个bean的advisor
List<Advisor> eligibleA