欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring源码学习系列1.2-spring事务代理深入分析2

程序员文章站 2022-03-13 10:22:53
...
提示:
BeanPostProcessor

AopUtils

代理模式

spring中<aop:config/>,<tx:annotation-driver/>,<aop:aspectJ>等配置看似复杂,其实本质就是PointCut,BeanPostProcessor,AbstractAutoProxyCreator一些接口直接的解耦

查找的Advisor用到了模板方法设计模式和委托模式,创建代理类用到了代理模式




解析:
<tx:annotation-driven transaction-manager="transactionManager" /> - TxNamespaceHandler

spring中的该配置实际上就是注册了几个beanDefinition

InfrastructureAdvisorAutoProxyCreator - BeanPostProcess

AnnotationTransactionAttributeSource - 可以延伸为Pointcut

TransactionInterceptor - MethodInterceptor

TransactionAttributeSourceAdvisor - Advisor(其中持有TransactionAttributeSourcePointcut)



在bean实例化后,开始调用BeanPostProcess.postProcessAfterInitialization

1.首先查询所有的advisor

2.根据advisor中的pointcut校验bean是否符合该advisor,并返回methodInterceptor

3.将methodInterceptor通过适配器模式封装到advisors(这里的methodInterceptor是广义的概念,有可能是advice等)

4.将advisors封装到advisedSupport,委托ProxyFactory(AdvisedSupport)生成代理

ProxyFactory委托AopProxyFactory(InvocationHandler)生成代理





<aop:aspectj-autoproxy /> - AopNamespaceHandler

该配置就是定义了一个AnnotationAwareAspectJAutoProxyCreator(BeanPostProcessor)的bean







<aop:config/> - AopNamespaceHandler

spring中的该配置实际上就是注册了几个beanDefinition

AspectJAwareAdvisorAutoProxyCreator -BeanPostProcessor

AspectJExpressionPointcut - Pointcut

DefaultBeanFactoryPointcutAdvisor - Advisor




讨论:
这里注册的几个BeanPostProcessor都继承了AbastractAutoProxyCreator。AbastractAutoProxyCreator采用了模板方法设计模式,在模板方法中定义了生成代理的一系列步骤,由子类实现查找匹配的Advisor的过程


采用AopUtils查找合适的Advisor
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz){
...
}



PointCut接口设计:
public interface Pointcut {

	/**
	 * Return the ClassFilter for this pointcut.
	 * @return the ClassFilter (never {@code null})
	 */
	ClassFilter getClassFilter();

	/**
	 * Return the MethodMatcher for this pointcut.
	 * @return the MethodMatcher (never {@code null})
	 */
	MethodMatcher getMethodMatcher();


	/**
	 * Canonical Pointcut instance that always matches.
	 */
	Pointcut TRUE = TruePointcut.INSTANCE;

}