关于proxy模式下,@Transactional标签在创建代理对象时的应用

本文详细介绍了Spring中的@Transactional标签在创建代理对象时的应用,包括Spring AOP的基础概念、BeanPostProcessor、Advisor、Interceptor、TransactionInterceptor等关键组件的工作原理,以及@Transactional注解的解析过程。通过分析源码,揭示了代理对象如何处理事务逻辑。
摘要由CSDN通过智能技术生成

@Transactional标签用于Spring中的事务标记。
先简单说下几个概念:
1)Spring的AOP是应用于Spring管理的bean上并基于代理实现的,代理的方法有java动态代理和CGLib动态代理方式,在不进行任何设置时,如果一个被代理的类实现了接口,就优先使用java动态代理。
2)Spring在bean的创建过程中将代理应用于bean上,代理的创建有这么一个重要的类AbstractAutoProxyCreator,这个类用于自动代理的创建,而这个类实现的接口中有BeanPostProcessor这个接口。但是这个类是一个抽象类,因为系统会根据不同的配置方式创建不同的子类:
对于aop:config的标签,创建的是AspectJAwareAdvisorAutoProxyCreator类,对于aspectj-autoproxy标签,创建的是AnnotationAwareAspectJAutoProxyCreator类。其继承结构如下:
这里写图片描述
3)BeanPostProcessor的几个方法都是钩子函数,Spring容器管理的bean在创建过程中会调用实现了BeanPostProcessor的类的几个方法,用于修改创建的bean的实例。
4)Spring中aop采用了aopalliance的约定,Advice是一个标记接口,其子接口为Interceptor,事务的实现类就是一个Interceptor。Advisor接口用来包含Advice和其他一些信息,分为IntroductionAdvisor和PointcutAdvisor两个分支,前者只能应用于类层面。事务管理中的Advisor类是BeanFactoryTransactionAttributeSourceAdvisor,是PointcutAdvisor的一个分支。
5)事务的Interceptor为TransactionInterceptor

那么我们从AbstractAutoProxyCreator作为入口进行源代码的分析:
首先看实现的BeanPostProcessor的钩子函数

    /**
     * Create a proxy with the configured interceptors if the bean is
     * identified as one to proxy by the subclass.
     * @see #getAdvicesAndAdvisorsForBean
     */
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.containsKey(cacheKey)) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

这个方法的注释说明了这个方法的作用是:创建代理并应用所配置的interceptor于其上。
沿着这个方法继续查看wrapIfNecessary方法的代码片断:

            // Create proxy if we have advice.
            // 查找这个bean的adive和advisor
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            // 加入缓存
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            // 创建代理
            Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

可以发现,系统将查找应用于这个bean上的advice和advisor,然后根据此创建代理。getAdvicesAndAdvisorsForBean这个方式是一个模板方法,具体的实现由子类AbstractAdvisorAutoProxyCreator实现。
子类中getAdvicesAndAdvisorsForBean调用了findEligibleAdvisors函数:

    //找到所有advisor
        List<Advisor> candidateAdvisors = findCandidateAdvisors(); 
    //过滤适用于这个bean的advisor
        List<Advisor> eligibleA
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值