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(); // 获取所有Advisor
ListAdvisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); // 寻找合法的Advisor
extendAdvisors(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.class
TransactionInterceptor.class
AnnotationTransactionAttributeSource
和 TransactionInterceptor
是 BeanFactoryTransactionAttributeSourceAdvisor
的属性。BeanFactoryTransactionAttributeSourceAdvisor
的属性 pointcut
代码如下:
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected 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 {
@Override
public 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
方法:
@Override
public 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())
寻找类上的事务注解,如果找到事务配置,则说明该方法应该被代理。