当前位置: 首页 > 后端技术 > Java

SpringBoot如果服务@Transactional的方法不是公共的会发生什么?(1)

时间:2023-04-01 16:28:11 Java

先说如果方法是public的,再研究细节@ServicepublicclassTestServiceImpl{@Transactional(rollbackFor=Exception.class)publicvoidtrans1(){}}AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(),其中applyBeanPostProcessorsAfterInitialization()继承自AbatorstractAutoProxy下是方法细节publicObjectapplyBeanPostProcessorsAfterInitialization(ObjectexistingBean,StringbeanName)throwsBeansException{Objectresult=existingBean;//getBeanPostProcessors()是sptringboot启动时系统配置的BeanPostProcessor;其中有一个BeanPostProcessor叫做AnnotationAwareAspectJAutoProxyCreator;for(BeanPostProcessorbeanProcessor:getBeanPostProcessors()){//WhentraversingAnnotationAwareAspectJAutoProxyCreator,executeitspostProcessAfterInitialization()Objectcurrent=beanProcessor.postProcessAfterInitialization(结果,豆名);if(current==null){返回结果;}结果=当前的;}返回结果;}以下是AbstractAutoProxyCreator.postProcessAfterInitialization()的详细信息:if(!this.earlyProxyReferences.contains(cacheKey)){//该方法的重要逻辑是根据beanName获取通知列表,如果列表不为空,则创建代理类;返回wrapIfNecessary(bean,beanName,cacheKey);}}返回豆;}图2图3protectedObjectwrapIfNecessary(Objectbean,StringbeanName,ObjectcacheKey){//获取bean和beanName获取通知列表。Object[]specificInterceptors=getAdvicesAndAdvisorsForBean(bean.getClass(),beanName,null);//本例中testServiceImpl的具体拦截器如图2所示;//如果通知列表不为空,创建代理类if(specificInterceptors!=DO_NOT_PROXY){this.advisedBeans.put(cacheKey,Boolean.TRUE);//执行具体的创建代理逻辑。本例中testServiceImpl的specificInterceptors如图3所示。this.proxyTypes.put(cacheKey,proxy.getClass());//直接returnreturnproxy;}//如果没有匹配的通知列表,返回一个普通beanthis.advisedBeans.put(cacheKey,Boolean.FALSE);returnbean;}如果我们在测试的情况下去掉public呢?,我们直接贴出结果:图4显示specificInterceptors=null,也就是说没有为其生成代理类。是什么原因?我们继续往下看://candidateAdvisors来自springboot启动配置通知列表try{//具体匹配逻辑由AopUtils.findAdvisorsThatCanApply()执行returnAopUtils.findAdvisorsThatCanApply(candidateAdvisors,beanClass);}最后{ProxyCreationContext.setCurrentProxiedBeanName(null);我们可以看到等待选择的通知列表有24个图5publicstaticbooleancanApply(Pointcutpc,ClasstargetClass,booleanhasIntroductions){IntroductionAwareMethodMatcherintroductionAwareMethodMatcher=null;如果(methodMatcherinstanceofIntroductionAwareMethodMatcher){introductionAwareMethodMatcher=(IntroductionAwareMethodMatcher)methodMatcher;}Set>classes=newLinkedHashSet<>();如果(!Proxy.isProxyClass(targetClass)){classes.add(ClassUtils.getUserClass(targetClass));}classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));对于(Classclazz:classes){Method[]methods=ReflectionUtils.getAllDeclaredMethods(clazz);for(Methodmethod:methods){//因为introductionAwareMethodMatcher==null,所以methodMatcher.matches实际上执行了我们的候选通知器match方法;如果(introductionAwareMethodMatcher!=null?introductionAwareMethodMatcher.matches(method,targetClass,hasIntroductions):methodMatcher.matches(method,targetClass)){returntrue;}}}返回假;}图6以TransactionAttributeSourcePointcut.matches()为例:图7publicbooleanmatches(Methodmethod,@NullableClasstargetClass){if(targetClass!=null&&TransactionalProxy.class.isAssignableFrom(targetClass)){returnfalse;}//图7显示tas实例TransactionAttributeSourcetas=getTransactionAttributeSource();返回(tas==null||tas.getTransactionAttribute(方法,targetClass)!=null);}publicTransactionAttributegetTransactionAttribute(Methodmethod,@NullableClasstargetClass){//我们需要解决它。事务属性utetxAttr=computeTransactionAttribute(method,targetClass);return(tas==null||tas.getTransactionAttribute(method,targetClass)!=null);}tas.getTransactionAttribute()将调用AbstractFallbackTransactionAttributeSource.computeTransactionAttribute():ProtectedTransactionCompactionAttribute方法,@NullableClasstargetClass){//Don'根据需要允许非公共方法。//通过上面的注释,我们可以看出,非public是不允许的,所以返回null;如果(allowPublicMethodsOnly()&&!Modifier.isPublic(method.getModifiers())){返回null;}}这时候上面的matches()返回false,最后AopUtils.findAdvisorsThatCanApply(candidateAdvisors,beanClass)返回一个空列表,所以AbstractAutoProxyCreator.wrapIfNecessary()中的specificInterceptors变量如果为null,就没有办法创建一个代理类!最后再提一个问题,如果一个服务的@Transactional方法同时有public和no-public怎么办?欢迎一起讨论~~~

猜你喜欢