Где я должен поместить аннотацию @Transactional: в определении интерфейса или в классе реализации?



вопрос из заголовка в коде:



@Transactional (readonly = true)
public interface FooService {
void doSmth ();
}


public class FooServiceImpl implements FooService {
...
}


vs



public interface FooService {
void doSmth ();
}

@Transactional (readonly = true)
public class FooServiceImpl implements FooService {
...
}
685   6  

6 ответов:

от http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

рекомендация весенней команды заключается в том, что вы только аннотируете конкретные классы с помощью @Transactional аннотации, в отличие от аннотирования интерфейсы. вы, конечно, можете разместить @Transactional аннотация на интерфейсе (или методе интерфейса), но это будет работать только так, как вы ожидаете, если вы используете прокси-серверы на основе интерфейса. Дело в том, что аннотации не унаследовал означает, что если вы используете прокси-серверы на основе классов, то параметры транзакции не будут распознаны инфраструктурой проксирования на основе классов, и объект не будет завернут в прокси-сервер транзакций (который будет решительно плохо). Поэтому, пожалуйста, примите совет команды Spring и только аннотируйте конкретные классы (и методы конкретных классов) с помощью @Transactional Примечание.

Примечание: так как эта механизм основан на прокси, только "внешние" вызовы метода, поступающие через прокси, будут перехвачены. это означает, что 'self-invocation', т. е. метод в целевом объекте, вызывающий какой-либо другой метод целевого объекта, не приведет к фактической транзакции во время выполнения, даже если вызванный метод помечен @Transactional!

(ударение добавлено к первому предложению, другое ударение от оригинала.)

вы можете поместить их на интерфейс, но будьте предупреждены, что транзакции могут не произойти в некоторых случаях. Смотрите второй совет в параграф 10.5.6 из весенних документов:

Spring рекомендует аннотировать только конкретные классы (и методы конкретных классов) с помощью аннотации @Transactional, а не аннотировать интерфейсы. Вы, конечно, можете разместить аннотацию @Transactional на интерфейсе (или методе интерфейса), но это работает только как вы ожидаете, если вы используете интерфейс на основе прокси. Тот факт, что аннотации Java не наследуются от интерфейсов, означает, что если вы используете прокси-серверы на основе классов (proxy-target-class="true") или аспект на основе переплетения (mode="aspectj"), то параметры транзакции не распознаются инфраструктурой проксирования и переплетения, и объект не будет обернут в транзакционный прокси, что было бы решительно плохо.

Я бы рекомендовал надеть их реализация по этой причине.

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

весной рекомендация это то, что вы аннотируете конкретные реализации вместо интерфейса. Это не неправильно использовать аннотацию на интерфейсе, просто можно злоупотреблять этой функцией и непреднамеренно обходить объявление @Transaction.

Если вы отметили что-то транзакционное в интерфейсе, а затем ссылаетесь на один из его реализующих классов в другом месте в spring, не совсем очевидно, что объект, который создает spring, не будет уважать аннотацию @Transactional.

на практике это выглядит примерно так:

public class MyClass implements MyInterface { 

    private int x;

    public void doSomethingNonTx() {}

    @Transactional
    public void toSomethingTx() {}

}

поддержка @Transactional на конкретных классах:

Я предпочитаю архитектировать решение в 3 разделах вообще: API, реализация и веб (если это необходимо). Я стараюсь изо всех сил поддерживать API как можно более легким/простым/POJO, минимизируя зависимости. Это особенно важно, если вы играете в распределенной/интегрированной среде, где вам нужно много делиться API.

для размещения @Transactional требуются библиотеки Spring в разделе API, который является IMHO не эффективно. Поэтому я предпочитаю добавлять его в реализацию, где выполняется транзакция.

размещение его на интерфейсе прекрасно, пока все прогнозируемые исполнители вашего IFC заботятся о данных TX (транзакции-это не проблемы, с которыми имеют дело только базы данных). Если метод не заботится о TX (но вам нужно поместить его туда для спящего режима или что-то еще), поместите его на impl.

кроме того, это может быть немного лучше место @Transactional о методах в интерфейсе:

public interface FooService {
    @Transactional(readOnly = true)
    void doSmth();
}

пожалуйста, взгляните на ссылку ниже, который иллюстрирует проблему с простым, но объясняя пример:

http://kim.saabye-pedersen.org/2013/05/spring-annotation-on-interface-or-class.html

Comments

    Ничего не найдено.