有A、B两个服务,相互依赖时会造成事务失效,简要代码如下:
AServiceImpl
@Service(interfaceClass=IAService.class,group="test",version="1.0.0")
@Transactional
public class AServiceImpl implements IAService {
@Autowired
private ITestService testService;
@Autowired
private IBService bService;
@Override
public void test(String string) {
TestEntity testEntity = new TestEntity();
testEntity.setTest("A-"+string);
testEntity = testService.save(testEntity);
if(!Objects.isNull(testEntity.getId())){
throw new RuntimeException("AService test....a...");
}
}
}
BServiceImpl
@Service(interfaceClass=IBService.class,group="test",version="1.0.0")
@Transactional
public class BServiceImpl implements IBService {
@Autowired
private ITestService testService;
@Autowired
private IAService aService;//相互引用,但实际并未使用
@Override
public void test(String string) {
TestEntity testEntity = new TestEntity();
testEntity.setTest("B-"+string);
testEntity = testService.save(testEntity);
if(!Objects.isNull(testEntity.getId())){
throw new RuntimeException("BService test...b....");
}
}
}
test
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootDubboDemoApplicationTests {
@Autowired
private ITestService testService;
@Reference(group = "test", version = "1.0.0")
private IAService iaService;
@Reference(group = "test", version = "1.0.0")
private IBService ibService;
@Test
public void testDubbo(){
System.out.println("start......");
try {
iaService.test("aaaa");
}catch (Exception e){
e.printStackTrace();
}
try {
ibService.test("bbbbb");
}catch (Exception e){
e.printStackTrace();
}
}
}
正常执行过后,事务应该回滚,数据库中没有保存数据
实际结果,a服务执行,数据库中存在记录
A-aaaa 被插入数据库
当注释掉A/B的循环依赖时,结果正常,数据库中没有数据
详细代码见:https://github.com/softxiang/springboot-dubbo-demo
另有一个问题如下:
@Service(interfaceClass=IAService.class,group="test",version="1.0.0")
@Transactional
public class AServiceImpl implements IAService
此种情况定义了一个dubbo service,是否还需要spring扫描这个service 看代码情况是不需要spring再做相应操作,但看网上很多文章包括issues中依然有人提类似问题 #2093
一个服务既是dubbo服务又是本地服务时,是否只需要注册为dubbo的service即可?
@Autowired
private IBService bService;
是否会自动区分本地service调用 还是dubbo service?
使用spring service标记服务C、D模拟上面类似情况,未出现事务失效的问题
dubbo can't support transactions.
但是A和B之间还没有调用关系,只是做了申明就失效了
如果把A、B都显式申明为dubbo service,A可以注入,B就注入不了
如:在AServiceImpl、BServiceImpl将 a b循环依赖的@Autowired改为
@Reference(group = "test", version = "1.0.0")
后,测试方法中的
@Reference(group = "test", version = "1.0.0")
private IBService ibService;
注入为null
有其他人发现并解决了问题,希望官方能处理一下
https://blog.csdn.net/liangshf520/article/details/79621345
有其他人发现并解决了问题,希望官方能处理一下
https://blog.csdn.net/liangshf520/article/details/79621345
这个问题和你碰到的循环依赖应该是两个问题。
你的这个问题今天我看了一下,主要原因是用于处理 dubbo 注解的 com.alibaba.dubbo.config.spring.AnnotationBean 实现的是 BeanPostProcessor 接口。这种实现方式是不太正确的,原因如下:
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
...
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
...
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
所以,正确的做法应该是废弃掉 BeanPostProcessor 的做法,而是在 ApplicationListener 中开始暴露 dubbo 服务,也就是说,等 spring 组装完毕之后 (org.springframework.context.support.AbstractApplicationContext#finishRefresh),再开始暴露服务。
总结一下,对于 dubbo 要暴露的服务,在 spring 场景下,真正应该代理的类不是 service interface 是实现,而是被 spring 正确组装以及增强完毕之后的类。
这个问题会统一在 2.6.6 版本中解决。
有其他人发现并解决了问题,希望官方能处理一下
https://blog.csdn.net/liangshf520/article/details/79621345
这个问题也看了一下。的确如作者所说,在 2.5.9 和 master 上都已经修复,问题仅存在在 2.6 分支上。根本原因还是 AnnotationBean 的问题。在他的例子中,aop 使用的是 jdk 的 dynamic proxy,导致 AnnotationBean 判断 Dubbo 服务失败,没有正常暴露服务。
改成 master 上新的机制就完全没有问题
这个问题会统一在 2.6.6 版本中解决。
感谢大佬
Most helpful comment
这个问题会统一在 2.6.6 版本中解决。