Finally I use code below. The critical part is 'parameterDefinitionForNewMethod.intercept(MethodCall.invoke(originalMethod).onSuper().withAllArguments())'. Please search 'parameterDefinition' and 'intercept(MethodCall.invoke(originalMethod).onSuper().withAllArguments())' in code below.
Here 'parameterDefinitionForNewMethod' is the instance of class 'DynamicType.Builder.MethodDefinition.ParameterDefinition<?>'. This instance means the new method 'doGetFieldPredicates(...)' in code below, which is corresponding to the doYyy(...) in the question above.
Here 'originalMethod' means the method 'getFieldPredicates(...)' in code below, which is corresponding to the yyy(...) in the question above.
builder = makeMethodToDelegateTo_ANewAbstractMethodWithOriginalMethodBodyAsDefaultMethodBody(
builder
, getDeclaredMethod(classGraphQLJpaQueryFactory, "getFieldPredicates")
, "field"
, "query"
, "cb"
, "root"
, "from"
, "environment"
);
protected DynamicType.Builder<?> makeMethodToDelegateTo_ANewAbstractMethodWithOriginalMethodBodyAsDefaultMethodBody(DynamicType.Builder<?> builder, Method originalMethod, String... expectedParameterNames) {
return makeMethodDelegateToANewMadeMethodWithMethodBody(
builder
, originalMethod
, it -> it.intercept(MethodCall.invoke(originalMethod).onSuper().withAllArguments())
, expectedParameterNames);
}
protected DynamicType.Builder<?> makeMethodDelegateToANewMadeMethodWithMethodBody(
DynamicType.Builder<?> builder
, Method originalMethod
, Function<DynamicType.Builder.MethodDefinition.ParameterDefinition<?>, DynamicType.Builder<?>> functionToMakeMethodBody
, String... expectedParameterNames) {
final String nameOfDelegatedMethod = appendCapitalizedString(String__do, originalMethod.getName());
DynamicType.Builder.MethodDefinition.ParameterDefinition<?> parameterDefinition
= getParameterDefinitionForMethod(builder, originalMethod, nameOfDelegatedMethod, expectedParameterNames);
builder = functionToMakeMethodBody.apply(parameterDefinition);
builder = makeMethodDelegateToAnotherMethod(builder, originalMethod, nameOfDelegatedMethod);
return builder;
}
protected DynamicType.Builder<?> makeMethodDelegateToAnotherMethod(DynamicType.Builder<?> builder, Method originalMethod, String nameOfNewDelegatedMethod) {
return builder.method(ElementMatchers.is(originalMethod))
.intercept(MethodCall.invoke(ElementMatchers.named(nameOfNewDelegatedMethod)).withAllArguments())
.transform(Transformer.ForMethod.withModifiers(Visibility.PROTECTED, MethodManifestation.FINAL));
}
protected DynamicType.Builder.MethodDefinition.ParameterDefinition<?> getParameterDefinitionForMethod(DynamicType.Builder<?> builder, Method methodForSignatureReferredTo, String nameOfNewDelegatedMethod, String[] expectedParameterNames) {
final Parameter[] methodParameters = methodForSignatureReferredTo.getParameters();
if (expectedParameterNames.length != 0 && expectedParameterNames.length != methodParameters.length) {
throw new IllegalArgumentException("expectedParameterNames's length is '" + expectedParameterNames.length
+ "', not zero and not equals to Method '" + methodForSignatureReferredTo.getName() + "' 's parameter length '" + methodParameters.length + "'.");
}
DynamicType.Builder.MethodDefinition.ParameterDefinition<?> parameterDefinition = builder.defineMethod(nameOfNewDelegatedMethod, methodForSignatureReferredTo.getGenericReturnType(), Visibility.PROTECTED);
for (int i = 0; i < methodParameters.length; i++) {
String parameterName = expectedParameterNames.length != 0 ? expectedParameterNames[i] : methodParameters[i].getName();
parameterDefinition = parameterDefinition.withParameter(methodParameters[i].getParameterizedType(), parameterName);
}
return parameterDefinition;
}
After the class is rebased, the method bodies are like code below, where 'doGetFieldPredicates(...)' is corresonding to the 'doYyy(...)' in question above. The 'doGetFieldPredicates(...)' invoke the original body of 'getFieldPredicates(...)' and can be overridden by sub class.
public final List<Predicate> getFieldPredicates(Field var1, CriteriaQuery<?> var2, CriteriaBuilder var3, Root<?> var4, From<?, ?> var5, DataFetchingEnvironment var6) {
return this.doGetFieldPredicates(var1, var2, var3, var4, var5, var6);
}
protected List<Predicate> doGetFieldPredicates(Field field, CriteriaQuery<?> query, CriteriaBuilder cb, Root<?> root, From<?, ?> from, DataFetchingEnvironment environment) {
return this.getFieldPredicates$original$ntjCvAEf(var1, var2, var3, var4, var5, var6);
}