栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring注解事务不支持 protect private 方法的原因

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring注解事务不支持 protect private 方法的原因

Spring注解事务不支持 protect private 方法的原因
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@Builder
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @Tolerate
    public User() {
    }

    @TableId(value = "id", type = IdType.ID_WORKER)
    private Long id;

    private String name;

    private String password;

    private Integer age;
}
@Service
public class UserServiceImpl2 {

    @Resource
    private UserMapper userMapper;

    @Transactional
    void saveUser(User user) {
        userMapper.insert(user);
        // 测试事务回滚
        if (!StringUtils.hasText(user.getName())) {
            throw new RuntimeException("username不能为空");
        }
    }
}
@SpringBootApplication
@MapperScan("com.example.mapper")
public class ThreadApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(ThreadApplication.class, args);
        UserServiceImpl2 userService = context.getBean(UserServiceImpl2.class);
        User user = User.builder().age(20).build();
        userService.saveUser(user);
    }
}

现在 userService.saveUser(user);这里打个断点,debug方式启动,可以看到取出来的userService不是代理类,所以事务肯定不会生效。

进入生成代理类的applyBeanPostProcessorsAfterInitialization方法,

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      // postProcessAfterInitialization会判断bean是否需要生成代理类
      Object current = processor.postProcessAfterInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}

AbstractAutoProxyCreator类重写了postProcessAfterInitialization方法

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}

为什么是AbstractAutoProxyCreator?看下@EnableAspectJAutoProxy注解,通@import导入AspectJAutoProxyRegistrar往IOC容器中注入了一个类型为AnnotationAwareAspectJAutoProxyCreator的bean。AnnotationAwareAspectJAutoProxyCreator的继承结构如图所示,它的父类为AbstractAutoProxyCreator并且重写了postProcessAfterInitialization方法

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
   boolean proxyTargetClass() default false;
   boolean exposeProxy() default false;
}
class AspectJAutoProxyRegistrar implements importBeanDefinitionRegistrar {
   @Override
   public void registerBeanDefinitions(
         Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry) {

      // 重点是这里
      AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
      ......
   }
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
   return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
      BeanDefinitionRegistry registry, @Nullable Object source) {

   return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
      Class cls, BeanDefinitionRegistry registry, @Nullable Object source) {

   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

   //判断容器中是否有该类型的Bean
   if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
      BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
      if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
         int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
         int requiredPriority = findPriorityForClass(cls);
         if (currentPriority < requiredPriority) {
            apcDefinition.setBeanClassName(cls.getName());
         }
      }
      return null;
   }

   // 在引入spring aop starter,aop自动装配时容器中并不存在这个类型的Bean
   // 所以通过 RootBeanDefinition注册一个
   RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
   beanDefinition.setSource(source);
   beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
   beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
   registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
   return beanDefinition;
}

回到wrapIfNecessary方法

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   ......
   // Create proxy if we have advice.
   // 获取该Bean对应的通知方法集合
   Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
   // 该Bean对应的通知方法集合为空,创建Bean的代理类
   if (specificInterceptors != DO_NOT_PROXY) {
      this.advisedBeans.put(cacheKey, Boolean.TRUE);
      // 创建Bean的代理类
      Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
   }
   // 该Bean对应的通知方法集合为空,Bean不需要代理
   this.advisedBeans.put(cacheKey, Boolean.FALSE);
   return bean;
}

所以重点在getAdvicesAndAdvisorsForBean方法返回了空数组,getAdvicesAndAdvisorsForBean方法内部主要包含以下这些逻辑:

获取所有的通知方法(切面里定义的各个方法);通过切点表达式判断这些通知方法是否可为当前Bean所用;如果有符合的通知方法,则对它们进行排序。

进入AbstractAdvisorAutoProxyCreator类的getAdvicesAndAdvisorsForBean方法。下面中间一大段都只是进入哪些方法看,不想看的直接看AbstractFallbackTransactionAttributeSource类的computeTransactionAttribute方法就好了

@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
      Class beanClass, String beanName, @Nullable TargetSource targetSource) {

   // 进入这个方法
   List advisors = findEligibleAdvisors(beanClass, beanName);
   if (advisors.isEmpty()) {
      return DO_NOT_PROXY;
   }
   return advisors.toArray();
}
protected List findEligibleAdvisors(Class beanClass, String beanName) {
   List candidateAdvisors = findCandidateAdvisors();
   // 进入这个方法
   List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
   extendAdvisors(eligibleAdvisors);
   if (!eligibleAdvisors.isEmpty()) {
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}
protected List findAdvisorsThatCanApply(
      List candidateAdvisors, Class beanClass, String beanName) {

   ProxyCreationContext.setCurrentProxiedBeanName(beanName);
   try {
      // 进入这个方法
      return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
   }
   finally {
      ProxyCreationContext.setCurrentProxiedBeanName(null);
   }
}
public static List findAdvisorsThatCanApply(List candidateAdvisors, Class clazz) {
   if (candidateAdvisors.isEmpty()) {
      return candidateAdvisors;
   }
   List eligibleAdvisors = new ArrayList<>();
   for (Advisor candidate : candidateAdvisors) {
      if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
         eligibleAdvisors.add(candidate);
      }
   }
   boolean hasIntroductions = !eligibleAdvisors.isEmpty();
   for (Advisor candidate : candidateAdvisors) {
      if (candidate instanceof IntroductionAdvisor) {
         // already processed
         continue;
      }
      // 进入这个方法
      if (canApply(candidate, clazz, hasIntroductions)) {
         eligibleAdvisors.add(candidate);
      }
   }
   return eligibleAdvisors;
}
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;
   }
}
public static boolean canApply(Pointcut pc, Class targetClass, boolean hasIntroductions) {
   .......
   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)) {
            // 进入methodMatcher.matches(method, targetClass),当方法修饰符不为public时,这里会返回false
            return true;
         }
      }
   }
   return false;
}

进入TransactionAttributeSourcePointcut类的matches方法

@Override
public boolean matches(Method method, Class targetClass) {
   TransactionAttributeSource tas = getTransactionAttributeSource();
   // 进入getTransactionAttribute方法
   return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

进入AbstractFallbackTransactionAttributeSource类的getTransactionAttribute方法

@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable 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);
      }
      ........
      return txAttr;
   }
}
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class targetClass) {
   // Don't allow non-public methods, as configured.
   // 如果方法修饰符不是public 返回null,好了到了这里就结束了
   if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
      return null;
   }
   .....
   return null;
}

`

@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class targetClass) {
   // Don't allow non-public methods, as configured.
   // 如果方法修饰符不是public 返回null,好了到了这里就结束了
   if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
      return null;
   }
   .....
   return null;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/770103.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号