如何在Byte Buddy的帮助下增强最终的非Interface类

问题描述 投票:0回答:1

背景: 我的程序使用gRPC进行通信。现在有一些特殊的clints(或存根),我想做一些逻辑(发送Mq消息或将其恢复到数据库中,等等~~)

问题:

public static final class SmsProxyAPIStub extends io.grpc.stub.AbstractAsyncStub<SmsProxyAPIStub> {
    private SmsProxyAPIStub(
        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
      super(channel, callOptions);
    }

    @java.lang.Override
    protected SmsProxyAPIStub build(
        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
      return new SmsProxyAPIStub(channel, callOptions);
    }

    /**
     */
    public void sendSmsMessage1(ird.ntp.be.sms.proto.SendSmsMessageRequest request,
        io.grpc.stub.StreamObserver<ird.ntp.be.sms.proto.SendSmsMessageResponse> responseObserver) {
      io.grpc.stub.ClientCalls.asyncUnaryCall(
          getChannel().newCall(getSendSmsMessageMethod(), getCallOptions()), request, responseObserver);

public void sendSmsMessage2(ird.ntp.be.sms.proto.SendSmsMessageRequest request,
        io.grpc.stub.StreamObserver<ird.ntp.be.sms.proto.SendSmsMessageResponse> responseObserver) {
      io.grpc.stub.ClientCalls.asyncUnaryCall(
          getChannel().newCall(getSendSmsMessageMethod(), getCallOptions()), request, responseObserver);
    }
  }

客户端类是final修饰的,没有实现任何接口,那我就得选择Byte Buddy(我不熟悉,我的任务已经超时了。)

我试过了:

   new ByteBuddy()
                    .rebase(SmsProxyAPIGrpc.class)
                            .constructor(ElementMatchers.isPrivate()) // 选择 private 构造函数
                            .intercept(
                                    MethodCall.invoke(
                                            originalClass.getDeclaredConstructor(Channel.class, CallOptions.class))
                                            .with(channel,callOptions)
                            ) // 调用带参数的原始类构造函
                    .method(ElementMatchers.nameContains("sendSmsMessage"))
                    .intercept(MethodDelegation.to(MonitorDemo.class))
                    .make()
                    .load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
                    .getLoaded();

但生成的代码确实包含我的增强逻辑, 但当我

Constructor<?> constructor = type.getDeclaredConstructor(Channel.class, CallOptions.class).setAccessible(true);
constructor.newInstance(channel,callOptions);

它让我得到“java.lang.reflect.InitationTargetException:由:ird.ntp.be.sms.proto.SmsProxyAPIGrpc$SmsProxyAPIBlockingStub.(SmsProxyAPIGrpc.java)处的java.lang.StackOverflowError引起”

我想增强SmsProxyAPIGrpc.SmsProxyAPIBlockingStub:

@javax.annotation.Generated(
  value = "by gRPC proto compiler (version 1.51.1)",
  comments = "Source: ProxyAPI.proto")
@io.grpc.stub.annotations.GrpcGenerated
public final class SmsProxyAPIGrpc {

private SmsProxyAPIGrpc() {}

public static final String SERVICE_NAME = "ird.ntp.be.sms.v1.SmsProxyAPI";

// Static method descriptors that strictly reflect the proto.
private static volatile io.grpc.MethodDescriptor<ird.ntp.be.sms.proto.SendSmsMessageRequest,
    ird.ntp.be.sms.proto.SendSmsMessageResponse> getSendSmsMessageMethod;

@io.grpc.stub.annotations.RpcMethod(
    fullMethodName = SERVICE_NAME + '/' + "SendSmsMessage",
    requestType = ird.ntp.be.sms.proto.SendSmsMessageRequest.class,
    responseType = ird.ntp.be.sms.proto.SendSmsMessageResponse.class,
    methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
public static io.grpc.MethodDescriptor<ird.ntp.be.sms.proto.SendSmsMessageRequest,
    ird.ntp.be.sms.proto.SendSmsMessageResponse> getSendSmsMessageMethod() {
  io.grpc.MethodDescriptor<ird.ntp.be.sms.proto.SendSmsMessageRequest, ird.ntp.be.sms.proto.SendSmsMessageResponse> getSendSmsMessageMethod;
  if ((getSendSmsMessageMethod = SmsProxyAPIGrpc.getSendSmsMessageMethod) == null) {
    synchronized (SmsProxyAPIGrpc.class) {
      if ((getSendSmsMessageMethod = SmsProxyAPIGrpc.getSendSmsMessageMethod) == null) {
        SmsProxyAPIGrpc.getSendSmsMessageMethod = getSendSmsMessageMethod =
            io.grpc.MethodDescriptor.<ird.ntp.be.sms.proto.SendSmsMessageRequest, ird.ntp.be.sms.proto.SendSmsMessageResponse>newBuilder()
            .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
            .setFullMethodName(generateFullMethodName(SERVICE_NAME, "SendSmsMessage"))
            .setSampledToLocalTracing(true)
            .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
                ird.ntp.be.sms.proto.SendSmsMessageRequest.getDefaultInstance()))
            .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
                ird.ntp.be.sms.proto.SendSmsMessageResponse.getDefaultInstance()))
            .setSchemaDescriptor(new SmsProxyAPIMethodDescriptorSupplier("SendSmsMessage"))
            .build();
      }
    }
  }
  return getSendSmsMessageMethod;
}

/**
 * Creates a new async stub that supports all call types for the service
 */
public static SmsProxyAPIStub newStub(io.grpc.Channel channel) {
  io.grpc.stub.AbstractStub.StubFactory<SmsProxyAPIStub> factory =
    new io.grpc.stub.AbstractStub.StubFactory<SmsProxyAPIStub>() {
      @java.lang.Override
      public SmsProxyAPIStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
        return new SmsProxyAPIStub(channel, callOptions);
      }
    };
  return SmsProxyAPIStub.newStub(factory, channel);
}

/**
 * Creates a new blocking-style stub that supports unary and streaming output calls on the service
 */
public static SmsProxyAPIBlockingStub newBlockingStub(
    io.grpc.Channel channel) {
  io.grpc.stub.AbstractStub.StubFactory<SmsProxyAPIBlockingStub> factory =
    new io.grpc.stub.AbstractStub.StubFactory<SmsProxyAPIBlockingStub>() {
      @java.lang.Override
      public SmsProxyAPIBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
        return new SmsProxyAPIBlockingStub(channel, callOptions);
      }
    };
  return SmsProxyAPIBlockingStub.newStub(factory, channel);
}

/**
 * Creates a new ListenableFuture-style stub that supports unary calls on the service
 */
public static SmsProxyAPIFutureStub newFutureStub(
    io.grpc.Channel channel) {
  io.grpc.stub.AbstractStub.StubFactory<SmsProxyAPIFutureStub> factory =
    new io.grpc.stub.AbstractStub.StubFactory<SmsProxyAPIFutureStub>() {
      @java.lang.Override
      public SmsProxyAPIFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
        return new SmsProxyAPIFutureStub(channel, callOptions);
      }
    };
  return SmsProxyAPIFutureStub.newStub(factory, channel);
}

/**
 * <pre>
 * API interface and its request/response messages
 * </pre>
 */
public static abstract class SmsProxyAPIImplBase implements io.grpc.BindableService {

  /**
   */
  public void sendSmsMessage(ird.ntp.be.sms.proto.SendSmsMessageRequest request,
      io.grpc.stub.StreamObserver<ird.ntp.be.sms.proto.SendSmsMessageResponse> responseObserver) {
    io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getSendSmsMessageMethod(), responseObserver);
  }

  @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
    return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
        .addMethod(
          getSendSmsMessageMethod(),
          io.grpc.stub.ServerCalls.asyncUnaryCall(
            new MethodHandlers<
              ird.ntp.be.sms.proto.SendSmsMessageRequest,
              ird.ntp.be.sms.proto.SendSmsMessageResponse>(
                this, METHODID_SEND_SMS_MESSAGE)))
        .build();
  }
}

/**
 * <pre>
 * API interface and its request/response messages
 * </pre>
 */
public static final class SmsProxyAPIStub extends io.grpc.stub.AbstractAsyncStub<SmsProxyAPIStub> {
  private SmsProxyAPIStub(
      io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
    super(channel, callOptions);
  }

  @java.lang.Override
  protected SmsProxyAPIStub build(
      io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
    return new SmsProxyAPIStub(channel, callOptions);
  }

  /**
   */
  public void sendSmsMessage(ird.ntp.be.sms.proto.SendSmsMessageRequest request,
      io.grpc.stub.StreamObserver<ird.ntp.be.sms.proto.SendSmsMessageResponse> responseObserver) {
    io.grpc.stub.ClientCalls.asyncUnaryCall(
        getChannel().newCall(getSendSmsMessageMethod(), getCallOptions()), request, responseObserver);
  }
}

/**
 * <pre>
 * API interface and its request/response messages
 * </pre>
 */
public static final class SmsProxyAPIBlockingStub extends io.grpc.stub.AbstractBlockingStub<SmsProxyAPIBlockingStub> {
  private SmsProxyAPIBlockingStub(
      io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
    super(channel, callOptions);
  }

  @java.lang.Override
  protected SmsProxyAPIBlockingStub build(
      io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
    return new SmsProxyAPIBlockingStub(channel, callOptions);
  }

  /**
   */
  public ird.ntp.be.sms.proto.SendSmsMessageResponse sendSmsMessage(ird.ntp.be.sms.proto.SendSmsMessageRequest request) {
    return io.grpc.stub.ClientCalls.blockingUnaryCall(
        getChannel(), getSendSmsMessageMethod(), getCallOptions(), request);
  }
}

/**
 * <pre>
 * API interface and its request/response messages
 * </pre>
 */
public static final class SmsProxyAPIFutureStub extends io.grpc.stub.AbstractFutureStub<SmsProxyAPIFutureStub> {
  private SmsProxyAPIFutureStub(
      io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
    super(channel, callOptions);
  }

  @java.lang.Override
  protected SmsProxyAPIFutureStub build(
      io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
    return new SmsProxyAPIFutureStub(channel, callOptions);
  }

  /**
   */
  public com.google.common.util.concurrent.ListenableFuture<ird.ntp.be.sms.proto.SendSmsMessageResponse> sendSmsMessage(
      ird.ntp.be.sms.proto.SendSmsMessageRequest request) {
    return io.grpc.stub.ClientCalls.futureUnaryCall(
        getChannel().newCall(getSendSmsMessageMethod(), getCallOptions()), request);
  }
}

private static final int METHODID_SEND_SMS_MESSAGE = 0;

private static final class MethodHandlers<Req, Resp> implements
    io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
    io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,
    io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,
    io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {
  private final SmsProxyAPIImplBase serviceImpl;
  private final int methodId;

  MethodHandlers(SmsProxyAPIImplBase serviceImpl, int methodId) {
    this.serviceImpl = serviceImpl;
    this.methodId = methodId;
  }

  @java.lang.Override
  @java.lang.SuppressWarnings("unchecked")
  public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {
    switch (methodId) {
      case METHODID_SEND_SMS_MESSAGE:
        serviceImpl.sendSmsMessage((ird.ntp.be.sms.proto.SendSmsMessageRequest) request,
            (io.grpc.stub.StreamObserver<ird.ntp.be.sms.proto.SendSmsMessageResponse>) responseObserver);
        break;
      default:
        throw new AssertionError();
    }
  }

  @java.lang.Override
  @java.lang.SuppressWarnings("unchecked")
  public io.grpc.stub.StreamObserver<Req> invoke(
      io.grpc.stub.StreamObserver<Resp> responseObserver) {
    switch (methodId) {
      default:
        throw new AssertionError();
    }
  }
}

private static abstract class SmsProxyAPIBaseDescriptorSupplier
    implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier {
  SmsProxyAPIBaseDescriptorSupplier() {}

  @java.lang.Override
  public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {
    return ird.ntp.be.sms.proto.SmsProxyServiceProto.getDescriptor();
  }

  @java.lang.Override
  public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {
    return getFileDescriptor().findServiceByName("SmsProxyAPI");
  }
}

private static final class SmsProxyAPIFileDescriptorSupplier
    extends SmsProxyAPIBaseDescriptorSupplier {
  SmsProxyAPIFileDescriptorSupplier() {}
}

private static final class SmsProxyAPIMethodDescriptorSupplier
    extends SmsProxyAPIBaseDescriptorSupplier
    implements io.grpc.protobuf.ProtoMethodDescriptorSupplier {
  private final String methodName;

  SmsProxyAPIMethodDescriptorSupplier(String methodName) {
    this.methodName = methodName;
  }

  @java.lang.Override
  public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {
    return getServiceDescriptor().findMethodByName(methodName);
  }
}

private static volatile io.grpc.ServiceDescriptor serviceDescriptor;

public static io.grpc.ServiceDescriptor getServiceDescriptor() {
  io.grpc.ServiceDescriptor result = serviceDescriptor;
  if (result == null) {
    synchronized (SmsProxyAPIGrpc.class) {
      result = serviceDescriptor;
      if (result == null) {
        serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
            .setSchemaDescriptor(new SmsProxyAPIFileDescriptorSupplier())
            .addMethod(getSendSmsMessageMethod())
            .build();
      }
    }
  }
  return result;
}
}

我需要一些帮助。 祝你好运发财

java grpc-java byte-buddy
1个回答
0
投票
   Class<?> type  =
            new ByteBuddy()
            .rebase(SmsProxyAPIGrpc.SmsProxyAPIBlockingStub.class)
                    .constructor(ElementMatchers.isPublic())
                    .intercept(
                            MethodCall.invoke(
                                    originalClass.getDeclaredConstructor(Channel.class, CallOptions.class))
                                    .with(channel,callOptions)
                    ) // 调用带参数的原始类构造函
            .method(ElementMatchers.nameContains("sendSmsMessage"))
            .intercept(MethodDelegation.to(MonitorDemo.class))
            .make()
            .load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST_PERSISTENT)
            .getLoaded();
It can work this way.The key is to make constructor public and mind the classloader.
© www.soinside.com 2019 - 2024. All rights reserved.