diff --git a/arex-instrumentation/dynamic/arex-dynamic/src/main/java/io/arex/inst/dynamic/DynamicClassInstrumentation.java b/arex-instrumentation/dynamic/arex-dynamic/src/main/java/io/arex/inst/dynamic/DynamicClassInstrumentation.java index 361abc5ad..399aca301 100644 --- a/arex-instrumentation/dynamic/arex-dynamic/src/main/java/io/arex/inst/dynamic/DynamicClassInstrumentation.java +++ b/arex-instrumentation/dynamic/arex-dynamic/src/main/java/io/arex/inst/dynamic/DynamicClassInstrumentation.java @@ -85,7 +85,6 @@ public List methodAdvices() { ElementMatcher.Junction matcher = null; if (onlyClass != null) { matcher = isMethod().and(not(takesNoArguments())) - .and(not(returns(TypeDescription.VOID))) .and(not(isAnnotatedWith(namedOneOf(DynamiConstants.SPRING_CACHE, DynamiConstants.AREX_MOCK)))); if (isNotAbstractClass(onlyClass.getClazzName())) { matcher = matcher.and(not(isOverriddenFrom(namedOneOf(Config.get().getDynamicAbstractClassList())))); @@ -108,7 +107,6 @@ public List methodAdvices() { private ElementMatcher.Junction builderMethodMatcher(DynamicClassEntity entity) { ElementMatcher.Junction matcher = parseTypeMatcher(entity.getOperation(), this::parseMethodMatcher) - .and(not(returns(TypeDescription.VOID))) .and(not(isAnnotatedWith(namedOneOf(DynamiConstants.SPRING_CACHE, DynamiConstants.AREX_MOCK)))); if (CollectionUtil.isNotEmpty(entity.getParameters())) { matcher = matcher.and(takesArguments(entity.getParameters().size())); @@ -126,19 +124,26 @@ public static boolean onEnter(@Advice.Origin Method method, @Advice.AllArguments Object[] args, @Advice.Local("extractor") DynamicClassExtractor extractor, @Advice.Local("mockResult") MockResult mockResult) { + if (ContextManager.needRecord()) { + RepeatedCollectManager.enter(); + } if (ContextManager.needRecordOrReplay()) { + if (void.class.isAssignableFrom(method.getReturnType())) { + return ContextManager.needReplay(); + } extractor = new DynamicClassExtractor(method, args); } if (ContextManager.needReplay()) { mockResult = extractor.replay(); return mockResult != null && mockResult.notIgnoreMockResult(); } - if (ContextManager.needRecord()) { - RepeatedCollectManager.enter(); - } return false; } + /** + * void method will not record because of extractor == null + * when replay, just return; + */ @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void onExit(@Advice.Local("extractor") DynamicClassExtractor extractor, @Advice.Local("mockResult") MockResult mockResult, diff --git a/arex-instrumentation/dynamic/arex-dynamic/src/test/java/io/arex/inst/dynamic/DynamicClassInstrumentationTest.java b/arex-instrumentation/dynamic/arex-dynamic/src/test/java/io/arex/inst/dynamic/DynamicClassInstrumentationTest.java index b49d73867..598160f6a 100644 --- a/arex-instrumentation/dynamic/arex-dynamic/src/test/java/io/arex/inst/dynamic/DynamicClassInstrumentationTest.java +++ b/arex-instrumentation/dynamic/arex-dynamic/src/test/java/io/arex/inst/dynamic/DynamicClassInstrumentationTest.java @@ -132,14 +132,14 @@ static Stream methodAdvicesCase() { DynamicClassEntity emptyOperation = new DynamicClassEntity("io.arex.inst.dynamic.DynamicTestClass", "", "", ""); Predicate> emptyOperationPredicate = methodAdvices -> { ElementMatcher matcher = methodAdvices.get(0).getMethodMatcher(); - return methodAdvices.size() == 1 && matchedMethodCount(matcher, DynamicTestClass.class) == 2; + return methodAdvices.size() == 1 && matchedMethodCount(matcher, DynamicTestClass.class) == 3; }; DynamicClassEntity testReturnVoidEntity = new DynamicClassEntity("io.arex.inst.dynamic.DynamicTestClass", "testReturnVoid", "", ""); DynamicClassEntity testReturnVoidWithParameterEntity = new DynamicClassEntity("io.arex.inst.dynamic.DynamicTestClass", "testReturnVoidWithParameter", "java.lang.String", "java.lang.System.currentTimeMillis"); Predicate> emptyOperationAndVoidPredicate = methodAdvices -> { ElementMatcher matcher = methodAdvices.get(0).getMethodMatcher(); - return methodAdvices.size() == 1 && matchedMethodCount(matcher, DynamicTestClass.class) == 0; + return methodAdvices.size() == 1 && matchedMethodCount(matcher, DynamicTestClass.class) == 1; }; DynamicClassEntity testReturnNonPrimitiveTypeWithParameterEntity = new DynamicClassEntity("io.arex.inst.dynamic.DynamicTestClass", "testReturnNonPrimitiveTypeWithParameter", "java.lang.String", null); @@ -150,6 +150,10 @@ static Stream methodAdvicesCase() { }; DynamicClassEntity testReturnWithParameterWildcard = new DynamicClassEntity("io.arex.inst.dynamic.DynamicTestClass", "*WithParameter*,testReturnVoid*,*WithParameter", "", null); + Predicate> operationWithParameterWildcardPredicate = methodAdvices -> { + ElementMatcher matcher = methodAdvices.get(0).getMethodMatcher(); + return methodAdvices.size() == 1 && matchedMethodCount(matcher, DynamicTestClass.class) == 4; + }; final DynamicClassEntity testReturnNonPrimitiveType = new DynamicClassEntity( "io.arex.inst.dynamic.DynamicTestClass", "testReturnNonPrimitiveType", "", @@ -157,10 +161,10 @@ static Stream methodAdvicesCase() { Predicate> emptyListPredicate = List::isEmpty; return Stream.of( - arguments("should_match_2_methods_when_empty_operation", Collections.singletonList(emptyOperation), NOT_EMPTY_PREDICATE.and(emptyOperationPredicate)), - arguments("should_match_0_method_when_with_return_void", Arrays.asList(testReturnVoidEntity, testReturnVoidWithParameterEntity), NOT_EMPTY_PREDICATE.and(emptyOperationAndVoidPredicate)), + arguments("should_match_3_methods_when_empty_operation", Collections.singletonList(emptyOperation), NOT_EMPTY_PREDICATE.and(emptyOperationPredicate)), + arguments("should_match_1_method_when_with_return_void", Arrays.asList(testReturnVoidEntity, testReturnVoidWithParameterEntity), NOT_EMPTY_PREDICATE.and(emptyOperationAndVoidPredicate)), arguments("should_match_2_method_when_with_parameter", Arrays.asList(testReturnNonPrimitiveTypeWithParameterEntity, testReturnPrimitiveTypeWithParameter), NOT_EMPTY_PREDICATE.and(operationWithParameterPredicate)), - arguments("should_match_2_method_when_with_parameter_wildcard", Arrays.asList(testReturnWithParameterWildcard), NOT_EMPTY_PREDICATE.and(operationWithParameterPredicate)), + arguments("should_match_4_method_when_with_parameter_wildcard", Arrays.asList(testReturnWithParameterWildcard), NOT_EMPTY_PREDICATE.and(operationWithParameterWildcardPredicate)), arguments("should_match_0_method_when_with_replace_uuid", Collections.singletonList(testReturnNonPrimitiveType), emptyListPredicate) ); }