From abfafc31e26bef41fc45b8e6dd991f36a43126da Mon Sep 17 00:00:00 2001 From: Crel Wu Date: Tue, 14 Nov 2023 14:35:34 +0800 Subject: [PATCH 1/2] bugfix: can't integrate dubbo with spring (#6015) --- changes/en-us/2.0.0.md | 2 ++ changes/zh-cn/2.0.0.md | 2 ++ .../parser/DefaultInterfaceParser.java | 4 ++-- .../parser/DefaultResourceRegisterParser.java | 4 ++-- .../GlobalTransactionalInterceptorParser.java | 2 +- .../interceptor/parser/InterfaceParser.java | 2 +- .../parser/RegisterResourceParser.java | 2 +- .../parser/DefaultRemotingParser.java | 10 ++++++++ .../integration/tx/api/util/ProxyUtil.java | 6 ++++- ...balTransactionalInterceptorParserTest.java | 2 +- .../annotation/GlobalTransactionScanner.java | 6 ++++- .../parser/RemotingFactoryBeanParser.java | 24 +++++++++++++------ .../spring/tcc/TccAnnotationProcessor.java | 2 +- ...integration.tx.api.remoting.RemotingParser | 1 - .../parser/TccActionInterceptorParser.java | 6 ++--- .../parser/TccRegisterResourceParser.java | 4 ++-- .../TccActionInterceptorParserTest.java | 2 +- 17 files changed, 56 insertions(+), 25 deletions(-) delete mode 100644 spring/src/main/resources/META-INF/services/io.seata.integration.tx.api.remoting.RemotingParser diff --git a/changes/en-us/2.0.0.md b/changes/en-us/2.0.0.md index fc8b106af16..49ee6f02f5d 100644 --- a/changes/en-us/2.0.0.md +++ b/changes/en-us/2.0.0.md @@ -87,6 +87,7 @@ The version is updated as follows: - [[#5887](https://github.com/seata/seata/pull/5887)] fix global transaction hook repeat execute - [[#6018](https://github.com/seata/seata/pull/6018)] fix incorrect metric report - [[#6024](https://github.com/seata/seata/pull/6024)] fix the white screen after click the "View Global Lock" button on the transaction info page in the console +- [[#6015](https://github.com/seata/seata/pull/6015)] fix can't integrate dubbo with spring ### optimize: - [[#5966](https://github.com/seata/seata/pull/5966)] decouple saga expression handling and remove evaluator package @@ -219,6 +220,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [Aruato](https://github.com/Aruato) - [ptyin](https://github.com/ptyin) - [jsbxyyx](https://github.com/jsbxyyx) +- [xxxcrel](https://github.com/xxxcrel) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/2.0.0.md b/changes/zh-cn/2.0.0.md index bb9c22850e2..73012f63a0d 100644 --- a/changes/zh-cn/2.0.0.md +++ b/changes/zh-cn/2.0.0.md @@ -86,6 +86,7 @@ Seata 是一款开源的分布式事务解决方案,提供高性能和简单 - [[#5887](https://github.com/seata/seata/pull/5887)] 修复全局事务钩子重复执行 - [[#6018](https://github.com/seata/seata/pull/6018)] 修复错误的 metric 上报 - [[#6024](https://github.com/seata/seata/pull/6024)] 修复控制台点击事务信息页面中的"查看全局锁"按钮之后白屏的问题 +- [[#6015](https://github.com/seata/seata/pull/6015)] 修复在spring环境下无法集成dubbo ### optimize: @@ -221,6 +222,7 @@ Seata 是一款开源的分布式事务解决方案,提供高性能和简单 - [ggbocoder](https://github.com/ggbocoder) - [ptyin](https://github.com/ptyin) - [jsbxyyx](https://github.com/jsbxyyx) +- [xxxcrel](https://github.com/xxxcrel) diff --git a/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/DefaultInterfaceParser.java b/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/DefaultInterfaceParser.java index c083965ed62..f07799dae0a 100644 --- a/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/DefaultInterfaceParser.java +++ b/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/DefaultInterfaceParser.java @@ -53,9 +53,9 @@ protected void initInterfaceParser() { } @Override - public ProxyInvocationHandler parserInterfaceToProxy(Object target) throws Exception { + public ProxyInvocationHandler parserInterfaceToProxy(Object target, String objectName) throws Exception { for (InterfaceParser interfaceParser : ALL_INTERFACE_PARSERS) { - ProxyInvocationHandler proxyInvocationHandler = interfaceParser.parserInterfaceToProxy(target); + ProxyInvocationHandler proxyInvocationHandler = interfaceParser.parserInterfaceToProxy(target, objectName); if (proxyInvocationHandler != null) { return proxyInvocationHandler; } diff --git a/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/DefaultResourceRegisterParser.java b/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/DefaultResourceRegisterParser.java index eb6294a0f71..2bce82a34b0 100644 --- a/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/DefaultResourceRegisterParser.java +++ b/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/DefaultResourceRegisterParser.java @@ -28,9 +28,9 @@ public class DefaultResourceRegisterParser { protected static List allRegisterResourceParsers = new ArrayList<>(); - public void registerResource(Object target) { + public void registerResource(Object target, String beanName) { for (RegisterResourceParser registerResourceParser : allRegisterResourceParsers) { - registerResourceParser.registerResource(target); + registerResourceParser.registerResource(target, beanName); } } diff --git a/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/GlobalTransactionalInterceptorParser.java b/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/GlobalTransactionalInterceptorParser.java index fd5b6241508..6e879dd7dea 100644 --- a/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/GlobalTransactionalInterceptorParser.java +++ b/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/GlobalTransactionalInterceptorParser.java @@ -46,7 +46,7 @@ public class GlobalTransactionalInterceptorParser implements InterfaceParser { * @see GlobalLock // GlobalLock annotation */ @Override - public ProxyInvocationHandler parserInterfaceToProxy(Object target) throws Exception { + public ProxyInvocationHandler parserInterfaceToProxy(Object target, String objectName) throws Exception { Class serviceInterface = DefaultTargetClassParser.get().findTargetClass(target); Class[] interfacesIfJdk = DefaultTargetClassParser.get().findInterfaces(target); diff --git a/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/InterfaceParser.java b/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/InterfaceParser.java index 13e283936b3..18c30df3a34 100644 --- a/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/InterfaceParser.java +++ b/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/InterfaceParser.java @@ -22,7 +22,7 @@ */ public interface InterfaceParser { - ProxyInvocationHandler parserInterfaceToProxy(Object target) throws Exception; + ProxyInvocationHandler parserInterfaceToProxy(Object target, String objectName) throws Exception; } diff --git a/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/RegisterResourceParser.java b/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/RegisterResourceParser.java index bd749628ead..1f84ccc3ef3 100644 --- a/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/RegisterResourceParser.java +++ b/integration-tx-api/src/main/java/io/seata/integration/tx/api/interceptor/parser/RegisterResourceParser.java @@ -20,6 +20,6 @@ */ public interface RegisterResourceParser { - void registerResource(Object target); + void registerResource(Object target, String beanName); } diff --git a/integration-tx-api/src/main/java/io/seata/integration/tx/api/remoting/parser/DefaultRemotingParser.java b/integration-tx-api/src/main/java/io/seata/integration/tx/api/remoting/parser/DefaultRemotingParser.java index 5b3a28baf94..cb635612a18 100644 --- a/integration-tx-api/src/main/java/io/seata/integration/tx/api/remoting/parser/DefaultRemotingParser.java +++ b/integration-tx-api/src/main/java/io/seata/integration/tx/api/remoting/parser/DefaultRemotingParser.java @@ -75,6 +75,16 @@ protected void initRemotingParser() { } } + /** + * register custom remoting parser + * @param remotingParser + */ + public boolean registerRemotingParser(RemotingParser remotingParser) { + synchronized (this) { + return allRemotingParsers.add(remotingParser); + } + } + /** * is remoting bean ? * diff --git a/integration-tx-api/src/main/java/io/seata/integration/tx/api/util/ProxyUtil.java b/integration-tx-api/src/main/java/io/seata/integration/tx/api/util/ProxyUtil.java index 8c0f6960518..2ed74da1f69 100644 --- a/integration-tx-api/src/main/java/io/seata/integration/tx/api/util/ProxyUtil.java +++ b/integration-tx-api/src/main/java/io/seata/integration/tx/api/util/ProxyUtil.java @@ -34,12 +34,16 @@ public class ProxyUtil { private static final Map PROXYED_SET = new HashMap<>(); public static T createProxy(T target) { + return createProxy(target, target.getClass().getName()); + } + + public static T createProxy(T target, String beanName) { try { synchronized (PROXYED_SET) { if (PROXYED_SET.containsKey(target)) { return (T) PROXYED_SET.get(target); } - ProxyInvocationHandler proxyInvocationHandler = DefaultInterfaceParser.get().parserInterfaceToProxy(target); + ProxyInvocationHandler proxyInvocationHandler = DefaultInterfaceParser.get().parserInterfaceToProxy(target, beanName); if (proxyInvocationHandler == null) { return target; } diff --git a/integration-tx-api/src/test/java/io/seata/integration/tx/api/interceptor/parser/GlobalTransactionalInterceptorParserTest.java b/integration-tx-api/src/test/java/io/seata/integration/tx/api/interceptor/parser/GlobalTransactionalInterceptorParserTest.java index e6807a9fc4a..b426b304a32 100644 --- a/integration-tx-api/src/test/java/io/seata/integration/tx/api/interceptor/parser/GlobalTransactionalInterceptorParserTest.java +++ b/integration-tx-api/src/test/java/io/seata/integration/tx/api/interceptor/parser/GlobalTransactionalInterceptorParserTest.java @@ -33,7 +33,7 @@ void parserInterfaceToProxy() throws Exception { GlobalTransactionalInterceptorParser globalTransactionalInterceptorParser = new GlobalTransactionalInterceptorParser(); //when - ProxyInvocationHandler proxyInvocationHandler = globalTransactionalInterceptorParser.parserInterfaceToProxy(business); + ProxyInvocationHandler proxyInvocationHandler = globalTransactionalInterceptorParser.parserInterfaceToProxy(business, business.getClass().getName()); //then Assertions.assertNotNull(proxyInvocationHandler); diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java index be1e7533473..e51365dcb4b 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java @@ -41,8 +41,10 @@ import io.seata.integration.tx.api.interceptor.handler.GlobalTransactionalInterceptorHandler; import io.seata.integration.tx.api.interceptor.handler.ProxyInvocationHandler; import io.seata.integration.tx.api.interceptor.parser.DefaultInterfaceParser; +import io.seata.integration.tx.api.remoting.parser.DefaultRemotingParser; import io.seata.rm.RMClient; import io.seata.spring.annotation.scannercheckers.PackageScannerChecker; +import io.seata.spring.remoting.parser.RemotingFactoryBeanParser; import io.seata.spring.util.OrderUtil; import io.seata.spring.util.SpringProxyUtils; import io.seata.tm.TMClient; @@ -279,7 +281,7 @@ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) return bean; } interceptor = null; - ProxyInvocationHandler proxyInvocationHandler = DefaultInterfaceParser.get().parserInterfaceToProxy(bean); + ProxyInvocationHandler proxyInvocationHandler = DefaultInterfaceParser.get().parserInterfaceToProxy(bean, beanName); if (proxyInvocationHandler == null) { return bean; } @@ -472,6 +474,8 @@ public void afterPropertiesSet() { @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; + RemotingFactoryBeanParser remotingFactoryBeanParser = new RemotingFactoryBeanParser(applicationContext); + DefaultRemotingParser.get().registerRemotingParser(remotingFactoryBeanParser); this.setBeanFactory(applicationContext); } diff --git a/spring/src/main/java/io/seata/spring/remoting/parser/RemotingFactoryBeanParser.java b/spring/src/main/java/io/seata/spring/remoting/parser/RemotingFactoryBeanParser.java index 4e5c2ab7cbd..f077149d950 100644 --- a/spring/src/main/java/io/seata/spring/remoting/parser/RemotingFactoryBeanParser.java +++ b/spring/src/main/java/io/seata/spring/remoting/parser/RemotingFactoryBeanParser.java @@ -21,13 +21,19 @@ import io.seata.integration.tx.api.remoting.parser.DefaultRemotingParser; import io.seata.spring.util.SpringProxyUtils; import org.springframework.context.ApplicationContext; +import org.springframework.util.Assert; /** * @author leezongjie */ public class RemotingFactoryBeanParser extends AbstractedRemotingParser { - public static ApplicationContext applicationContext; + public ApplicationContext applicationContext; + + public RemotingFactoryBeanParser(ApplicationContext applicationContext) { + Assert.notNull(applicationContext, "applicationContext must not be null"); + this.applicationContext = applicationContext; + } /** * if it is proxy bean, check if the FactoryBean is Remoting bean @@ -36,14 +42,14 @@ public class RemotingFactoryBeanParser extends AbstractedRemotingParser { * @param beanName the bean name * @return boolean boolean */ - protected static Object getRemotingFactoryBean(Object bean, String beanName) { + protected Object getRemotingFactoryBean(Object bean, String beanName) { if (!SpringProxyUtils.isProxy(bean)) { return null; } //the FactoryBean of proxy bean - String factoryBeanName = "&" + beanName; + String factoryBeanName = getFactoryBeanName(beanName); Object factoryBean = null; - if (applicationContext != null && applicationContext.containsBean(factoryBeanName)) { + if (applicationContext.containsBean(factoryBeanName)) { factoryBean = applicationContext.getBean(factoryBeanName); } return factoryBean; @@ -55,7 +61,7 @@ public boolean isReference(Object bean, String beanName) { if (factoryBean == null) { return false; } - return DefaultRemotingParser.get().isReference(bean, beanName); + return DefaultRemotingParser.get().isReference(factoryBean, getFactoryBeanName(beanName)); } @Override @@ -64,7 +70,7 @@ public boolean isService(Object bean, String beanName) { if (factoryBean == null) { return false; } - return DefaultRemotingParser.get().isReference(bean, beanName); + return DefaultRemotingParser.get().isService(factoryBean, getFactoryBeanName(beanName)); } @Override @@ -73,12 +79,16 @@ public RemotingDesc getServiceDesc(Object bean, String beanName) throws Framewor if (factoryBean == null) { return null; } - return DefaultRemotingParser.get().getServiceDesc(bean, beanName); + return DefaultRemotingParser.get().getServiceDesc(factoryBean, getFactoryBeanName(beanName)); } + private String getFactoryBeanName(String beanName) { + return "&" + beanName; + } @Override public short getProtocol() { return 0; } + } \ No newline at end of file diff --git a/spring/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java b/spring/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java index 130e3cad82e..2eb5acb8430 100644 --- a/spring/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java +++ b/spring/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java @@ -103,7 +103,7 @@ public void addTccAdvise(Object bean, String beanName, Field field, Class servic RemotingDesc remotingDesc = new RemotingDesc(); remotingDesc.setServiceClass(serviceClass); - Object proxyBean = ProxyUtil.createProxy(bean); + Object proxyBean = ProxyUtil.createProxy(bean, beanName); field.setAccessible(true); field.set(bean, proxyBean); LOGGER.info("Bean[" + bean.getClass().getName() + "] with name [" + field.getName() + "] would use proxy"); diff --git a/spring/src/main/resources/META-INF/services/io.seata.integration.tx.api.remoting.RemotingParser b/spring/src/main/resources/META-INF/services/io.seata.integration.tx.api.remoting.RemotingParser deleted file mode 100644 index 3de6f0e864d..00000000000 --- a/spring/src/main/resources/META-INF/services/io.seata.integration.tx.api.remoting.RemotingParser +++ /dev/null @@ -1 +0,0 @@ -io.seata.spring.remoting.parser.RemotingFactoryBeanParser \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParser.java b/tcc/src/main/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParser.java index 21434431e90..c6ef74fde6e 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParser.java +++ b/tcc/src/main/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParser.java @@ -37,13 +37,13 @@ public class TccActionInterceptorParser implements InterfaceParser { @Override - public ProxyInvocationHandler parserInterfaceToProxy(Object target) { - boolean isTxRemotingBean = TxBeanParserUtils.isTxRemotingBean(target, target.toString()); + public ProxyInvocationHandler parserInterfaceToProxy(Object target, String objectName) { + boolean isTxRemotingBean = TxBeanParserUtils.isTxRemotingBean(target, objectName); if (isTxRemotingBean) { RemotingDesc remotingDesc = DefaultRemotingParser.get().getRemotingBeanDesc(target); if (remotingDesc != null) { if (remotingDesc.isService()) { - DefaultResourceRegisterParser.get().registerResource(target); + DefaultResourceRegisterParser.get().registerResource(target, objectName); } if (remotingDesc.isReference()) { //if it is a tcc remote reference diff --git a/tcc/src/main/java/io/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java b/tcc/src/main/java/io/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java index f12fc2dedfa..fe99db93304 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java +++ b/tcc/src/main/java/io/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java @@ -41,8 +41,8 @@ public class TccRegisterResourceParser implements RegisterResourceParser { @Override - public void registerResource(Object target) { - boolean isTxRemotingBean = TxBeanParserUtils.isTxRemotingBean(target, target.toString()); + public void registerResource(Object target, String beanName) { + boolean isTxRemotingBean = TxBeanParserUtils.isTxRemotingBean(target, beanName); if (isTxRemotingBean) { RemotingDesc remotingDesc = DefaultRemotingParser.get().getRemotingBeanDesc(target); if (remotingDesc != null) { diff --git a/tcc/src/test/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java b/tcc/src/test/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java index e57dfc7c4f6..1fdac97965c 100644 --- a/tcc/src/test/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java +++ b/tcc/src/test/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java @@ -33,7 +33,7 @@ void parserInterfaceToProxy() { NormalTccActionImpl tccAction = new NormalTccActionImpl(); //when - ProxyInvocationHandler proxyInvocationHandler = tccActionInterceptorParser.parserInterfaceToProxy(tccAction); + ProxyInvocationHandler proxyInvocationHandler = tccActionInterceptorParser.parserInterfaceToProxy(tccAction, tccAction.getClass().getName()); //then Assertions.assertNotNull(proxyInvocationHandler); From 3e9a46ef88673f889350910f616638b995d41189 Mon Sep 17 00:00:00 2001 From: leezongjie Date: Thu, 16 Nov 2023 17:42:21 +0800 Subject: [PATCH 2/2] bugfix: fix hsf isReference bug (#6033) --- changes/en-us/2.0.0.md | 1 + changes/zh-cn/2.0.0.md | 1 + .../integration/tx/api/remoting/parser/HSFRemotingParser.java | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/changes/en-us/2.0.0.md b/changes/en-us/2.0.0.md index 49ee6f02f5d..6f565947176 100644 --- a/changes/en-us/2.0.0.md +++ b/changes/en-us/2.0.0.md @@ -90,6 +90,7 @@ The version is updated as follows: - [[#6015](https://github.com/seata/seata/pull/6015)] fix can't integrate dubbo with spring ### optimize: +- [[#6033](https://github.com/seata/seata/pull/6033)] optimize the isReference judgment logic in HSFRemotingParser, remove unnecessary judgment about FactoryBean - [[#5966](https://github.com/seata/seata/pull/5966)] decouple saga expression handling and remove evaluator package - [[#5928](https://github.com/seata/seata/pull/5928)] add Saga statelang semantic validation - [[#5208](https://github.com/seata/seata/pull/5208)] optimize throwable getCause once more diff --git a/changes/zh-cn/2.0.0.md b/changes/zh-cn/2.0.0.md index 73012f63a0d..ef63a7db76c 100644 --- a/changes/zh-cn/2.0.0.md +++ b/changes/zh-cn/2.0.0.md @@ -90,6 +90,7 @@ Seata 是一款开源的分布式事务解决方案,提供高性能和简单 ### optimize: +- [[#6033](https://github.com/seata/seata/pull/6033)] 优化HSFRemotingParser中isReference判断逻辑,去掉关于FactoryBean的无用判断 - [[#5966](https://github.com/seata/seata/pull/5966)] Saga 表达式解耦并统一格式 - [[#5928](https://github.com/seata/seata/pull/5928)] 增加Saga模式状态机语义验证阶段 - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 diff --git a/integration-tx-api/src/main/java/io/seata/integration/tx/api/remoting/parser/HSFRemotingParser.java b/integration-tx-api/src/main/java/io/seata/integration/tx/api/remoting/parser/HSFRemotingParser.java index 1b56961ceed..8a6c54bda4c 100644 --- a/integration-tx-api/src/main/java/io/seata/integration/tx/api/remoting/parser/HSFRemotingParser.java +++ b/integration-tx-api/src/main/java/io/seata/integration/tx/api/remoting/parser/HSFRemotingParser.java @@ -55,7 +55,7 @@ public boolean isRemoting(Object bean, String beanName) { @Override public boolean isReference(Object bean, String beanName) { String beanClassName = bean.getClass().getName(); - return isHsf && ("com.taobao.hsf.app.spring.util.HSFSpringConsumerBean".equals(beanClassName) || "org.springframework.beans.factory.FactoryBean".equals(beanClassName)); + return isHsf && "com.taobao.hsf.app.spring.util.HSFSpringConsumerBean".equals(beanClassName); } @Override