Spring начать транзакцию с объекта, созданного новым - PullRequest
2 голосов
/ 16 января 2011

У меня есть класс POJO с методом, аннотированным @Transactional

public class Pojo {

    @Transactional
    public void doInTransaction() {
        ...
    }
}

Управление декларативными транзакциями Spring основано на AOP, но я не имею никакого опыта в этом.Мой вопрос: возможно ли, что при вызове только (new Pojo).doInTransaction() Spring запустит транзакцию.

Ответы [ 4 ]

3 голосов
/ 16 января 2011

Spring декларативное управление транзакциями основано на APO, но у меня нет никакого опыта с этим.

Я бы порекомендовал начать работать с ним, и вы получите опыт использования советов по транзакциям с использованием AOP.Хорошей отправной точкой является здесь .

Возможно ли, что при вызове (нового Pojo) .doInTransaction () только Spring начнет транзакцию.*

Нет, вы не можете ожидать, что Spring узнает о бине, который вы вызвали вручную.Однако, похоже, что вы хотите избежать декларативного управления транзакциями и выполнять программное управление транзакциями.Есть способ сделать это с помощью Spring с использованием Transaction Template .Это то, что вы искали?

1 голос
/ 10 июня 2011

Да, возможно . Spring не требует использования динамических прокси для работы @Transactional. Вместо этого вы можете использовать «истинный AOP», как это предусмотрено AspectJ.

Подробнее см. http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-declarative-aspectj

1 голос
/ 17 января 2011

Это несколько возможно, но громоздким способом: Вы должны использовать механизм AutowireCapableBeanFactory.

Вот пример транзакционного класса

public interface FooBar{
    void fooIze(Object foo);
}

public class FooBarImpl implements FooBar{
    @Transactional
    @Override
    public void fooIze(final Object foo){
        // do stuff here
    }
}

А вот как мы можем это использовать:

public class FooService implements ApplicationContextAware{

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(
    final ApplicationContext applicationContext){
        this.applicationContext = applicationContext;
    }

    public void serviceMethod(){

        //declare variable as interface, initialize to implementation
        FooBar fooBar = new FooBarImpl();

        // try to use it, won't work, as it's not a proxy yet
        Object target = new Object[0];
        fooBar.fooIze(target); // no transaction

        // now let spring create the proxy and re-assign the variable
        // to the proxy:
        fooBar = // this is no longer an instance of FooBarImpl!!!
            (FooBar) applicationContext
                .getAutowireCapableBeanFactory()
                .applyBeanPostProcessorsAfterInitialization(fooBar,
                    "someBeanName");
        fooBar.fooIze(fooBar); // this time it should work

    }

}

Это не лучшая практика. Во-первых, это делает ваше приложение хорошо осведомленным о Spring Framework, а также нарушает принципы внедрения зависимостей. Так что используйте это, только если нет другого пути!

0 голосов
/ 16 января 2011

Способ, которым Spring обрабатывает транзакцию через Annotation, использует AOP, как вы сказали. Бит AOP реализован с использованием динамических прокси (см. doc )

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

Если вы просто сделаете

Pojo p = new Pojo();
p.doInTransaction();

Spring не играет здесь никакой роли, и ваш вызов метода не будет внутри транзакции.

так что вам нужно сделать что-то вроде этого

ApplicationContext springContext = ...;
Pojo p = (Pojo) springContext.getBean("your.pojo.id");
p.doInTransaction();

Примечание: это пример, вы должны предпочесть внедрение зависимостей вместо того, чтобы извлекать ваш бин вручную из контекста

Таким образом, и с правильно настроенным Spring Context, Spring должен иметь возможность проверять ваши классы на наличие транзакционных аннотаций и автоматически оборачивать ваши бины в экземпляры динамических прокси с поддержкой аннотаций. С вашей точки зрения, это ничего не меняет, вы все равно приведете свой объект к своим собственным классам, но если вы попытаетесь распечатать имя класса вашего пружинного контекста Pojo, вы получите что-то вроде Proxy $. .. а не ваше первоначальное имя класса.

Взгляните на эту ссылку в любом случае: текст ссылки

...