我有一个带有注释的方法的 POJO 类@Transactional
public class Pojo {
@Transactional
public void doInTransaction() {
...
}
}
Spring 声明式事务管理基于 AOP,但我对此没有任何经验。我的问题是:是否有可能在单独调用(new Pojo).doInTransaction()
时,Spring 会启动一个事务。
我有一个带有注释的方法的 POJO 类@Transactional
public class Pojo {
@Transactional
public void doInTransaction() {
...
}
}
Spring 声明式事务管理基于 AOP,但我对此没有任何经验。我的问题是:是否有可能在单独调用(new Pojo).doInTransaction()
时,Spring 会启动一个事务。
Spring 声明式事务管理基于 APO,但我对此没有任何经验。
我建议您开始使用它,您将获得使用 AOP 使用事务建议的经验。一个好的起点就在这里。
是否有可能在单独调用 (new Pojo).doInTransaction() 时,Spring 将启动一个事务。
不,您不能期望 Spring 知道您手动调用的 bean。但是,听起来您想要避免声明式事务管理并进行程序化事务管理。有一种方法可以使用 Spring 使用Transaction Template来做到这一点。那是你要找的吗?
这在某种程度上是可能的,但以一种麻烦的方式:您必须使用该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 框架,而且它违反了依赖注入原则。所以只有在没有其他方法的情况下才使用它!
是的,这是可能的。Spring不需要使用动态代理@Transactional
来工作。相反,您可以使用 AspectJ 提供的“真正的 AOP”。
正如您所说,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 包装到注释感知动态代理实例中。从你的观点来看,这并没有改变任何东西,你仍然会将你的对象转换为你自己的类,但是如果你尝试打印出你的 spring 上下文 Pojo bean 的类名,你会得到 Proxy$。 ..而不是你原来的班级名称。
无论如何看看这个链接:链接文本