1. Spring AOP 代理核心类
Spring AOP 借助 AnnotationAwareAspectJAutoProxyCreator.class 类对其他 Bean 进行代理。该类的父类 AbstractAutoProxyCreator 实现了 BeanPostProcessor 接口,在 Bean 实例化时会调用 postProcessAfterInitialization 方法,此方法又会调用 wrapIfNecessary 方法:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// ...忽略部分代码// 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;}}
上述方法会获取合法的 Advice 及 Advisor,进而创建代理。
2. 寻找合法的 Advisor
getAdvicesAndAdvisorsForBean 方法会调用 findEligibleAdvisors 方法:
protected ListAdvisor> findEligibleAdvisors(Class> beanClass, String beanName) {ListAdvisor> candidateAdvisors = findCandidateAdvisors(); // 获取所有AdvisorListAdvisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); // 寻找合法的AdvisorextendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}
进一步查看 findAdvisorsThatCanApply 方法中的 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;}}
若 Advisor 是 PointcutAdvisor 的子类,则会调用 canApply(pca.getPointcut(), targetClass, hasIntroductions) 方法:
public static boolean canApply(Pointcut pc, Class> targetClass, boolean hasIntroductions) {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;}SetClass>> classes = new LinkedHashSet();if (!Proxy.isProxyClass(targetClass)) {classes.add(ClassUtils.getUserClass(targetClass));}classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(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;}
上述代码先判断 Pointcut 的 classFilter 是否能匹配目标 Bean,接着获取 MethodMatcher,调用其 matches 方法匹配目标 Bean 所有接口中的方法。
3. Spring tx 模块判断 Bean 事务开启步骤
3.1 解析 annotation - driven 标签
查看 Spring 解析 annotation - driven 标签的解析器 AnnotationDrivenBeanDefinitionParser 类,其 parse 方法注册了三个类:
BeanFactoryTransactionAttributeSourceAdvisor.class:实现了PointcutAdvisor接口。AnnotationTransactionAttributeSource.classTransactionInterceptor.class
AnnotationTransactionAttributeSource 和 TransactionInterceptor 是 BeanFactoryTransactionAttributeSourceAdvisor 的属性。BeanFactoryTransactionAttributeSourceAdvisor 的属性 pointcut 代码如下:
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {@Override@Nullableprotected TransactionAttributeSource getTransactionAttributeSource() {return transactionAttributeSource;}};
3.2 TransactionAttributeSourcePointcut 类的 classFilter 设置
TransactionAttributeSourcePointcut 类的构造方法设置了 classFilter:
protected TransactionAttributeSourcePointcut() {setClassFilter(new TransactionAttributeSourceClassFilter());}
3.3 判断目标类是否可代理
回顾前面分析的 canApply 方法,第一步是获取 pointcut 的 classfilter,调用其 matches 方法判断目标类是否能进行代理。Spring tx 获取到的 classfilter 为 TransactionAttributeSourceClassFilter,其 matches 方法实现如下:
private class TransactionAttributeSourceClassFilter implements ClassFilter {@Overridepublic boolean matches(Class> clazz) {if (TransactionalProxy.class.isAssignableFrom(clazz) ||PlatformTransactionManager.class.isAssignableFrom(clazz) ||PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {return false;}TransactionAttributeSource tas = getTransactionAttributeSource();return (tas == null || tas.isCandidateClass(clazz));}}
getTransactionAttributeSource() 方法会调用到 BeanFactoryTransactionAttributeSourceAdvisor 的 private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() 处,返回初始化类时设置的 AnnotationTransactionAttributeSource 类实例。
3.4 判断目标类是否为候选类
tas.isCandidateClass(clazz) 代码如下:
public boolean isCandidateClass(Class> targetClass) {for (TransactionAnnotationParser parser : this.annotationParsers) {if (parser.isCandidateClass(targetClass)) {return true;}}return false;}
3.5 获取 MethodMatcher
TransactionAttributeSourcePointcut 的父类 StaticMethodMatcherPointcut 的 getMethodMatcher 方法实现为 return this,所以会调用 TransactionAttributeSourcePointcut 的 matches 方法:
@Overridepublic boolean matches(Method method, Class> targetClass) {TransactionAttributeSource tas = getTransactionAttributeSource();return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);}
同样会调用 AnnotationTransactionAttributeSource 的 getTransactionAttribute 方法:
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class> targetClass) {Object cacheKey = getCacheKey(method, targetClass);TransactionAttribute cached = this.attributeCache.get(cacheKey);if (cached != null) {if (cached == NULL_TRANSACTION_ATTRIBUTE) {return null;}else {return cached;}}else {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);}this.attributeCache.put(cacheKey, txAttr);}return txAttr;}}
3.6 计算事务属性
继续查看 computeTransactionAttribute 方法:
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class> targetClass) {// Don't allow no - public methods as required.if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {return null;}// 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 = AopUtils.getMostSpecificMethod(method, targetClass);// First try is the method in the target class.TransactionAttribute txAttr = findTransactionAttribute(specificMethod);if (txAttr != null) {return txAttr;}// Second try is the transaction attribute on the target class.txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {return txAttr;}if (specificMethod != method) {// Fallback is to look at the original method.txAttr = findTransactionAttribute(method);if (txAttr != null) {return txAttr;}// Last fallback is the class of the original method.txAttr = findTransactionAttribute(method.getDeclaringClass());if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {return txAttr;}}return null;}
该方法第一行判断 Method 是否为 public,只有 public 方法才合法。
接下来调用 findTransactionAttribute(specificMethod) 方法寻找方法上的事务注解,如果找不到,则调用 findTransactionAttribute(specificMethod.getDeclaringClass()) 寻找类上的事务注解,如果找到事务配置,则说明该方法应该被代理。
