Spring使用new创建的对象启动事务

时间:2011-01-16 18:27:06

标签: java spring spring-aop spring-transactions

我有一个POJO类,其注释方法使用@Transactional

public class Pojo {

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

Spring声明式事务管理基于AOP,但我没有任何经验。我的问题是: 是否有可能在单独调用(new Pojo).doInTransaction()时,Spring将启动一个事务。

4 个答案:

答案 0 :(得分:3)

  

Spring声明式事务   管理是基于APO,但我没有   对此有任何经验。

我建议您开始使用它,您将获得使用AOP使用交易建议的经验。一个很好的起点是here

  

调用时是否可能   (新Pojo).doInTransaction()单独,   Spring将启动一个Transaction。

不,你不能指望Spring知道你手动调用的bean。但是,听起来您希望避免声明式事务管理并执行程序化事务管理。使用Transaction Template有一种方法可以使用Spring。那是你在找什么?

答案 1 :(得分:1)

这有点可能,但是以一种繁琐的方式:你必须使用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,并且它违反了依赖注入原则。所以只有在没有别的办法时才使用它!

答案 2 :(得分:1)

是的, 是可能的。 Spring 要求使用@Transactional的动态代理才能工作。相反,您可以使用AspectJ提供的“真正的AOP”。

有关详细信息,请参阅http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-declarative-aspectj

答案 3 :(得分:0)

Spring通过Annotation处理事务的方式正如你所说的那样使用AOP。 AOP位使用动态代理实现(请参阅doc

所以为了做到这一点你需要通过spring容器检索你的类的实例(这里是Pojo),因为为了使它工作,Spring将返回你的Pojo上的动态代理,它将自动包围任何注释使用事务管理代码的方法。

如果你只是做一个

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

Spring在这里没有任何角色,你的方法调用也不在事务中。

所以你需要做的就是这样

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

注意:这是一个示例,您应该更喜欢依赖注入,而不是从上下文中手动检索bean

通过这样做,并且通过正确配置的Spring上下文,Spring应该了解您的类以扫描事务注释并自动将bean包装到注释感知动态代理实例中。从你的观点来看,你不会改变任何东西,你仍然会将你的对象转换为你自己的类,但如果你试图打印出你的春天上下文Pojo bean的类名,你会得到一些代理作为$。 ..而不是你原来的班级名称。

无论如何,请查看此链接:link text