docs: @Override
      protected void createForwardingMethodBody(ClassMethod classMethod, final MethodInformation methodInfo, ClassMethod staticConstructor) {
          final Method method = methodInfo.getMethod();
          // we can only use bytecode based invocation for some methods
          // at the moment we restrict it solely to public methods with public
          // return and parameter types
          boolean bytecodeInvocationAllowed = Modifier.isPublic(method.getModifiers()) && Modifier.isPublic(method.getReturnType().getModifiers());
          for (Class<?> paramType : method.getParameterTypes()) {
              if (!Modifier.isPublic(paramType.getModifiers())) {
                  bytecodeInvocationAllowed = false;
                  break;
              }
          }
          if (!bytecodeInvocationAllowed) {
              createInterceptorBody(classMethod, methodInfo, staticConstructor);
              return;
          }
  
          // create a new interceptor invocation context whenever we invoke a method on a client proxy
          // we use a try-catch block in order to make sure that endInterceptorContext() is invoked regardless whether
          // the method has succeeded or not
  
          new RunWithinInterceptionDecorationContextGenerator(classMethod, this) {
  
              @Override
              void doWork(CodeAttribute b, ClassMethod classMethod) {
                  loadBeanInstance(classMethod.getClassFile(), methodInfo, b);
                  //now we should have the target bean instance on top of the stack
                  // we need to dup it so we still have it to compare to the return value
                  b.dup();
  
                  //lets create the method invocation
                  String methodDescriptor = methodInfo.getDescriptor();
                  b.loadMethodParameters();
                  if (method.getDeclaringClass().isInterface()) {
                      b.invokeinterface(methodInfo.getDeclaringClass(), methodInfo.getName(), methodDescriptor);
                  } else {
                      b.invokevirtual(methodInfo.getDeclaringClass(), methodInfo.getName(), methodDescriptor);
                  }
              }
  
              @Override
              void doReturn(CodeAttribute b, ClassMethod classMethod) {
                  // assumes doWork() result is on top of the stack
                  // if this method returns a primitive we just return
                  if (method.getReturnType().isPrimitive()) {
                      b.returnInstruction();
                  } else {
                      // otherwise we have to check that the proxy is not returning 'this;
                      // now we need to check if the proxy has return 'this' and if so return
                      // an
                      // instance of the proxy.
                      // currently we have result, beanInstance on the stack.
                      b.dupX1();
                      // now we have result, beanInstance, result
                      // we need to compare result and beanInstance
  
                      // first we need to build up the inner conditional that just returns
                      // the
                      // result
                      final BranchEnd returnInstruction = b.ifAcmpeq();
                      b.returnInstruction();
                      b.branchEnd(returnInstruction);
  
                      // now add the case where the proxy returns 'this';
                      b.aload(0);
                      b.checkcast(methodInfo.getMethod().getReturnType().getName());
                      b.returnInstruction();
                  }
              }
          }.runStartIfNotEmpty();
      }