我们先说假如该方法是public,研究一下其中的细节

@Service
public class TestServiceImpl {
    @Transactional(rollbackFor = Exception.class)
    public void trans1(){}
}

image.png
image.png

AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(),其中applyBeanPostProcessorsAfterInitialization()继承自AbstractAutoProxyCreator,下面是方法细节

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

        Object result = existingBean;
        //getBeanPostProcessors()是sptring boot启动时系统配置的BeanPostProcessor;其中有一个BeanPostProcessor叫做AnnotationAwareAspectJAutoProxyCreator;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            //当遍历AnnotationAwareAspectJAutoProxyCreator时,执行其postProcessAfterInitialization()
            Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

以下是AbstractAutoProxyCreator.postProcessAfterInitialization()细节:

    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                //这个方法的重要逻辑是,根据beanName获取通知列表,如果列表不为空,创建代理类;
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

image.png图2
image.png图3

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        //获取bean和beanName获取通知列表.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        //本示例中testServiceImpl的specificInterceptors如图2所示;
        //如果通知列表不为空,则创建代理类
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //执行具体创建代理逻辑,本示例中testServiceImpl的specificInterceptors如图3所示
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            //直接返回
            return proxy;
        }
        //如果没有匹配的通知列表,返回普通的bean
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;

}

如果我们测试用例中的 public 去掉呢?,我们直接贴出结果:
image.png图4
可以看到 specificInterceptors = null,也就是说并没有为其生成代理类。什么原因呢?我们继续往下看:

    //candidateAdvisors来自spring boot启动是配置的通知列表
    protected List<Advisor> findAdvisorsThatCanApply(
            List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

        ProxyCreationContext.setCurrentProxiedBeanName(beanName);
        try {
            //由AopUtils.findAdvisorsThatCanApply()执行具体的匹配逻辑
            return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
        }
        finally {
            ProxyCreationContext.setCurrentProxiedBeanName(null);
        }
    }

我们可以看到候选的通知列表有24个
image.png图5

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
    IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
            introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
        }

        Set<Class<?>> classes = new LinkedHashSet<>();
        if (!Proxy.isProxyClass(targetClass)) {
            classes.add(ClassUtils.getUserClass(targetClass));
        }
        classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

        for (Class<?> clazz : classes) {
            Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
            for (Method method : methods) {
                //因为introductionAwareMethodMatcher == null,所以methodMatcher.matches实际执行我们的候选通知器match方法;
                if (introductionAwareMethodMatcher != null ?
                        introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                        methodMatcher.matches(method, targetClass)) {
                    return true;
                }
            }
        }

        return false;
}

image.png图6
以TransactionAttributeSourcePointcut.matches()为例:
image.png图7

public boolean matches(Method method, @Nullable Class<?> targetClass) {
        if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
            return false;
        }
        //图7为tas实例
        TransactionAttributeSource tas = getTransactionAttributeSource();
        return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
    }
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
    // We need to work it out.
    TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
        return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

tas.getTransactionAttribute()会调用AbstractFallbackTransactionAttributeSource.computeTransactionAttribute():

protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
        // Don't allow no-public methods as required.
        //通过上面这个注释看出不允许非public,因此返回 null;
        if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
            return null;
        }
}

此时上面的matches()返回false,最终AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass)返回空列表,这样一来AbstractAutoProxyCreator.wrapIfNecessary()中的 specificInterceptors 变量为null,也就没有办法创建代理类了!

最后,再抛出一个问题,假如一个service @Transactional方法既有 public,又有 no-pubic 会怎样呢?欢迎一起探讨~~~


子瞻
1 声望9 粉丝