-
Notifications
You must be signed in to change notification settings - Fork 8.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
optimize: branch register resource only at RM server end #5399
Changes from 7 commits
8d2e41a
505f7c5
61aae61
968c8d0
bb1a55c
4c3875d
7cbf600
543eb5a
ddaaa91
26dc039
38361ba
5cca5c4
d98f3ab
daeaafc
002935e
e56a8b2
fa6e3bf
c42030e
22455a3
e6c90fe
80b175e
43f0bcc
b34ae57
f4030a5
3ec392b
c3ffb17
1da082e
bfa742a
93b32cf
8c23358
e5cfe2c
6719fe7
83e4dae
78c7121
378fc00
2df4c80
95c6903
057c581
3055c18
79288d6
076a8fc
a0fbe96
967bfd6
5af4071
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,21 +15,21 @@ | |
*/ | ||
package io.seata.rm.tcc.interceptor.parser; | ||
|
||
import java.lang.reflect.Field; | ||
import java.lang.reflect.InvocationHandler; | ||
import java.lang.reflect.Method; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.HashSet; | ||
import java.util.Set; | ||
|
||
import io.seata.common.util.ReflectionUtil; | ||
import io.seata.integration.tx.api.interceptor.TxBeanParserUtils; | ||
import io.seata.integration.tx.api.interceptor.handler.ProxyInvocationHandler; | ||
import io.seata.integration.tx.api.interceptor.parser.DefaultResourceRegisterParser; | ||
import io.seata.integration.tx.api.interceptor.parser.InterfaceParser; | ||
import io.seata.integration.tx.api.remoting.RemotingDesc; | ||
import io.seata.integration.tx.api.remoting.parser.DefaultRemotingParser; | ||
import io.seata.rm.tcc.api.TwoPhaseBusinessAction; | ||
import io.seata.rm.tcc.interceptor.TccActionInterceptorHandler; | ||
|
||
import java.lang.reflect.Method; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.HashSet; | ||
import java.util.Set; | ||
import org.springframework.aop.support.AopUtils; | ||
|
||
/** | ||
* @author leezongjie | ||
|
@@ -38,39 +38,46 @@ public class TccActionInterceptorParser implements InterfaceParser { | |
|
||
@Override | ||
public ProxyInvocationHandler parserInterfaceToProxy(Object target) { | ||
boolean isTxRemotingBean = TxBeanParserUtils.isTxRemotingBean(target, target.toString()); | ||
if (isTxRemotingBean) { | ||
RemotingDesc remotingDesc = DefaultRemotingParser.get().getRemotingBeanDesc(target); | ||
if (remotingDesc != null) { | ||
if (remotingDesc.isService()) { | ||
DefaultResourceRegisterParser.get().registerResource(target); | ||
} | ||
if (remotingDesc.isReference()) { | ||
//if it is a tcc remote reference | ||
Set<String> methodsToProxy = tccProxyTargetMethod(remotingDesc); | ||
if (remotingDesc != null && !methodsToProxy.isEmpty()) { | ||
ProxyInvocationHandler proxyInvocationHandler = new TccActionInterceptorHandler(remotingDesc, methodsToProxy); | ||
return proxyInvocationHandler; | ||
} | ||
} | ||
|
||
// below only enhance the native business bean. | ||
// eliminate without two phase annotation bean. | ||
Set<String> methodsToProxy = this.tccProxyTargetMethod(target); | ||
if (methodsToProxy.isEmpty()) { | ||
return null; | ||
} | ||
|
||
// eliminate aop proxy. | ||
if (AopUtils.isAopProxy(target)) { | ||
return null; | ||
} | ||
|
||
// eliminate dubbo etc proxy bean. | ||
Field[] fields = ReflectionUtil.getAllFields(target.getClass()); | ||
for (Field field : fields) { | ||
if (field.getGenericType().equals(InvocationHandler.class)) { | ||
return null; | ||
} | ||
} | ||
return null; | ||
|
||
// register resource and enhance with interceptor | ||
DefaultResourceRegisterParser.get().registerResource(target); | ||
return new TccActionInterceptorHandler(target, methodsToProxy); | ||
} | ||
|
||
/** | ||
* is TCC proxy-bean/target-bean: LocalTCC , the proxy bean of sofa:reference/dubbo:reference | ||
* | ||
* @param remotingDesc the remoting desc | ||
* @param target the target bean | ||
* @return boolean boolean | ||
*/ | ||
private Set<String> tccProxyTargetMethod(RemotingDesc remotingDesc) { | ||
if (!remotingDesc.isReference() || remotingDesc == null) { | ||
|
||
private Set<String> tccProxyTargetMethod(Object target) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How to handle method overloading with the same method name 如何处理方法名相同都标注TwoPhaseBusinessAction注解的方法重载问题。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
这个问题将由后续pr解决 |
||
if (target == null) { | ||
return Collections.emptySet(); | ||
} | ||
Set<String> methodsToProxy = new HashSet<>(); | ||
//check if it is TCC bean | ||
Class<?> tccServiceClazz = remotingDesc.getServiceClass(); | ||
Class<?> tccServiceClazz = target.getClass(); | ||
Set<Method> methods = new HashSet<>(Arrays.asList(tccServiceClazz.getMethods())); | ||
Set<Class<?>> interfaceClasses = ReflectionUtil.getInterfaces(tccServiceClazz); | ||
if (interfaceClasses != null) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the past, the result of being processed by the RPC framework would have been either a Reference Bean or a Service Bean. However, if you are not currently using this RPC framework handling, how do you ensure that the class is not proxy or that the TwoPhaseBusinessAction has the highest priority order?
在过去,被RPC框架处理后,最终得到的结果肯定是Reference Bean或者Service Bean。但是,如果当前不再使用这种RPC框架的处理方式来判断,如何保证这个类没有被代理过或者怎么保证TwoPhaseBusinessAction的切面优先级是最高的?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
之前这种方式确实有问题,不能保证,以下以一种思路:
利用spring 的 bean definition,提前在自动代理前得到各个类的引用关系,从而提前获取依赖关系,保存名字在Set中,然后在AOP自动代理的wrapIfNecessary中,判断是否存在。
在RM端,Set中保存的是 service指向的原生bean的name。
在TM端,Set中保存的是开启事务的bean的name。