2015-08-17 7 views
6

У меня есть пользовательский Around, реализованный в соответствии с пользовательской аннотацией. Я хочу, чтобы пользовательский интерфейс выполнял WITHIN в внешнем @Transactional. К сожалению, это не работает. (AOP работает. Я вижу стеки, которые показывают его).Custom Spring AOP Around + @Transactional

Трассировка стека показывает мое выполнение AOP перед (регистратором), сеансом MyBatis, начинающим транзакцию, MyBatis, закрывающим транзакции, весной, закрывающей транзакцию, а затем завершением моей AOP.

Я думал, что это будет иметь приспособление для АОП. Я установил значение, возвращаемое в 1. Я использовал. Это не сработало. Я думаю, это потому, что я неправильно понял, как заказы Весны.

Advice заказа

Что происходит, когда несколько советов все хотят работать на же присоединиться к точке? Spring AOP следует тем же правилам приоритета, что и AspectJ, чтобы определить порядок выполнения рекомендаций. Самый старший совет приоритетов запускается сначала «по пути в» (поэтому дается два куска перед советом, первый с наивысшим приоритетом запускается первым). «На выходе выход из точки соединения, совет с наивысшим приоритетом запускается последним (так что дано два куска после совета, тот, который имеет наивысший приоритет , будет работать вторым).

Если два аргумента, определенные в разных аспектах, оба должны иметь значение , выполняются в одной и той же точке соединения, если вы не указали иначе, то порядок выполнения не определен. Вы можете контролировать порядок выполнения на с указанием приоритета. Это делается обычным способом Spring либо , реализующим интерфейс org.springframework.core.Ordered в классе аспектного вида или аннотируя его аннотацией заказа. Учитывая два аспекта , аспект, возвращающий более низкое значение из Ordered.getValue() (или значение аннотации), имеет более высокий приоритет.

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

Так что я взял атрибут заказа. Это должно заставить @Transactional возвращать Integer.MIN_VALUE. Поэтому, если бы я понял вышеприведенную цитату, то должен был работать последним. Когда я перераспределяюсь, он все еще выполняется назад. Мой AOP, Spring TX, MyBatis, Закрыть MyBatis, Закрыть SPring Tx, Закрыть мой AOP.

Что я делаю неправильно?

ответ

7

Если атрибут порядок не сконфигурирован для аннотации @Transactional, то Advisor, который несет ответственность за транзакции - атрибут AbstractPointcutAdvisor (на самом деле, одним из подклассов него) будет возвращать Ordered .LOWEST_PRECEDENCE, который определяется как целое число .MAX_VALUE.

Советник, отвечающий за пользовательский совет АОП, подкласс того же самого AbstractPointcutAdvisor, будет проверять, реализует ли фактический Advice заказный интерфейс, и если это так, предоставленное значение будет использоваться во время сортировки. Если пользовательский совет АОП не реализует Упорядоченный интерфейс, Советник возвращает тот же Default Ordered.LOWEST_PRECEDENCE, и результат сортировки становится слегка непредсказуемым.

Итак, настройка атрибута заказа для аннотации @Transactional, например. как это

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xsi:schemaLocation=" 
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
      http://www.springframework.org/schema/tx 
      http://www.springframework.org/schema/tx/spring-tx-3.1.xsd> 
      ....... 

      <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" order="[Order for @Transactional]"> 
<beans/>  

, и ваш совет АОП реализация выглядит следующим образом

import org.aspectj.lang.ProceedingJoinPoint; 
import org.aspectj.lang.annotation.Around; 
import org.aspectj.lang.annotation.Aspect; 

import org.springframework.core.Ordered; 

@Aspect 
public class CustomAspect implements Ordered { 

    @Around(value = "@annotation(CustomAnnotation)") 
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable { 
    ... 
    } 
    .... 

    @Override 
    public int getOrder() { 
     return [Order for @CustomAnnotation]; 
    } 

    .... 

} 

, то вы, вероятно, есть вся свобода (пока, статически) с упорядочением в вашем приложении.

Под капотом, это AspectJAwareAdvisorAutoProxyCreator, который при инициализации прокси сортирует Advisors с помощью компаратора org.springframework.aop.aspectj.autoproxy.AspectJPrecedenceComparator, который делегирует сортировки для OrderComparator. Позже, после фактического выполнения, конкретная реализация AopProxy содержит для определенного метода массив советов, на которые он называет перехватчики, и это может быть использовано для динамического переупорядочения, я думаю, но ни одна из этих вещей мне не кажется легко доступны и/или настраиваются.

My environment is Spring Beans, TX, АОП - все версии 4.0.3. У меня также есть два менеджера пользовательских Transaction, один Hibernate переплет и один JDBC DataSource переплета, но я не думаю, что здесь имеет значения

3

После небольшого эксперимента выясняется, что просто удаление атрибута не делает эту работу. Я нахожу это нечетным, поскольку порядок @Transactional по умолчанию - Integer.MIN_VALUE. По-видимому, если вы хотите включить заказ, вам нужно явно указать порядок на самый маленький из всех заказов АОП.

Смежные вопросы