Skip to content
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

解决AdviceListener半路执行了after却没先执行before的问题,具体表现有:#cost计算错误 #2959

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

trytocatch
Copy link

@trytocatch trytocatch commented Nov 25, 2024

fix #2958
fix #2565

在进方法时,记录有哪些AdviceListener被执行,在出方法时,以记录的AdviceListener为基础,再执行skipAdviceListener过滤,从而保证执行after时,一定执行过before,从而解决目前计算cost等依赖于进出栈而造成的问题。

此方案并没有解决目前存在的有before没有after的问题,针对此问题,目前的代码是兼容了这一情况的,故暂不处理,后续可对这块逻辑进行重新设计,从根本上解决问题

如果代码增强可以在方法前后添加同一个局部变量,那么可以在直接记录哪些AdviceListener被执行过,但是发现bytekit目前并不支持这样做,没法将前后串起来,InstrumentApi.invokeOrigin()又只能用在事先编写好的特定Method,而不是按条件去匹配Method,所以将信息记录到ThreadLocal中的一个ArrayList中,来模拟栈上的局部变量

该方案的正确性依赖于代码增强的atEnter和atExit是配对执行的,目前通过测试验证来看是成立的,另外,不太可能在方法执行一半,然后方法被增强了,然后执行了atExit,这样不太合理,也不好确定新方法执行的起点,因为已经修改过了,所以,该假设应该是成立的。

需要注意的是,后续修改atExit等方法时,不要抛出异常,否则会出现执行了atExit的部分代码,然后又执行了atExceptionExit的代码,导致重复执行(通过分析bytekit生成的增强代码推断得出),这是目前便存在的小隐患,如果要处理的话,可以调整bytekit生成的代码位置,比如将atExit的代码插入到atExceptionExit的try-catch的后面去,而不是放在里面,atExceptionExit仅处理原始方法的异常可能更合理,像atEnter就没有包含在此try-catch之内

差异:

原来多个AdviceListener的执行顺序是

1
2
3
原始方法
1
2
3

使用本方案之后:

1
2
3
原始方法
3
2
1

感觉这样更合理,符合一般的切面执行顺序,故不再完全遵循原来的顺序

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant