1.事务相关的类
spring 事务也是通过 aop 实现的,那肯定也有切面、切点、通知、为目标对象创建代理对象,代理对象执行目标方法等等。
先小小回顾一下普通 aop 的相关知识点:
- 切面、切点、通知 都是自定义的,根据需求开发不同的切面。
- 在项目启动时,
AnnotationAwareAspectJAutoProxyCreator
解析了所有切面 ,为每一个通知创建一个增强器,并将所有的增强器注入容器中。- 在项目启动时, bean被创建后要执行初始化,在初始化过程中,
AnnotationAwareAspectJAutoProxyCreator
发现该 bean 被增强器命中了(切了),就为该 bean 创建代理对象,并将代理对象注入容器中。- 最后是代理对象执行目标方法,并在恰当的时候执行通知。
事务肯定也有对应的组件以及流程。
但与普通 aop 不同的是,事务的通知内容不是千变万化的,它是固定的,而且 spring 已经已经写好了,我们只需要拿来使用就可以了。通知被解析后会变成一个增强器,既然通知的内容都固定了且已知了,那是不是增强器的主要内容也已经是固定的,后续只需要将切面以及其他少部分信息 set 进增强器就行了,所以事务的增强器 spring 也已经帮我们写好了,我们也只需要拿来使用就可以了。
So:
TransactionInterceptor
这就是事务的通知 Advice。BeanFactoryTransactionAttributeSourceAdvisor
事务的增强器。TransactionAttributeSourcePointcut
: 切点。主要负责方法匹配,就是找方法上有没有注解@Transactional
。TransactionAttributeSource
:解析方法上的@Transaction
注解中属性。并且将解析结果缓存到 map 中。InfrastructureAdvisorAutoProxyCreator
: 这是个 beanBostProcessor,为增强器命中的目标对象创建代理对象。
貌似缺了一个切面类,不缺的,因为事务的解析过程和普通 aop 不一样:
- 普通aop 解析过程,先从容器中拿所有
Object.class
,看类脑门上有没有@Aspect
注解,再解析切面的通知,为通知创建增强器. bulabulabula…。 - 事务解析过程,直接从容器中拿
Advisor.class
,它是直接拿增强器。
2. 事务准备过程
也可以说叫配置过程,事务需要用到上面 6 个类,怎么把这些类配置到项目中去呢?只有配置妥当了,启动时才能加载到,最后才能发挥事务的威力。
很简单,只需在配置类上加 @EnableTransactionManagement
注解。意为”启动事务管理“。
看下这个注解做了什么。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {}
@Import(TransactionManagementConfigurationSelector.class)
会在项目启动执行 BeanFactoryPostProcessor 时将 TransactionManagementConfigurationSelector 注入容器。
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<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;
}
}
// 剩余代码不贴了。
}
selectImports(AdviceMode adviceMode)
返回了一组全限定类名,在项目启动过程中,会根据类名解析每一个类。这里会解析两个类:AutoProxyRegistrar.class
和 ProxyTransactionManagementConfiguration.class
。
解析这两个类,到底是做了什么事情?
ProxyTransactionManagementConfiguration
有 Configuration 注解,那它就是个配置类,类中方法上有 @Bean 注解,这就很明了了。解析这个类实际上是向容器中注入了 bean。
注入了谁的bean?
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
// 注入事务增强器:BeanFactoryTransactionAttributeSourceAdvisor。
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
// 往增强器中set transactionAttributeSource,
// transactionAttributeSource 会解析方法上的 @Transactional 注解,将结果保存到增强器中。
advisor.setTransactionAttributeSource(transactionAttributeSource);
// 往增强器中set 通知。
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
// 注入 TransactionAttributeSource
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
// 注入通知。
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
AutoProxyRegistrar
将 InfrastructureAdvisorAutoProxyCreator
注入到了容器。
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
private final Log logger = LogFactory.getLog(getClass());
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
// 走这里
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
if (!candidateFound && logger.isInfoEnabled()) {
String name = getClass().getSimpleName();
logger.info(String.format("%s was imported but no annotations were found " +
"having both 'mode' and 'proxyTargetClass' attributes of type " +
"AdviceMode and boolean respectively. This means that auto proxy " +
"creator registration and configuration may not have occurred as " +
"intended, and components may not be proxied as expected. Check to " +
"ensure that %s has been @Import'ed on the same class where these " +
"annotations are declared; otherwise remove the import of %s " +
"altogether.", name, name, name));
}
}
}
往下走…
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
// ----
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 关键信息:InfrastructureAdvisorAutoProxyCreator.class
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;
}
// cls = InfrastructureAdvisorAutoProxyCreator.class
// 为 cls 创建 beanDefinition。
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 将 beanDefinition 注入容器。
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
就这么一个注解,将:
-
事务通知:
TransactionInterceptor
。 -
事务的增强器:
BeanFactoryTransactionAttributeSourceAdvisor
。 -
解析Transaction注解 :
TransactionAttributeSource
。 -
为增强器命中的目标对象创建代理对象:
InfrastructureAdvisorAutoProxyCreator
全都给配置好了,在项目启动过程中,这些类都会被注入容器。
准备过程结束后,开始下面的阶段:1. 将目标对象变成代理对象,2. 代理对象执行目标方法。
3. 将目标对象变成代理对象
这个阶段和普通 aop 几乎是一样的:先是生成 bean,在bean 的初始化阶段,如果 bean 被切了,就为bean生成代理对象。bean 的注入过程这里就不再描述了,这是 IOC 的过程。
直接场景假设:UserService 的 bean 已经被 create 完毕,接下来执行 initializeBean() 方法是为其创建代理对象。
@Service
public class UserService {
@AutoWired
public UserRepository userRepository;
@Transactional
public void testTranscation() throws Exception {
userRepository.updateUserMoney("diego",900);
}
}
这个过程要做三件事情:
- 从容器中获取增强器,是通过解析切面的方式,还是直接拿增强器,增强器都会被拿到。
- 判断 bean 是否被增强器切了。
- 如果被增强器切了,为 bean 生成代理对象。
3.1 从容器中获取事务的增强器
和普通 aop 的过程一样,事务的增强器也是在 create bean 之前就解析并注入容器了,在 bean 的初始化阶段直接从容器中拿增强器(如果没拿到才会再次解析,但一般都是拿到了)。
// AbstractAutowireCapableBeanFactory.java
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 走这里.....
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
// ---
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// AnnotationAwareAspectJAutoProxyCreator 调用 postProcessBeforeInstantiation()方法。
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
进去看看
// AbstractAutoProxyCreator.java
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;
}
// 在 shouldSkip 方法里解析的增强器并且缓存起来。
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// AspectJAwareAdvisorAutoProxyCreator.java
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 获取项目中所有的增强器。
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
// ----
protected List<Advisor> findCandidateAdvisors() {
// 先获取事务的增强器。
List<Advisor> advisors = super.findCandidateAdvisors();
if (this.aspectJAdvisorsBuilder != null) {
// 接下来再解析用户自定义的切面,生成增强器。
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
// 返回找到的所有的增强器。
return advisors;
}
最后一步了,看看怎么获取的事务的增强器。
// AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
// BeanFactoryAdvisorRetrievalHelper.java
public List<Advisor> findAdvisorBeans() {
// 先看下增强器之前有没有被获取到,如果有就直接去缓存中拿,不过没有再创建。
String[] advisorNames = this.cachedAdvisorBeanNames;
// 第一次肯定是之前没有被获取过,后续再次获取就是去缓存中直接拿了。
if (advisorNames == null) {
// 从 beanFactory 中获取所有的 Advisor.class 类型的 beanName。它的 beanDefinition 存在或者直接是 bean 都可以。
// 因为事务的通知spring已经写好了,直接通过增强器给注进来了,做以直接通过 Advisor.class 类型拿就行了。
// 不需要再走普通 aop 那套,先找切面,再找通知,最后为通知 new Advisor()。
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
// 将拿到的 advisorNames 保存到 cachedAdvisorBeanNames 中,表示这些 name 的增强器已经被缓存了。
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
// 保存所有的 advisor bean。
List<Advisor> advisors = new ArrayList<>();
// 遍历 advisorNames 获取每一个 advisor。
// 如果 bean存在直接从单例池中拿,
// 如果bean 不存在,通过 beanDefinition 创建一个。
for (String name : advisorNames) {
// 名字是合法的。
if (isEligibleBean(name)) {
// 如果正在创建中,那啥也不干,就打个日志。
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
// 如果不处于正在创建中,那么 getBean() 将其获取。单例池中有,直接拿,没有,走 createBean() 创建一个。
try {
// (先获取),再将拿到的 advisor 缓存到 advisors 中。
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
// 返回拿到的所有 Advisor。
return advisors;
}
从这里可以看到,所谓的获取增强器,一方面是真的拿到增请器并返回给函数调用,另一方面是指增强器被注入到了容器中。
在后面的初始化 bean 中,直接从容器中拿增强器。
3.2 判断 bean 是否被增强器切了
判断逻辑也很简单,UserService 的 Class 对象,依次去下面四个地方找有没有 @Transaction
注解,只要有一个地方有那就是被切了。
- UserService 的 每 public 一个方法上。
- UserService 类上。
- UserService 父类接口的每一个方法上。
- UserService 父类接口上。
下面看下具体的代码实现:
// AbstractAutoProxyCreator.java
/**
这里面:
1. 获取所有的增强器。
2. 删选有没有增强器切bean。
3. 如果有,为 bean 创建代理对象。
*/
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;
}
// 项目中的所有增强器在 doCreateBean 之前就已经解析好了,
// 这里是:1. 从容器中获取所有增强器;2. 筛选出那些切了当前 bean 的增强器,并返回。
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 如果 specificInterceptors 不为空,说明 bean 被切了。
if (specificInterceptors != DO_NOT_PROXY) {
// 设置需要为 cacheKey 创建代理。(标识符而已)
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理。
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 保存 cacheKey 的代理。
this.proxyTypes.put(cacheKey, proxy.getClass());
// 返回创建好的代理对象。
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
整体逻辑都在这里了,再往下走看下 判断 bean 被切的具体细节。
// AbstractAutoProxyCreator.java
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 为 beanClass 寻找符合条件的增强器(advisors)
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
// ---
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 找到所有候选的 advisors,包括事务的 advisor 和 普通 aop 的 advisor。。
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 在所有的 advisors 中筛选出切 bean 的 advisor。
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
// 返回符合条件的 advisor
return eligibleAdvisors;
}
// ---
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 走这里....
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
进到 AopUtils.java
中再看看
// AopUtils.java
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {。
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
continue;
}
// 在判断 advisor 能否使用在 clazz 上。
if (canApply(candidate, clazz, hasIntroductions)) {
// 如果可以,保存。
eligibleAdvisors.add(candidate);
}
}
// 返回所有能使用在 clazz 上的的 advisor。
return eligibleAdvisors;
}
// ---
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 {
return true;
}
}
// ---
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<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
// classes 中只有 UserService 的类对象。
for (Class<?> clazz : classes) {
// 获取类中的全部方法。
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
// 遍历每一个方法。(看方法上是否有 @Transaction 注解或者类上有 @Transaction 注解)
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
// 在这里判断的。
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
TransactionAttributeSourcePointcut
终于上场了,它去找目标类中有没有 @Transaction
注解。
public boolean matches(Method method, Class<?> targetClass) {
// TransactionAttributeSource 在这里被拿到了。
TransactionAttributeSource tas = getTransactionAttributeSource();
// tas.getTransactionAttribute() 找事务注解。
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
AbstractFallBackTransactionAttributeSource
执行了真正的找 @Transaction
注解 的逻辑。
// AbstractFallBackTransactionAttributeSource.java
// targetClass 是 UserService 的类对象,method 是 UserService 中的某个方法。
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
// method + class 作为 key。
Object cacheKey = getCacheKey(method, targetClass);
// 先去缓存中获取下,有没有这个 key 已经解析好的事务属性。
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// 如果能找到,但属性信息是空,那就表示,该方法上没有事务。。
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
// 属性信息不为空,那就直接返回事务注解的属性信息。
return cached;
}
}
else {
// 缓存里没有就需要自己解析了。
// 从目标类的方法、目标类、目标类实现的接口的方法、目标类实现的接口上依次查@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.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
// ---- 核心方法在这里 ----
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// 如果 @Transcational 标注在 非 public 方法上,则不解析。
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// 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;
}
}
// 如果都没有,那就返回 null。
return null;
}
这里的代码说明了两个事情:
- 上面写的找 @Transactional 顺序是对的。
- 非 public 方法上标 @Transactional 是无效的,因为源码根本就不解析。
那最后再看一个问题,到底是怎么解析到的 @Transactional 注解。
protected TransactionAttribute findTransactionAttribute(Method method) {
return determineTransactionAttribute(method);
}
// ---
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
// 这里有个事务注解解析器。
TransactionAttribute attr = parser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
return null;
}
// --- SpringTransactionAnnotationParser.java
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
// 解析的是 Transactional.class 类。
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
那些切 Uservice 的 增强器就是这么被筛选出来的。
接下来还剩最后一步,为 UserService 创建代理对象…
3.3 为目标对象创建代理对象。
这一块的逻辑和普通的 aop 没有什么区别。
-
创建代理工厂。
ProxyFactory proxyFactory = new ProxyFactory();
-
将目标对象和它的增强器都 set 到 代理工厂中。
proxyFactory.setTargetSource(targetSource); proxyFactory.addAdvisors(advisors);
-
代理工厂创建代理对象,并返回。
proxyFactory.getProxy(getProxyClassLoader())
代理对象中个既有目标对象也有目标对象的增强器,当代理对象执行目标方法时,在恰当时机将通知织入,自己是可以实现的。
#4. 代理对象执行目标方法
这部分也是好大的一块内容,单独写一篇博客吧,不然这篇博客得写的老长…
5. 发现一个小问题
我的事务配置是这样的。
@Configuration
@ComponentScan("com.jdbctemplate")
@EnableTransactionManagement
@EnableAspectJAutoProxy(exposeProxy = true)
public class JdbcConfig {
// ......
}
@EnableAspectJAutoProxy
注入了 AspectJAwareAdvisorAutoProxyCreator
类;
@EnableTransactionManagement
注入了 InfrastructureAdvisorAutoProxyCreator
类;
这两个都是BeanPostProcessor,都可以将 目标对象变成代理对象。
如果两个同时存在,在为事务相关的类创建目标对象时,会使用 AspectJAwareAdvisorAutoProxyCreator
将目标对象变成代理对象。
当去掉 @EnableAspectJAutoProxy
注解时,事务功能也能照常运行。