开发者

Spring start a transaction with object created by new

开发者 https://www.devze.com 2023-02-05 11:35 出处:网络
I have a POJO class with a method annotated with @Transactional public class Pojo { @Transactional public void doInTransaction() {

I have a POJO class with a method annotated with @Transactional

public class Pojo {

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

Spring declarative transaction management is based on AOP but I don't have any experience with that. My question is: Is it p开发者_如何学Goossible that when invoking the (new Pojo).doInTransaction() alone, Spring will start a Transaction.


Spring declarative transaction management is based on APO but I don't have any experience with that.

I would recommend to start working with it and you will get the experience of using transaction advices using AOP. A good starting point is here.

Is it possible that when invoking the (new Pojo).doInTransaction() alone, Spring will start a Transaction.

No, you can't expect Spring to be aware of a bean that you manually invoked. However, it sounds like that you are wanting to avoid declarative transaction management and do programmatic transaction management. There is a way to do that with Spring using the Transaction Template. Is that what you were looking for?


It is somewhat possible, but in a cumbersome way: You must use the AutowireCapableBeanFactory mechanism.

Here is a transactional class as example

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

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

And here is how we can use it:

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

    }

}

This is not a best practice. For one thing, it makes your application highly aware of the Spring Framework and also, it violates the dependency injection principles. So use this only if there is no other way!


Yes, it is possible. Spring does not require the use of dynamic proxies for @Transactional to work. Instead, you can use "true AOP", as provided by AspectJ.

For the details, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-declarative-aspectj


The way Spring handle the transaction through Annotation is using AOP as you've said. The AOP bit is implemented using Dynamic Proxies (see doc)

So in order to do so you'll need to retrieve an instance of your class (Pojo here) through the spring container since to make it work, Spring will return you a Dynamic Proxy over your Pojo that will automatically surround any annotated method with the transaction management code.

If you simply do a

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

Spring doesn't have any role to play here and your method call won't be inside a transaction.

so what you need to do is something like this

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

Note: this is an example, you should prefer dependency injection instead of retrieving your bean manually from the context

By doing so, and with a properly configured Spring Context, Spring should have lookout your classes to scan for transactional annotation and automatically wrapped your beans into annotation aware dynamic proxies instances. From your point of view that doesn't change anything, you'll still cast your object to your own Classes, but if you try to print out the class name of your spring context Pojo bean, you'll get something as Proxy$... and not your original class name.

Have a look at this link anyway : link text

0

精彩评论

暂无评论...
验证码 换一张
取 消