【问题标题】:Spring Transaction Management: using @Transactional vs using AOP (<aop:advisor)Spring 事务管理:使用 @Transactional 与使用 AOP (<aop:advisor)
【发布时间】:2015-03-24 17:35:11
【问题描述】:

我对 Spring 事务管理感到困惑。在我的应用程序中,我在服务类中使用 @Transactional 实现了事务管理。我配置我的spring.xml就像:

    <beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <beans:property name="dataSource" ref="dataSource" />
            <beans:property name="configLocation" value="classpath:hibernate.cfg.xml"/>                              
            <beans:property name="hibernateProperties">
                <beans:props>
                    <beans:prop key="hibernate.dialect">${jdbc.dialect}</beans:prop>
                    <beans:prop key="hibernate.show_sql">false</beans:prop>
                    <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
                </beans:props>
            </beans:property>
        </beans:bean>  
        <!-- Transaction manager -->
            <beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
                <beans:property name="sessionFactory" ref="sessionFactory" />
            </beans:bean> 

如果我在下面的配置文件中实现事务管理,而不在服务类中使用@Transactional:

    <aop:pointcut id="defaultServiceOperation"
            expression="execution(* x.y.service.*Service.*(..))"/>

    <aop:pointcut id="noTxServiceOperation"
            expression="execution(* x.y.service.ddl.DefaultDdlManager.*(..))"/>

    <aop:advisor pointcut-ref="defaultServiceOperation" advice-ref="defaultTxAdvice"/>

    <aop:advisor pointcut-ref="noTxServiceOperation" advice-ref="noTxAdvice"/>

</aop:config>

它比@Transactional 给我带来什么好处吗?有人告诉我使用@Transactional 也是spring 中AOP 的实现。谁能解释一下?

【问题讨论】:

    标签: java spring aop spring-transactions


    【解决方案1】:

    不会的。

    好处

    如果您不需要一些非常明确的要求,或者您没有性能问题,则不应该重新发明轮子。 Spring 几乎是完美设计、测试和锐化的工具,甚至可以替代企业应用服务器。 @Transactional 是管理事务的声明方式,它比任何 aop xml 配置更方便和可读。它的好处包括以声明方式自动处理所有事务管理方面:隔离和传播级别(控制嵌套事务并不容易)、超时、回滚条件以及服务类的每个方法的不同 TransactionManagers。易于阅读、易于配置、易于使用。

    @Transactional(readOnly = false, rollbackFor = ServiceException.class, isolation = Isolation.READ_COMMITTED)
    public void myServiceJob(...)
    

    当你看到这个方法时,很容易理解它的事务属性(在方法中不提供事务实现细节)。如果是普通的 AOP,每次你想知道这个方法发生了什么,你应该检查你的 xml 配置并找到相应的方法,这不太优雅。

    另一方面,调试或使用这些代理进行任何其他声明式管理非常困难。例如。这很棘手(但并非不可能)从上下文中提取您的 bean 并使用反射从包装的 bean 中获取一些东西(比如说,出于监控目的)。另外,当bean调用它的一个方法时,它不会被委托给proxy,因为你的bean对proxy一无所知,所以this指的是bean本身。解决此问题的唯一方法是提供“self”字段并将其设置在自定义 bean 后处理器中(但您的实现也受此影响)。

    实施

    如果 Spring 配置为使用事务管理,它会在 bean 的定义上寻找 @Transactional 注释并创建自动生成的 AOP 代理,它是您的 bean 的子类。 Spring 代理的默认行为只是将方法的调用委托给底层 bean。然后 Spring 用必要的 TransactionManager 注入 TransactionInterceptor。 拦截器的代码看起来很简单:

    public Object invoke(final 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...
        return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
            @Override
            public Object proceedWithInvocation() throws Throwable {
                return invocation.proceed();
            }
        });
    }
    

    invokeWithinTransactionTransactionInterceptor 内部确定调用是否应该在调用者事务的范围内(如果存在)还是在新的事务范围内(它与传播级别有关)。然后选择对应的TransactionManager,配置超时时间和隔离级别,然后调用该方法。在它决定是否应该提交或回滚事务之后(根据捕获的异常和时间做出选择)。

    【讨论】:

    • 感谢您的回答。您不仅回答了我的问题,还让我了解了春季交易。我有一种感觉,@Transactional 更容易理解,也更容易工作。当 Spring 管理整个事务过程时,现在我可以选择这种方法而不是基于 xml 的事务管理方法。
    猜你喜欢
    • 2014-11-30
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-24
    • 1970-01-01
    相关资源
    最近更新 更多