通常我们要开启spring的事务我们需要加上@EnableTransactionManagement这个注解,那么肯定的这个注解的作用就是往容器里面去import了一个组件从而使得方法上面的@Transaction注解生效,而且spring事务的原理也是基于代理去实现事务回滚,事务隔离等功能的,那么既然是基于代理的原理,spring的事务与springAOP在实现这方面上有何异曲同工之处呢?
首先来看看@EnableTransactionManagement这个注解做了什么事
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
这个注解往里面导入了一个TransactionManagementConfigurationSelector,最终这个selector往容器导入了两个组件,分别是AutoProxyRegistrar和ProxyTransactionManagementConfiguration
AutoProxyRegistrar
这个类又是一个ImportBeanDefinitionRegistrar组件,所以最终会调用registerBeanDefinitions这个方法,根据参数中的registry去向容器注册BeanDefinition,最终注册的逻辑:
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
上面的代码不必再过多解释,就是往容器中注册了一个InfrastructureAdvisorAutoProxyCreator这个类,接下来我们再来看下ProxyTransactionManagementConfiguration这个类
ProxyTransactionManagementConfiguration
@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());
if (this.enableTx != null) {
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;
}
}
这个类就是 一个配置类,里面配置3个需要往容器中去注册的Bean,分别是BeanFactoryTransactionAttributeSourceAdvisor,TransactionAttributeSource,TransactionInterceptor并且需要注意的是这三个bean都使用@Role注解声明为ROLE_INFRASTRUCTURE,这个在后面的代码中会用到。上面我们先总结下@EnableTransactionManagement注解最终做了就是往spring容器中导入了4个关键组件,分别是InfrastructureAdvisorAutoProxyCreator,BeanFactoryTransactionAttributeSourceAdvisor,TransactionAttributeSource,TransactionInterceptor
InfrastructureAdvisorAutoProxyCreator
先看下这个类的继承关系图
能够看到这个类最终也是继承于AbstractAutoProxyCreator,在前面SpringAOP的自动代理就说过这个类,这个类实现了BeanPostProcessor下面的两个子接口,所以在当bean在实例化之前和初始化之后都会被这个类所拦截,这里细节就不再多说,我们直接看拦截的方法
实例化之前org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
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;
}
这个方法在SpringAOP中主要就是去解析我们的aspect切面类得到解析后的advisor并缓存起来,而spring事务在这里却没有做什么事情。初始化之后就要来到bean的初始化之后的后置处理了:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(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);
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;
}
和SpringAOP套路一样,都是在bean初始化的后置方法里面去生成代理对象,在生成代理对象之前会先寻找适合该bean使用的advisor,那么重点来看getAdvicesAndAdvisorsForBean这个方法
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 寻找适合的advisor
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 寻找候选的advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 从寻找到的候选的advisor中去找到适合该bean的advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
// 调用了AbstractAdvisorAutoProxyCreator中寻找候选advisor辅助类
return this.advisorRetrievalHelper.findAdvisorBeans();
}
这个辅助类重写了它父类的isEligibleBean方法,而isEligibleBean方法是判断advisor是否能够成为候选的条件判断方法
private class BeanFactoryAdvisorRetrievalHelperAdapter extends BeanFactoryAdvisorRetrievalHelper {
public BeanFactoryAdvisorRetrievalHelperAdapter(ConfigurableListableBeanFactory beanFactory) {
super(beanFactory);
}
@Override
protected boolean isEligibleBean(String beanName) {
return AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName);
}
}
根据上面我们的分析,上面的方法我们一直所执行的对象都是InfrastructureAdvisorAutoProxyCreator,只不过都是这个类的父类的方法,而在这里的isEligibleBean方法,里面调用的AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName)这句代码刚好就被InfrastructureAdvisorAutoProxyCreator所重写了
@Override
protected boolean isEligibleAdvisorBean(String beanName) {
return (this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) &&
this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
}
而在InfrastructureAdvisorAutoProxyCreator中重写判断advisor是否是候选的advisor的条件就是这个advisor的role等于BeanDefinition.ROLE_INFRASTRUCTURE,这个值是不是有点眼熟?没错,就是上面叫大家去注意的地方,回到ProxyTransactionManagementConfiguration这个类,这个类在spring容器进行bean注册的时候就往容器中放进了三个bean,而这三个bean的role都等于BeanDefinition.ROLE_INFRASTRUCTURE
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());
if (this.enableTx != null) {
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;
}
在这里就可以说下这三个bean的作用了,第一个bean是一个advisor,在寻找候选的advisor方法的时候会从容器中getBean可以得到,然后又符合了role等于BeanDefinition.ROLE_INFRASTRUCTURE的条件,所以此时最终候选的advisor只有这个advisor,第二个bean能够作用于advisor的pointcut处理,是用来配合处理判断目标bean是否符合这个advisor的,判断逻辑就是判断该bean的方法或者类上面是否有@Transactional注解,如果有就说明这个advisor适用于这个bean,而第三个就是我们的事务拦截器了,代理对象增强逻辑的地方,会处理有关spring事务的所有事情
总结
关于advisor中的pointcut的细节逻辑是怎样的,以及之后的事务增强的处理就不细说了,我们这里主要是去学习到了整个spring事务在创建代理以及寻找advisor,MethodInteceptor的过程与SpringAOP的相似之处,SpringAOP是会在bean实例化之前的前置处理会先去解析aspect切面并且把解析出来的advisor缓存起来,而spring事务在这一步基本上没做什么处理,然后在bean初始化的后置处理SpringAOP和spring事务都会去创建代理对象,但是两者在寻找advisor的逻辑上就有些不同,SpringAOP是会找出spring容器中所有的advisor(包括了解析aspect切面的advisor),而spring事务是找role等于BeanDefinition.ROLE_INFRASTRUCTURE的advisor,之后两者在判断适用于bean的advisor的pointcut的逻辑也是各自的不同,最后在代理对象执行方法的时候,如果单独只开启了spring事务那么此时的拦截链是只会有一个,就是上面注册的TransactionInterceptor这个bean