Spring 事务管理:使用 @Transactional 与使用 AOP (<aop:advisor) [英] Spring Transaction Management: using @Transactional vs using AOP (<aop:advisor)

查看:34
本文介绍了Spring 事务管理:使用 @Transactional 与使用 AOP (<aop:advisor)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a confusion about Spring transaction management. In my application I implemented transaction management using @Transactional in the service class. And I configured my spring.xml is like:

    <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:

If I implement transaction management in the configuration file like below without using @Transactional in the service class:

    <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 也是春季 AOP 的实现.谁能给我解释一下?

does it give me any benefits over @Transactional? Someone told me using @Transactional is also implementation of AOP in spring. Can anyone explain me how?

推荐答案

不会.

好处

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

If you don't need some very specified requirements or you have no performance issues, you shouldn't reinvent the wheel. Spring is almost perfectly designed, tested and sharped instrument, which can be replacement even for enterprise application servers. @Transactional is declarative way for managing transactions, it's far more convenient and readable than any aop xml configs. It's benefits include automatic handling of all transaction management aspects in declarative way: isolation and propagation levels (it's not easy to control nested transactions), timeouts, rollback conditions and distinct TransactionManagers for every single method of your service's class. Easy to read, easy to configure, easy to use.

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

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

When you see this method, it's easy to understand it's transactional attributes (without providing transactions implementation details in method). In case of plain AOP every time you want to know what happens in this method, you should check your xml config and find corresponding method, which is way less elegant.

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

On other hand, it's very hard to debug or use these proxies for any other declarative management. E.g. it's tricky (but not impossible) extract your bean from context and get something out of your wrapped bean using reflection (let's say, for monitoring purposes). In addition, when bean calls one of its method, it won't be delegated to proxy, because your bean knows nothing about proxy, so this refers to bean itself. The only way to cure this it to provide "self" field and set it in custom bean postprocessor (but your implementation suffers from this either).

实施

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

If Spring is configured to use transactional management, it's looking for @Transactional annotation on bean's definitions and creates auto-generated AOP proxy, which is subclass of your bean. Default behavior of Spring proxy is just delegating method's calls to underlying bean. Then Spring injects TransactionInterceptor with necessary TransactionManagers. Code of interceptor looks quite simple:

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();
        }
    });
}

invokeWithinTransaction 内部 TransactionInterceptor 确定调用应该在调用者事务的范围内(如果存在)还是在新的范围内(关于传播级别).然后选择对应的TransactionManager,配置超时和隔离级别,然后调用方法.在决定事务是提交还是回滚之后(根据捕获的异常和时间进行选择).

Inside of invokeWithinTransaction TransactionInterceptor determines whether should invocation be in scope of caller transaction (if one exists) or in a new one (it's about propagation level). Then it choses corresponding TransactionManager, configures timeout and isolation level, then invokes the method. After it decides if transaction should be commited or rolled back (choice is made based on caught exception and timing).

这篇关于Spring 事务管理:使用 @Transactional 与使用 AOP (&lt;aop:advisor)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆