首页 > 其他分享 >SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?

时间:2023-08-21 17:36:29浏览次数:40  
标签:调用 SpringBoot service 55 代码 代理 如下 bean 方法


SpringBoot run方法代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring


可以看到它会调用refreshContext方法来刷新Spring容器,这个refreshContext方法最终会调用AbstractApplicationContext的refresh方法,代码如下

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring_02


SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring boot_03


如上图,refresh方法最终会调用finisheBeanFactoryInitialization方法,代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_静态方法_04


SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring boot_05


从上图可以看出,它最终会调用preInstantiateSingletons方法来实例化单例的bean,代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_实例化_06


SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring boot_07


其中,每一个bean创建时都要调用getBean方法,getBean代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring boot_08


如上图,getBean调用doGetBean, doGetBean代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring_09


SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring_10


SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring boot_11


SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_实例化_12


整体逻辑就是先从缓存中获取bean,如果为空则调用createBean来创建bean,createBean代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_静态方法_13


SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring boot_14


从上图看到,createBean调用了doCreateBean来完成bean创建,doCreateBean代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_静态方法_15


SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_静态方法_16


从上图可以看到doCreateBean调用了initializeBean来完成对bean的初始化,initializeBean代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring_17


从上图可以看到它调用了applyBeanPostProcessorsAfterInitialization,这个方法代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring_18


可以看到,applyBeanPostProcessorsAfterInitialization中获取了Spring容器中所有的BeanPostProcessor,然后调用它们的postProcessAfterInitialization方法来对bean进行后置处理,而可能的代理对象就是通过BeanPostProcessor生成的。而InfrastructureAdvisorAutoProxyCreator这个BeanPostProcessor就是来完成代理对象生成的(当然,前提是加了@Transactional注解,否则不会生成代理对象,会直接返回原始对象)

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring boot_19


InfrastructureAdvisorAutoProxyCreator的postProcessAfterInitialization代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_静态方法_20


其中调用了wrapIfNecessary方法,wrapIfNecessary代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_实例化_21


从上图我们看到,如果specificInterceptors不为空,则会去生成代理对象并返回,否则直接将原始对象返回。getAdvicesAndAdvisorsForBean代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_java_22


它调用了findEligibleAdvisors方法,代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_静态方法_23


findEligibleAdvisors首先从Spring容器中获取所有的Advisor,然后调用findAdvisorsThatCanApply来获取可以应用的Advisor,findAdvisorsThatCanApply代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring boot_24


它调用了AopUtils的静态方法findAdvisorsThatCanApply方法,代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring_25


其中调用的canApply方法代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_java_26


其中调用的canApply代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_静态方法_27


SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring_28


其中调用的matches方法代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring_29


其中调用的getTransactionAttribute方法代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_静态方法_30


SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_静态方法_31


其中调用的computeTrasactionAttribute代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_静态方法_32


SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_实例化_33


其中调用的findTransactionAttribute代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring boot_34


其中调用的determineTransactionAttribute代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_实例化_35


其中会分别调用Spring容器中的TransactionAttributeParser进行注解分析,实际上只有一个SpringTransactionAttributeParser,SpringTransactionAttributeParser的parseTransactionAnnotation代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_实例化_36


从上图可以看到,要从传入的元素(实际就是我们定义的业务方法)来获取它是否包含@Transactional注解,如果包含,则调用parseTransactionAnnotation来获取注解上配置的事务相关的属性(也就是在@Transactional注解上配置的那些值)

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring boot_37


因此,最终决定是否生成代理对象的是parseTransactionAnnotation方法的返回值

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_实例化_38


一步一步往回返,最终返回到AbstractAutoProxyCreator的wrapIfNecessary方法:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_实例化_39


如果parseTransactionAnnotation方法返回的是null,则这里的specificInterceptors为空,不会生成代理对象。

如果parseTransactionAnnotation方法返回的不是null,则这里的specificInterceptors大小为1,则会调用createProxy创建代理对象。以上分析了是否要创建代理对象,开始分析代理对象的创建过程。createProxy代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring boot_40


SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring boot_41


可以看到,首先new出一个Proxy,然后设置targetSource(也就是bean的原始类型)和用于事务处理的Advisor,最有调用getProxy,getProxy代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_实例化_42


其中调用的createAopProxy代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_spring_43


其中调用的createAopProxy代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_java_44


默认情况下,SpringBoot会使用ObjenesisCglibAopProxy,如上图。ObjenesisCglibAopProxy的getProxy代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_java_45


SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_实例化_46


可以看到它最终会调用createProxyClassAndInstance方法来创建出代理对象,它的代码如下:

SpringBoot复习:(55)在service类中的方法上加上@Transactional注解后,Spring底层是怎么生成代理对象的?_静态方法_47


标签:调用,SpringBoot,service,55,代码,代理,如下,bean,方法
From: https://blog.51cto.com/amadeusliu/7177762

相关文章