回顧下AOP相關知識點:
- 靜态代理與JDK動态代理與CGLIB動态代理
- Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的差別
- spring源碼系列8:AOP源碼解析之代理的建立
我們總結出AOP公式
- JDK動态代理(Proxy+InvocationHandler)+advised
- CGLB動态代理(Enhancer+MethodInterceptor)+advised
本質都是在記憶體中生成了新的位元組碼類。
這節我們看看事務是如何利用AOP實作的。
事務代理生成過程
一、@EnableTransactionManagement配置事務環境
@EnableTransactionManagement的@Import(TransactionManagementConfigurationSelector.class)引入TransactionManagementConfigurationSelector.class。此類
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
default:
return null;
}
}
PROXY:情況下,會注冊兩個類:
AutoProxyRegistrar:
實作了ImportBeanDefinitionRegistrar。其接口方法registerBeanDefinitions會向倉庫注冊Bean定義 InfrastructureAdvisorAutoProxyCreator。
InfrastructureAdvisorAutoProxyCreator
繼承了AbstractAdvisorAutoProxyCreator間接繼承了
AbstractAutoProxyCreator
。
在AOP代理生成那一節,我們講過。
AnnotationAwareAspectJAutoProxyCreator
也是間接繼承了
AbstractAutoProxyCreator
AbstractAutoProxyCreator
在AOP實作原理中做了大部分工作。
從這一點看,事務代理對象建立過程,與AOP代理對象過程是一樣的,關鍵就在這個AbstractAutoProxyCreator類
ProxyTransactionManagementConfiguration
是一個@Configuration。有三個@Bean注解方法。
- transactionAdvisor()
- transactionAttributeSource()
- transactionInterceptor()
@Configurationpublic 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());
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;
}}
1.BeanFactoryTransactionAttributeSourceAdvisor:
首先:transactionAdvisor()方法會向倉庫中注冊一個BeanFactoryTransactionAttributeSourceAdvisor。

從其繼承關系上看,他是一個Advisor,并且還是PointcutAdvisor.關于Advisor,上節我們分析過他是封裝了(Advice+Pointcut)
既然都有了Advisor了,那Advice和Pointcut在哪裡呢?
BeanFactoryTransactionAttributeSourceAdvisor有一個pointcut 屬性,會new 一個TransactionAttributeSourcePointcut。
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
從其繼承關系,我們可以看出他其實就是一個Pointcut。
至此,就剩下Advice沒有被發現。
2.TransactionAttributeSource:
其次:transactionAttributeSource()會向倉庫中注冊一個AnnotationTransactionAttributeSource。這個AnnotationTransactionAttributeSource幹嘛用的呢?
BeanFactoryTransactionAttributeSourceAdvisor.setTransactionAttributeSource(transactionAttributeSource())屬性值private TransactionAttributeSource transactionAttributeSource;private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};TransactionAttributeSourcePointcut的matche方法@Override
public boolean matches(Method method, Class<?> targetClass) {
if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
AnnotationTransactionAttributeSource對象會指派給BeanFactoryTransactionAttributeSourceAdvisor的
transactionAttributeSource
屬性。
pointcut
屬性初始化時,new 一個
TransactionAttributeSourcePointcut類
并實作
getTransactionAttributeSource()
方法,
getTransactionAttributeSource()
方法正好傳回了
transactionAttributeSource
也就是說TransactionAttributeSourcePointcut的getTransactionAttributeSource()方法傳回的是AnnotationTransactionAttributeSource
3.TransactionInterceptor :
最後:transactionInterceptor()方法,會向倉庫中注冊一個TransactionInterceptor類。
TransactionInterceptor從繼承關系看他是一個Advice. 也就是增強器,是對事務真正處理地方。
有了Advice+Pointcut。Advice+Pointcut = Advisor 。 Advisor+TargetSource = Advised
有了Advised ,這樣spring事務不正是套用了AOP的基礎嗎。
二、代理的生成
在AOP源碼分析那一節,我們講過,postProcessAfterInitialization後置初始化方法中,wrapIfNecessary 滿足條件,才建立代理。
@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;}
而這個條件就是:getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); 能夠擷取适用于目前bean的Advisor
1.Advisor尋找
我們回顧上節:
getAdvicesAndAdvisorsForBean 經過
AbstractAdvisorAutoProxyCreator.findEligibleAdvisors
的調用,
AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass)
的調用,最終會調用
AopUtils.canApply
來判斷某個Advisor是否适用于目前類。
我們來看看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;
}
}
上文提到,
- BeanFactoryTransactionAttributeSourceAdvisor 是一個PointcutAdvisor類型的Advisor
- BeanFactoryTransactionAttributeSourceAdvisor中new 一個TransactionAttributeSourcePointcut。
是以此處會走:
canApply(pca.getPointcut(), targetClass, hasIntroductions)分支。
pca.getPointcut()
傳回的是
TransactionAttributeSourcePointcut
進一步分析重載方法canApply(Pointcut pc, Class
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<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(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;
}
- 先ClassFilter.matches 校驗一次。
的父類TransactionAttributeSourcePointcut
表示類檢查全部通過StaticMethodMatcherPointcut.classFilter= ClassFilter.TRUE
- 再MethodMatcher.matches 方法進行校驗
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
@Override
public boolean matches(Method method, Class<?> targetClass) {
if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}}
matches方法會調用
getTransactionAttributeSource()
擷取一個
TransactionAttributeSource
對象,通過
TransactionAttributeSource.getTransactionAttribute(method, targetClass)
,來判斷适應性。
關于
getTransactionAttributeSource()
上文講過。會傳回一個
AnnotationTransactionAttributeSource
執行個體對象。
也就是說:TransactionAttributeSourcePointcut 的 matches()方法是通過AnnotationTransactionAttributeSource.getTransactionAttribute(method, targetClass)來實作的。
來看看getTransactionAttribute()方法
@Override
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
// First, see if we have a cached value.
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// Value will either be canonical value indicating there is no transaction attribute,
// or an actual transaction attribute.
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
}
else {
// We need to work it out.
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
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.isDebugEnabled()) {
logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
這裡用了一個緩存,但重點在這個
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
// Don't allow no-public methods as required.
// 非public方法事務不生效。
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// Ignore CGLIB subclasses - introspect the actual user class.
Class<?> userClass = ClassUtils.getUserClass(targetClass);
// 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 = ClassUtils.getMostSpecificMethod(method, userClass);
// If we are dealing with method with generic parameters, find the original method.
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
// 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;
}
}
return null;
}
由此:我們們也終于知道,@Transactional注解的查找順序,實作類方法–》實作類–》接口方法–》接口
我們在這四個地方添加@Transactional注解都會使事務生效。
在這四個地方任一一個地方找到了@Transactional注解,說明
BeanFactoryTransactionAttributeSourceAdvisor
适用于目前類,getAdvicesAndAdvisorsForBean 的傳回不為空。接下來就可以建立動态代理了。
2.代理的生成
// 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;
}
createProxy()方法,在spring源碼系列8:AOP源碼解析之代理的建立一節我們一節分析過了。
最終的結果就是通過
CglibAopProxy. getProxy()傳回代理對象
或者
JdkDynamicAopProxy. getProxy()傳回代理對象
總結:
- AOP = 動态代理+ Advised(Adisor+TargetSource);
- Adisor = Advice+Pointcut