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<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 进入这个方法
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 进入这个方法
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> 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;
}