docs: public void visitAroundMethod(Object declaringType,
                                    Object returnType,
                                    Object genericReturnType,
                                    Map<String, Object> returnTypeGenericTypes,
                                    String methodName,
                                    Map<String, Object> argumentTypes,
                                    Map<String, AnnotationMetadata> argumentAnnotationMetadata,
                                    Map<String, Map<String, Object>> genericTypes,
                                    AnnotationMetadata annotationMetadata) {
  
          // to make dispatch to this method more efficient and annotation metadata accurate also generate an executable method
          visitExecutableMethod(
              declaringType,
              returnType,
              genericReturnType,
              returnTypeGenericTypes,
              methodName,
              argumentTypes,
              argumentAnnotationMetadata,
              genericTypes,
              annotationMetadata);
  
          List<Object> argumentTypeList = new ArrayList<>(argumentTypes.values());
          int argumentCount = argumentTypes.size();
          Type returnTypeObject = getTypeReference(returnType);
          boolean isPrimitive = isPrimitive(returnType);
          boolean isVoidReturn = isPrimitive && returnTypeObject.equals(Type.VOID_TYPE);
          final Type declaringTypeReference = getTypeReference(declaringType);
          MethodRef methodKey = new MethodRef(methodName, argumentTypeList, returnTypeObject);
          if (isProxyTarget) {
              // if the target class is being proxied then the method will be looked up from the parent bean definition.
              // Therefore no need to generate a bridge
              if (!proxyTargetMethods.contains(methodKey)) {
                  int index = proxyMethodCount++;
                  proxyTargetMethods.add(methodKey);
                  buildMethodOverride(returnType, methodName, index, argumentTypeList, argumentCount, isVoidReturn);
              }
          } else if (!proxiedMethodsRefSet.contains(methodKey)) {
              int index = proxyMethodCount++;
              // if the target is not being proxied then we generate a subclass where only the proxied methods are overridden
              // Each overridden method calls super.blah(..) thus maintaining class semantics better and providing smaller more efficient
              // proxies
  
              String methodProxyShortName = "$$proxy" + index;
              String bridgeName = "$$access" + index;
              String methodExecutorClassName = proxyFullName + methodProxyShortName;
  
              List<Object> bridgeArguments = new ArrayList<>();
              bridgeArguments.add(proxyFullName);
              bridgeArguments.addAll(argumentTypeList);
              String bridgeDesc = getMethodDescriptor(returnType, bridgeArguments);
  
              ExecutableMethodWriter executableMethodWriter = new ExecutableMethodWriter(
                  proxyFullName, methodExecutorClassName, methodProxyShortName, isInterface, annotationMetadata) {
                  @Override
                  protected void buildInvokeMethod(Type declaringTypeObject, String methodName, Object returnType, Collection<Object> argumentTypes, GeneratorAdapter invokeMethodVisitor) {
                      // load this
                      invokeMethodVisitor.loadThis();
                      // first argument to static bridge is reference to parent
                      invokeMethodVisitor.getField(methodType, FIELD_PARENT, proxyType);
                      // now remaining arguments
                      for (int i = 0; i < argumentTypeList.size(); i++) {
                          invokeMethodVisitor.loadArg(1);
                          invokeMethodVisitor.push(i);
                          invokeMethodVisitor.visitInsn(AALOAD);
                          AopProxyWriter.pushCastToType(invokeMethodVisitor, argumentTypeList.get(i));
                      }
                      invokeMethodVisitor.visitMethodInsn(INVOKESTATIC, proxyInternalName, bridgeName, bridgeDesc, false);
                      if (isVoidReturn) {
                          invokeMethodVisitor.visitInsn(ACONST_NULL);
                      } else {
                          AopProxyWriter.pushBoxPrimitiveIfNecessary(returnType, invokeMethodVisitor);
                      }
                      invokeMethodVisitor.visitInsn(ARETURN);
                      invokeMethodVisitor.visitMaxs(AbstractClassFileWriter.DEFAULT_MAX_STACK, 1);
                      invokeMethodVisitor.visitEnd();
                  }
  
              };
              executableMethodWriter.makeInner(proxyInternalName, classWriter);
              executableMethodWriter.visitMethod(declaringType, returnType, genericReturnType, returnTypeGenericTypes, methodName, argumentTypes, argumentAnnotationMetadata, genericTypes);
  
              proxiedMethods.add(executableMethodWriter);
              proxiedMethodsRefSet.add(methodKey);
              String overrideDescriptor = buildMethodOverride(returnType, methodName, index, argumentTypeList, argumentCount, isVoidReturn);
  
              // now build a bridge to invoke the original method
              MethodVisitor bridgeWriter = classWriter.visitMethod(ACC_STATIC | ACC_SYNTHETIC,
                  bridgeName, bridgeDesc, null, null);
              GeneratorAdapter bridgeGenerator = new GeneratorAdapter(bridgeWriter, ACC_STATIC + ACC_SYNTHETIC, bridgeName, bridgeDesc);
              for (int i = 0; i < bridgeArguments.size(); i++) {
                  bridgeGenerator.loadArg(i);
              }
  
              bridgeWriter.visitMethodInsn(INVOKESPECIAL, declaringTypeReference.getInternalName(), methodName, overrideDescriptor, false);
              pushReturnValue(bridgeWriter, returnType);
              bridgeWriter.visitMaxs(DEFAULT_MAX_STACK, 1);
              bridgeWriter.visitEnd();
          }
      }