Spring事務(wù)實(shí)現(xiàn)原理

代理對象在哪里創(chuàng)建

先從bean被創(chuàng)建后如何產(chǎn)生代理對象開始奉件,在AbstractAutowireCapableBeanFactory.doCreateBean 初始化bean創(chuàng)建后慕嚷,并且將依賴注入到bean中,在調(diào)用initializeBean 方法對剛剛完成依賴注入bean進(jìn)行一次"初始化"

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
        }
        if (mbd == null || !mbd.isSynthetic()) {
            //就是在這里對符合條件bean 轉(zhuǎn)換成 代理對象  對象 -> AnnotationAwareAspectJAutoProxyCreator
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

AbstractAutoProxyCreator.postProcessAfterInitialization

    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            //判斷Class FactoryBean 實(shí)現(xiàn)類共虑,修改bean名字 在beanName前面加上&
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                return wrapIfNecessary(bean, beanName, cacheKey); //這里將會返回代理后的對象
            }
        }
        return bean;
    }

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        //targetSourcedBeans 沒有生成代理bean 緩存
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        //advisedBeans 也是緩存,返回false 則不會生成代理對象
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        //ORIGINAL 后置表明bean 實(shí)例不會變,則不會生成代理對象
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.
        //這里會返回 BeanFactoryTransactionAttributeSourceAdvisor,如果不創(chuàng)建代理對象秩冈,這里就會返回空數(shù)組
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE); //緩存已經(jīng)解析過bean封字,后面就不用再解析一次class
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    protected Object[] getAdvicesAndAdvisorsForBean(
            Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
        //使用Advisor 去處理class 是否需要生成代理對象昭齐,如果需要則返回 advisors 不為空
        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }


    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        //從容器中獲取內(nèi)置Advisor 使用一個Advisor 生成Advisor 通過代理工廠生成一堆代理對象
        //這里會返回 BeanFactoryTransactionAttributeSourceAdvisor
        List<Advisor> candidateAdvisors = findCandidateAdvisors();

        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

上面判斷主要做一些檢查弹砚,當(dāng)所有狀態(tài)合法后才會進(jìn)入getAdvicesAndAdvisorsForBean返回通過指定bean生成的通知废膘,在通過Advisor數(shù)組生成代理對象醋旦。這個方法主要邏輯就是通過

BeanFactoryTransactionAttributeSourceAdvisor 工廠內(nèi)置Advisor解析Class并且生成pointcut 切點(diǎn)扒接。主要實(shí)現(xiàn)在AopUtils

    /**
    * candidateAdvisors 內(nèi)置Advisor 也就是BeanFactoryTransactionAttributeSourceAdvisor
    *  給定Class 找尋可用Advisor
    */
    public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
        if (candidateAdvisors.isEmpty()) {
            return candidateAdvisors;
        }
        List<Advisor> eligibleAdvisors = new ArrayList<>();
        // IntroductionAdvisor只能應(yīng)用于類級別 事務(wù)一般定位到Method上吹菱,不會使用這種類型Advisor
        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;
            }
                        // 這里會使用candidate 去解析Class 如果需要生成代理方法或者代理對象 將會返回true
            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
            PointcutAdvisor pca = (PointcutAdvisor) advisor;
            return canApply(pca.getPointcut(), targetClass, hasIntroductions);
        }
        else {
            // It doesn't have a pointcut so we assume it applies.
            return true;
        }
    }
        //pointcut 為 TransactionAttributeSourcePointcut 內(nèi)部類
    public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
        Assert.notNull(pc, "Pointcut must not be null");
        if (!pc.getClassFilter().matches(targetClass)) {
            return false;
        }
                //方法匹配器附迷,用于解析Method 是否需要生成代理方法
        MethodMatcher methodMatcher = pc.getMethodMatcher();
        if (methodMatcher == MethodMatcher.TRUE) { //沒有任何邏輯惧互,沒有方法都會生成代理方法
            // No need to iterate the methods if we're matching any method anyway...
            return true;
        }

        IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
            introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
        }

        Set<Class<?>> classes = new LinkedHashSet<>();
        if (!Proxy.isProxyClass(targetClass)) { //向上獲取父類class,排除掉代理class
            classes.add(ClassUtils.getUserClass(targetClass));
        }
        classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

        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)) { //最終調(diào)用方法匹配器找到適合方法
                    return true;
                }
            }
        }

        return false;
    }

本質(zhì)依然是使用BeanFactoryTransactionAttributeSourceAdvisor 內(nèi)部對象來匹配Class 或Method喇伯,并且生成Advisor喊儡。
主要流程使用BeanFactoryTransactionAttributeSourceAdvisor.Pointcut(TransactionAttributeSourcePointcut 抽象類) -> TransactionAttributeSourcePointcut.matches ->AbstractFallbackTransactionAttributeSource.getTransactionAttribute
-> AnnotationTransactionAttributeSource.findTransactionAttribute ->AnnotationTransactionAttributeSource.determineTransactionAttribute -> TransactionAnnotationParser.TransactionAttribute

其中在AnnotationTransactionAttributeSource.determineTransactionAttribute 方法會使用Spring 支持TransactionAnnotationParser 數(shù)組去解析method并且返回TransactionAttribute
TransactionAnnotationParser是Spring 事務(wù)注解解析器接口在Class、Method 上解析注解并且將聲明注解解析成TransactionAttribute 支持3種實(shí)現(xiàn)

  • SpringTransactionAnnotationParser Spring自身數(shù)據(jù)庫事務(wù) 解析@Transactional
  • Ejb3TransactionAnnotationParser EJB事務(wù) 解析 javax.ejb.TransactionAttribute
  • JtaTransactionAnnotationParser JTA1.2 事務(wù) 解析javax.transaction.Transactional

我們一起看下如何生成代理對象的createProxy

    protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
            @Nullable Object[] specificInterceptors, TargetSource targetSource) {

        if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
            AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
        }

        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);

        if (!proxyFactory.isProxyTargetClass()) { // 如果還沒有設(shè)置代理目標(biāo)類這里在設(shè)置一次
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        //這里返回Advisor 所以仍然是返回BeanFactoryTransactionAttributeSourceAdvisor
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);

        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }

        // Use original ClassLoader if bean class not locally loaded in overriding class loader
        ClassLoader classLoader = getProxyClassLoader();
        if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
            classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
        }
        // 這里有兩個邏輯稻据,一根據(jù)需求創(chuàng)建AopProxy 二 調(diào)用getProxy 創(chuàng)建代理對象
        return proxyFactory.getProxy(classLoader);
    }

調(diào)用AopProxy創(chuàng)建代理目標(biāo)類艾猜,根據(jù)不同情況初始化不同AopProxy

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        // GraalVM Native Image 只支持 Dynamic proxy (java.lang.reflect.Proxy)
        if (!NativeDetector.inNativeImage() &&
                (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

    /**
     * Determine whether the supplied {@link AdvisedSupport} has only the
     * {@link org.springframework.aop.SpringProxy} interface specified
     * (or no proxy interfaces specified at all).
     */
    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class<?>[] ifcs = config.getProxiedInterfaces();
        return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
    }
}

其中JdkDynamicAopProxy 是通過InvocationHandler 接口實(shí)現(xiàn),ObjenesisCglibAopProxy就是通過Cglib實(shí)現(xiàn)捻悯,這次只有看下Cglib如何創(chuàng)建動態(tài)對象的

    public Object getProxy(@Nullable ClassLoader classLoader) {

        try {
            Class<?> rootClass = this.advised.getTargetClass();
            Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

            Class<?> proxySuperClass = rootClass;
            if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                for (Class<?> additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }

            // Validate the class, writing log messages as necessary.
            validateClassIfNecessary(proxySuperClass, classLoader);

            // Configure CGLIB Enhancer...
            //Cglib 核心就是通過Enhancer 對象去創(chuàng)建代理
            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (classLoader instanceof SmartClassLoader &&
                        ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                    enhancer.setUseCache(false);
                }
            }
            enhancer.setSuperclass(proxySuperClass);
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
            //這里將Spring 內(nèi)置7MethodInterceptor 實(shí)現(xiàn)
            Callback[] callbacks = getCallbacks(rootClass);
            Class<?>[] types = new Class<?>[callbacks.length];
            for (int x = 0; x < types.length; x++) {
                types[x] = callbacks[x].getClass();
            }
            // fixedInterceptorMap only populated at this point, after getCallbacks call above
            enhancer.setCallbackFilter(new ProxyCallbackFilter(
                    this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
            enhancer.setCallbackTypes(types);

            // Generate the proxy class and create a proxy instance.
            return createProxyClassAndInstance(enhancer, callbacks);
        }

    }

Cglib樣例

編寫一個簡單Demo類匆赃,對方法進(jìn)行前后增強(qiáng)。

public class Demo {

    public void  call(){
        System.out.println("我就是目標(biāo)類原始方法");
    }
}

編寫攔截器

public class CglibMethodInterceptor implements MethodInterceptor {

        /**
         * 通過在intercept 上重寫方法達(dá)到通知增強(qiáng)邏輯
         * @param o 代表Cglib 生成的動態(tài)代理類 對象本身
         * @param method 代理類中被攔截的接口方法 Method 實(shí)例
         * @param objects 接口方法參數(shù)
         * @param methodProxy 用于調(diào)用父類真正的業(yè)務(wù)類方法今缚∷懔可以直接調(diào)用被代理類接口方法 原始方法
         * @return
         * @throws Throwable
         */
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("invoke before....");
            MonitorUtil.start();
            Object invoke = methodProxy.invokeSuper(o, objects);
            //Object invoke = method.invoke(o,objects); 這樣會導(dǎo)致棧溢出
            System.out.println("invoken after");
            MonitorUtil.finish();
            return invoke;
        }
    }

最后創(chuàng)建代理對象

    @Test
    public void cglibTest(){
        Enhancer enhancer = new Enhancer();
        enhancer.setClassLoader(this.getClass().getClassLoader());
        enhancer.setSuperclass(Demo.class);
        enhancer.setCallback(new CglibMethodInterceptor());
        Demo proxyInst = (Demo) enhancer.create();
        proxyInst.call();
    }

執(zhí)行結(jié)果

invoke before....
我就是目標(biāo)類原始方法
invoken after

其實(shí)跟JDK動態(tài)代理寫法差不多,都是通過在原始方法前后插入代碼荚斯,達(dá)到增強(qiáng)埠居。CGLIB支持多個MethodInterceptor,組成一個攔截器鏈事期,按照一定順序執(zhí)行intercept滥壕。這種方法有利于AOP結(jié)構(gòu)和代理業(yè)務(wù)代碼解耦。

事務(wù)如何通過代理來實(shí)現(xiàn)的

通過上面一個小例子兽泣,我們已經(jīng)了解到實(shí)現(xiàn)代理邏輯核心就是getCallbacks(rootClass) 返回攔截器绎橘,內(nèi)置攔截器有7種,事務(wù)實(shí)現(xiàn)類就是在CglibAopProxy.DynamicAdvisedInterceptor唠倦。

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

        private final AdvisedSupport advised;

        public DynamicAdvisedInterceptor(AdvisedSupport advised) {
            this.advised = advised;
        }

        @Override
        @Nullable
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            Object oldProxy = null;
            boolean setProxyContext = false;
            Object target = null;
            TargetSource targetSource = this.advised.getTargetSource();
            try {
                if (this.advised.exposeProxy) {
                    // Make invocation available if necessary.
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }
                // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
                target = targetSource.getTarget();
                Class<?> targetClass = (target != null ? target.getClass() : null);
                //這里會返回TransactionInterceptor 事務(wù)執(zhí)行核心類
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                Object retVal;
                // Check whether we only have one InvokerInterceptor: that is,
                // no real advice, but just reflective invocation of the target.
                if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { //沒有代理攔截器
                    // We can skip creating a MethodInvocation: just invoke the target directly.
                    // Note that the final invoker must be an InvokerInterceptor, so we know
                    // it does nothing but a reflective operation on the target, and no hot
                    // swapping or fancy proxying.
                    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                    retVal = methodProxy.invoke(target, argsToUse);
                }
                else {
                    // We need to create a method invocation...  在這里執(zhí)行事務(wù)
                    retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
                }
                retVal = processReturnType(proxy, target, method, retVal); //包裝返回類型
                return retVal;
            }
            finally {
                if (target != null && !targetSource.isStatic()) {
                    targetSource.releaseTarget(target);
                }
                if (setProxyContext) {
                    // Restore old proxy.
                    AopContext.setCurrentProxy(oldProxy);
                }
            }
        }

這個內(nèi)部類主要就是兩個核心方法getInterceptorsAndDynamicInterceptionAdvice称鳞,從BeanFactoryTransactionAttributeSourceAdvisor.pointcut 返回MethodInterceptor 實(shí)現(xiàn)類TransactionInterceptor 并且使用InterceptorAndDynamicMethodMatcher 將返回MethodInterceptor、MethodMatcher 包裝起來稠鼻,下面會使用到的冈止。
將攔截器執(zhí)行鏈作為構(gòu)造器參數(shù)初始化CglibMethodInvocation,調(diào)用proceed 執(zhí)行事務(wù)候齿,proceed 會調(diào)用父類ReflectiveMethodInvocation.proceed熙暴,核心邏輯就在里面了闺属。

    public Object proceed() throws Throwable {
        // We start with an index of -1 and increment early.
        // currentInterceptorIndex 默認(rèn)是-1 相等表示攔截器鏈里面沒有代理方法,直接執(zhí)行原方法
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }
        //從第一個開始執(zhí)行
        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // Evaluate dynamic method matcher here: static part will already have
            // been evaluated and found to match.
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
            //dm 就是上面寫到TransactionAnnotationParser
            if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                return dm.interceptor.invoke(this); //調(diào)用TransactionInterceptor.invoke
            }
            else {
                // Dynamic matching failed.
                // Skip this interceptor and invoke the next in the chain.
                return proceed();
            }
        }
        else {
            // It's an interceptor, so we just invoke it: The pointcut will have
            // been evaluated statically before this object was constructed.
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

這里使用遞歸方式執(zhí)行調(diào)用鏈
TransactionInterceptor 可以說是Spring事務(wù)執(zhí)行器了周霉,它負(fù)責(zé)執(zhí)行事務(wù)掂器,它自己本身沒有任務(wù)事務(wù)實(shí)現(xiàn)代碼,都是通TransactionManager 事務(wù)管理器來實(shí)現(xiàn)事務(wù)開始俱箱、回滾国瓮、提交。
直接從TransactionInterceptor.invoke 開始分析

    public Object invoke(MethodInvocation invocation) throws Throwable {
        // Work out the target class: may be {@code null}.
        // The TransactionAttributeSource should be passed the target class
        // as well as the method, which may be from an interface.
        Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

        // Adapt to TransactionAspectSupport's invokeWithinTransaction...
        //這里調(diào)用父類TransactionAspectSupport.invokeWithinTransaction
        return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
            @Override
            @Nullable
            public Object proceedWithInvocation() throws Throwable {
                return invocation.proceed();
            }
            @Override
            public Object getTarget() {
                return invocation.getThis();
            }
            @Override
            public Object[] getArguments() {
                return invocation.getArguments();
            }
        });
    }

invokeWithinTransaction 看方法嗎方法命名就知道干什么的狞谱,執(zhí)行事務(wù)方法乃摹。三個參數(shù)
Method 要執(zhí)行方法,主要是獲取事務(wù)注解上屬性
Class 被代理Class芋簿,作業(yè)跟Method差不多
InvocationCallback 被實(shí)現(xiàn)的class峡懈,主要用于執(zhí)行代理方法。要知道Spring AOP是代理chain 方式執(zhí)行与斤,一個類不單止是被事務(wù)代理的肪康,還有會因?yàn)槠渌麡I(yè)務(wù)被代理了,保證代理鏈能全部執(zhí)行下去撩穿。

protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
            final InvocationCallback invocation) throws Throwable {

        // If the transaction attribute is null, the method is non-transactional.
        TransactionAttributeSource tas = getTransactionAttributeSource();
        //TransactionAttribute 是執(zhí)行事務(wù)必須實(shí)體 包含很多重要信息 事務(wù)隔離級別磷支、事務(wù)傳播級別、異呈彻眩回滾等
        final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
        //獲取TransactionManager 事務(wù)管理器雾狈,再平常開發(fā)中可以存在自己配置事務(wù)管理器情況,先讀取@Transactional value 屬性抵皱,
        //沒有從transactionManagerBeanName 可以從配置文件指定
        //最后就是Spring默認(rèn)事務(wù)實(shí)現(xiàn)
        final TransactionManager tm = determineTransactionManager(txAttr);

        if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
            //這里是反應(yīng)式事務(wù) Mongdb NOSQL使用善榛,這里略過
        }

        PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
        final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
        
        // CallbackPreferringPlatformTransactionManager 是 PlatformTransactionManager  擴(kuò)展接口提供在執(zhí)行事務(wù)時暴露一個回調(diào)方法
        if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
            // Standard transaction demarcation with getTransaction and commit/rollback calls.
            // 獲取正在執(zhí)行的事務(wù)狀態(tài)或者創(chuàng)建一個事務(wù) TransactionInfo 事務(wù)狀態(tài) 會記錄事務(wù)執(zhí)行,用于回滾
            TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

            Object retVal;
            try {
                // This is an around advice: Invoke the next interceptor in the chain.
                // This will normally result in a target object being invoked.
                // invocation 就是被實(shí)現(xiàn)類呻畸,調(diào)用原始方法或者代理方法
                // 其實(shí)這里就是around advice 環(huán)繞通知 前面開啟事務(wù)移盆,下面方法負(fù)責(zé)回滾或提交
                retVal = invocation.proceedWithInvocation();
            }
            catch (Throwable ex) {
                // target invocation exception
                //處理業(yè)務(wù)異常,如果異常符合回滾伤为,就會回滾否則就是commit
                completeTransactionAfterThrowing(txInfo, ex);
                throw ex;
            }
            finally {
                 // 在ThreadLocal 清除事務(wù)狀態(tài)txInfo
                 //要知道所有事務(wù)都通過ThreadLocal 進(jìn)行傳遞
                 //在正持溲或者異常情況下,清除線程綁定事務(wù)
                cleanupTransactionInfo(txInfo);
            }

            //處理下返回值绞愚,使用了io.vavr.control.Try 來處理叙甸,沒用過 略過下面
            if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
                // Set rollback-only in case of Vavr failure matching our rollback rules...
                TransactionStatus status = txInfo.getTransactionStatus();
                if (status != null && txAttr != null) {
                    retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
                }
            }

            //這個說的很明白 處理完返回值后再進(jìn)行提交事務(wù)
            commitTransactionAfterReturning(txInfo);
            return retVal;
        }

        else { //這個是CallbackPreferringPlatformTransactionManager 執(zhí)行事務(wù)方式
               //跟上面處理差不多就是多了一個execute 方法,在回調(diào)函數(shù)去執(zhí)行事務(wù)位衩,相當(dāng)于將事務(wù)執(zhí)行交給調(diào)用者去實(shí)現(xiàn)
            Object result;
            final ThrowableHolder throwableHolder = new ThrowableHolder();

            // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
            try {
                result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
                    TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
                    try {
                        Object retVal = invocation.proceedWithInvocation();
                        if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
                            // Set rollback-only in case of Vavr failure matching our rollback rules...
                            retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
                        }
                        return retVal;
                    }
                    catch (Throwable ex) {
                        if (txAttr.rollbackOn(ex)) {
                            // A RuntimeException: will lead to a rollback.
                            if (ex instanceof RuntimeException) {
                                throw (RuntimeException) ex;
                            }
                            else {
                                throw new ThrowableHolderException(ex);
                            }
                        }
                        else {
                            // A normal return value: will lead to a commit.
                            throwableHolder.throwable = ex;
                            return null;
                        }
                    }
                    finally {
                        cleanupTransactionInfo(txInfo);
                    }
                });
            }
            catch (ThrowableHolderException ex) {
                throw ex.getCause();
            }
            catch (TransactionSystemException ex2) {
                if (throwableHolder.throwable != null) {
                    logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                    ex2.initApplicationException(throwableHolder.throwable);
                }
                throw ex2;
            }
            catch (Throwable ex2) {
                if (throwableHolder.throwable != null) {
                    logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                }
                throw ex2;
            }

            // Check result state: It might indicate a Throwable to rethrow.
            if (throwableHolder.throwable != null) {
                throw throwableHolder.throwable;
            }
            return result;
        }
    }

總結(jié)

image.png

在這篇文章中我們簡單學(xué)習(xí)了Spring初始化bean時裆蒸,如何將bean創(chuàng)建成一個代理對象,并且使用Cglib技術(shù)創(chuàng)建一個代理bean糖驴,在結(jié)合事務(wù)管理器分析了代理如何去實(shí)現(xiàn)Spring事務(wù)的光戈。使用一個小例子演示了Cglib代理如何實(shí)現(xiàn)的哪痰,方便理解Spring AOP代理是通過一個攔截器去實(shí)現(xiàn)的遂赠,一個對象的多個代理封裝到調(diào)用鏈里面久妆,執(zhí)行方法時順序執(zhí)行,保證每一個代理與代理之間沒有任何聯(lián)系跷睦,相互獨(dú)立筷弦。這次我還了解了Spring代理機(jī)制原理,通過Advisor實(shí)現(xiàn)類去解析Class抑诸、Method烂琴,通過PointcutAdvisor(匹配Class、Method)蜕乡、IntroductionAdvisor (支持Class)是否需要生成代理對象奸绷。然后在通過專門代理工程去生成對應(yīng)代理對象。
我們簡單了解事務(wù)實(shí)現(xiàn)层玲,其實(shí)就是環(huán)繞通知實(shí)現(xiàn)而已号醉,還了解到事務(wù)狀態(tài)傳遞是通過ThreadLocal來實(shí)現(xiàn)的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末辛块,一起剝皮案震驚了整個濱河市畔派,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌润绵,老刑警劉巖线椰,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異尘盼,居然都是意外死亡憨愉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門卿捎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來配紫,“玉大人,你說我怎么就攤上這事娇澎”恳希” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵趟庄,是天一觀的道長括细。 經(jīng)常有香客問我,道長戚啥,這世上最難降的妖魔是什么奋单? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮猫十,結(jié)果婚禮上览濒,老公的妹妹穿的比我還像新娘呆盖。我一直安慰自己,他們只是感情好贷笛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布应又。 她就那樣靜靜地躺著,像睡著了一般乏苦。 火紅的嫁衣襯著肌膚如雪株扛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天汇荐,我揣著相機(jī)與錄音洞就,去河邊找鬼。 笑死掀淘,一個胖子當(dāng)著我的面吹牛旬蟋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播革娄,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼倾贰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了稠腊?” 一聲冷哼從身側(cè)響起躁染,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎架忌,沒想到半個月后吞彤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡叹放,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年饰恕,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片井仰。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡埋嵌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出俱恶,到底是詐尸還是另有隱情雹嗦,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布合是,位于F島的核電站了罪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏聪全。R本人自食惡果不足惜泊藕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望难礼。 院中可真熱鬧娃圆,春花似錦玫锋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吝岭,卻和暖如春三痰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背窜管。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留稚机,地道東北人幕帆。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像赖条,于是被迫代替她去往敵國和親失乾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容