您的位置:首页 > 编程语言 > Java开发

Spring事物(二)----基于注解源码分析之1

2018-12-04 11:51 302 查看

源码解析流程

源码从哪里看起?当然是配置文件作为入口。
打开xml的配置,找到如下片段,就是这么简单的配置,怎么看呢。

链接annotataion-driven标签,发现跳转到jar包的xsd文件了,既然是标签,按惯性思维,应该是要解析标签。打开后的目录结构,哪个是我们需要的呢,不熟悉spring的标签解析请自行度娘。 打开spring.handlers文件,TxNamespaceHandler这个就是解析tx标签的类。


TxNamespaceHandler类,AnnotationDrivenBeanDefinitionParser就是标签的解析器,看AnnotationDrivenBeanDefinitionParser的parse解析方法,由于我们没有指定mode的模式,默认为proxy模式

打开AopAutoProxyConfigurer的configureAutoProxyCreator方法,注入了三个bean实例。

AnnotationTransactionAttributeSource(注解事物的属性类)
TransactionInterceptor(对代理方法进行拦截的处理类)
BeanFactoryTransactionAttributeSourceAdvisor(匹配是否对目标类进行切面)
这三个bean是事物的灵魂。整个事物就靠这三个类完成。那怎么把事物织入到bean中呢?

接下来我们看第一个红色框架方法,这里主要registerAutoProxyCreatorIfNecessary方法

注册了InfrastructureAdvisorAutoProxyCreator类。这个类干啥用呢?我们看看这个类的继承图,是不是看到了熟悉的beanPostProcessor接口

很多同志不明白就算你实现了beanPostProcessor接口又咋样?下面我用一张图来普及下bean的实例化过程;

看到红色描述没?bean在实例化后调用了实现beanPostProcessor接口的实例中postProcessAfterInitialization方法来对bean进行加强。前面我们提到的InfrastructureAdvisorAutoProxyCreator类正好实现了beanPostProcessor接口。那么在bean实例化完成后,通过实现beanPostProcessor接口的postProcessAfterInitialization方法就可以对bean进行事物加强了。我们发现InfrastructureAdvisorAutoProxyCreator并没有实现这个方法。咋回事呢。别急。这不是还实现了很多父类吗。我们父类找找。功夫不负有心人。在AbstractAutoProxyCreator这个父类我们发现了postProcessAfterInitialization的实现

接下来,我们看下wrapIfNecessary干了些什么事情?
1、如果处理过了,就不需要再处理了
2、如果需要处理的类是通知基础类,不需要再处理
3、获取匹配当前bean的增强器
4、如果bean增强器不为空,生成bean增强的代理类,返回代理类
5、如果bean增强器为空,直接返回目标bean

接下来继续看看怎么获取bean的增强器:
1.首先调用findEligibleAdvisors方法获取bean的增强器
2.findCandidateAdvisors方法获取所有注册的增强器的实例
3.findAdvisorsThatCanApply方法返回匹配当前bean的可用增强器实例


下面来分析下findCandidateAdvisors方法,其中又调用了findAdvisorBeans方法。从方法我们看出,从容器中寻找实现Advisor接口的所有实例,并添加到集合返回


回到最开始说过的注册事物三个类,其中BeanFactoryTransactionAttributeSourceAdvisor的继承关系图,哇喔。好巧哦。那就意味着BeanFactoryTransactionAttributeSourceAdvisor也会当做增强器返回。

既然已经返回了所有容器中的advice增强器。那接下来要做的事情是筛选出匹配当前bean的增强器,我们分析findAdvisorsThatCanApply方法




筛选过程如下
1、调用findAdvisorsThatCanApply方法,传入所有的增强器和当前bean的实例,
2、处理过IntroductionAdvisor增强器后,接下来调用canApply方法处理PointcutAdvisor增强器
3、由BeanFactoryTransactionAttributeSourceAdvisor继承图可以看到是BeanFactoryTransactionAttributeSourceAdvisor继承了PointcutAdvisor增强器,那么继续调用canApply方法的第一个入参pca.getPointcut()调用的是BeanFactoryTransactionAttributeSourceAdvisor中的getPointcut()方法返回
TransactionAttributeSourcePointcut实例。
4、获取当前bean的所有方法,循环调用TransactionAttributeSourcePointcut的matches方法进行匹配

查看TransactionAttributeSourcePointcut的matches方法

getTransactionAttributeSource调用的是BeanFactoryTransactionAttributeSourceAdvisor的getTransactionAttributeSource方法,到这里有人开始懵逼了。这个TransactionAttributeSource从哪里注入进来的??这得从头说起。还记得解析标签的注册了三个bean吗?


原来如此!相信不用我解释了吧,getTransactionAttributeSource返回的就是AnnotationTransactionAttributeSource,那么tas.getTransactionAttribute(method, targetClass)方法调用就是AnnotationTransactionAttributeSource的方法或者是其父类的方法,果不其然,在父类AbstractFallbackTransactionAttributeSource找到了getTransactionAttribute的实现方法


查询事物的属性过程:
1。查看方法是否有属性注解
2。查看方法坐在的类上面是否有属性注解
3。查看方法所在的接口上的方法上面是否有属性注解
4。查看方法所在的接口上面是否有属性注解

接下看下findTransactionAttribute方法,最终调用的SpringTransactionAnnotationParser的parseTransactionAnnotation解析方法,先获取方法上的配置的@Transactional注解的属性,然后封装成RuleBasedTransactionAttribute实例






到此,筛选工作完成,如果有bean的可用的增强器,就返回增强器数组。
接下就是为bean生成织入增强器。并生成增强事物后的代理类

接下看下createProxy创建到代理类的过程:
1.将拦截器封装为增强器
2.生成代理类

先解析所有的拦截器。调用wrap方法将拦截器封装成增强器

代理类生成流程,先创建代理工厂,接着创建代理类,创建代理类有两种模式,第一种是动态代理。第二种是cglib代理模式,默认是第一种
optimize:用来控制通过CGLIB创建的代理是否使用激进的优化策略,不推荐使用这个设置,目前这个属性仅用于CGLIB代理,对于JDK动态代理无效。
proxyTargetClass:属性为true时,目标类本身被代理而不是目标类的接口。如果这个属性值被设为true,CGLIB代理将被创建。
hasNOUserSuppliedProxyInterfaces:是否存在代理接口。



假设现在createAopProxy返回的是JdkDynamicAopProxy代理类,我们看到是通过Proxy来生成代理类,并且JdkDynamicAopProxy实现了InvocationHandler接口,重写了invoke方法。这里不做过多的描述,不懂的话,先度娘补习。

此时,我们已经生成了bean实例不再是原来初始化的bean了。而且带有铠甲(事物)功能的bean了。到了这里,可能还是很多小白很懵逼,生成的代理bean有啥用呢?我怎么样调用才能调用我的代理类中的方法呢?

欲知后事如何,请听下回分解!!!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: