Spring Transaction Management: использование @Transactional против использования AOP (<aop: advisor)

1

У меня есть путаница в управлении транзакциями 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
spring-transactions

1 ответ

0
Лучший ответ

Это не так.

Выгоды

Если вам не нужны какие-то очень определенные требования или у вас нет проблем с производительностью, вы не должны изобретать велосипед. Весна практически идеально спроектирована, протестирована и скорректирована, что может быть заменой даже для серверов корпоративных приложений. @Transactional является декларативным способом управления транзакциями, он гораздо удобнее и читабельнее любых конфигураций aop xml. К преимуществам относится автоматическая обработка всех аспектов управления транзакциями декларативным способом: уровни изоляции и распространения (нелегко контролировать вложенные транзакции), тайм-ауты, условия отката и различные транзакционные менеджеры для каждого отдельного метода вашего класса обслуживания. Легко читается, легко настраивается, прост в использовании.

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

Когда вы видите этот метод, легко понять его транзакционные атрибуты (без предоставления сведений о реализации транзакций в методе). В случае простого AOP каждый раз, когда вы хотите узнать, что происходит в этом методе, вы должны проверить свой xml-конфигуратор и найти соответствующий метод, который менее изящный.

С другой стороны, очень сложно отлаживать или использовать эти прокси для любого другого декларативного управления. Например, это сложно (но не невозможно) извлечь ваш компонент из контекста и получить что-то из вашего завернутого bean-компонента, используя отражение (скажем, для целей мониторинга). Кроме того, когда bean вызывает один из его методов, он не будет делегирован proxy, потому что ваш bean-компонент ничего не знает о прокси-сервере, поэтому this относится к самому bean-компоненту. Единственный способ вылечить это, чтобы обеспечить "я" поле и установить его в пользовательском bean postprocessor (но ваша реализация также страдает от этого).

Реализация

Если Spring настроен на использование управления транзакциями, он ищет аннотацию @Transactional для определений bean-компонентов и создает автоматически сгенерированный прокси AOP, который является подклассом вашего компонента. Поведение по умолчанию прокси-сервера Spring просто делегирует вызовы методов базовому компоненту. Затем Spring вводит TransactionInterceptor с необходимыми TransactionManagers. Код перехватчика выглядит довольно просто:

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

Внутри invokeWithinTransaction TransactionInterceptor определяет, должен ли быть вызов в области транзакции вызывающего абонента (если таковой существует) или в новой (это о уровне распространения). Затем он выбирает соответствующий TransactionManager, настраивает время ожидания и уровень изоляции, а затем вызывает метод. После того, как он решает, следует ли совершать транзакции или откатываться (выбор производится на основе исключенного и синхронизированного отслеживания).

  • 0
    Спасибо за Ваш ответ. Вы не только ответили на мой вопрос, но и дали мне представление о весенних сделках. У меня было ощущение, что @Transactional легче понять и легче в работе. Когда Spring управляет всем процессом транзакций, теперь я могу выбрать этот подход вместо подхода управления транзакциями на основе xml.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню