Nahid Shah
Nahid Shah

Reputation: 213

Spring Transaction Management: using @Transactional vs using AOP (<aop:advisor)

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> 

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>

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?

Upvotes: 1

Views: 1547

Answers (1)

qwwdfsad
qwwdfsad

Reputation: 3207

It won't.

Benefits

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(...)

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.

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).

Implementation

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

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).

Upvotes: 1

Related Questions