2015-03-24 6 views
1

У меня есть путаница в управлении транзакциями Spring. В моем приложении я реализовал управление транзакциями, используя @Transactional в классе службы. И я настроил мой spring.xml, как:Управление весовыми транзакциями: использование @Transactional против AOP (<aop: advisor)

<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 - это также реализация АОП весной. Может ли кто-нибудь объяснить мне, как?

ответ

0

Это не будет.

Преимущества

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

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

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

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

Реализация

Если Spring настроен на использование транзакций управления, он ищет @Transactional аннотации определений бина и создает автоматически сгенерированный АОП прокси, который является подклассом вашего компонента. Поведение по умолчанию прокси-сервера 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's invokeWithinTransaction... 
    return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() { 
     @Override 
     public Object proceedWithInvocation() throws Throwable { 
      return invocation.proceed(); 
     } 
    }); 
} 

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

+0

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