如何使用 ByteBuddy 获取 class 的动态代理

How to get a dynamic proxy for a class using ByteBuddy

我想为生成的 classes (Swagger) 使用使用 Proxy.newProxyInstance 的动态代理,这些没有实现接口,这让我想到了 ByteBuddy,它应该允许使用它我来构建 Proxy.newProxyInstance 所需的界面。
我到目前为止:

    Class<?> restClass = RestServiceApi.class;
    Builder<?> builder = byteBuddy.makeInterface().merge(Visibility.PUBLIC).name(restClass.getName() + "I");
    for (Method method : restClass.getMethods()) {

builder = builder.defineMethod(method.getName(),HOW_TO_DO_THIS);

        }
        Class<?> restInterface = builder.make().load(this.getClass().getClassLoader()).getLoaded();
        Class<?>[] proxyInterfaces = new Class<?>[] { restInterface };
// TODO create manipulatedRestServiceApiThatImplementsRestInterfaceI
        asyncServiceProxy = new AsynchronousServiceProxy<>(RestServiceApi.class, errorHandler, guiBlockingListener);
        ctrAsyncService = (manipulatedRestServiceApiThatImplementsRestInterfaceI) Proxy.newProxyInstance(RestServiceApi.class.getClassLoader(), proxyInterfaces, asyncServiceProxy);

即使可以弄清楚如何编写定义每个方法所需的代码,我也觉得我没有以正确的方式进行,我将编写大量代码将 Method 的反射信息转换为 ByteBudd 所需的任何代码,我怀疑有更简单的方法来构建此接口 class.

如果有人能指出正确的方向,我将不胜感激。

您可以简单地申请:

builder = builder.define(method).intercept(MethodDelegation.to(YourDelegation.class));

MethodDelegation 在 Javadoc 中有非常广泛的记录,您可能需要通过它的签名解析调用的方法,然后使用反射调用它,以获得最简单的解决方案。

事实证明我的预感是正确的(我从错误的角度出发)并且应该更广泛地提出这个问题。我真正需要的(但没有问到)是一个构建动态代理的解决方案,你没有服务接口但有服务 class。
有了服务接口,可以使用java.lang.reflect.Proxy搭建动态服务代理:

MyInvocationHandler<ServiceInterface> serviceProxy = new MyInvocationHandler<>();
proxiedService = (ServiceInterface) Proxy.newProxyInstance(ServiceInterface.class.getClassLoader(), new Class[] { ServiceInterface.class }, serviceProxy);

proxiedService.methodOfServiceInterface();

语句 proxiedService.methodOfServiceInterface() 并将调用方法 MyInvocationHandler.invoke(Object proxy, final Method method, final Object[] arguments),该方法可以执行实际方法所需的任何操作(例如,通过远程方法调用)。
这种方法可以很好地调用具有接口的 EJB 或 SOAP 服务,但会中断服务 class。所以我真正需要的是一种算法来构建动态服务代理,该代理适用于服务接口 服务 classes。
使用 ByteBuddy 构建动态服务代理实际上非常简单。以下通用方法实现了所需的算法:

    /**
     * Creates a service proxy to call methods of the service class/interface.
     *
     * @param <T>                     type of service class or interface
     * @param serviceClassOrInterface service class or interface
     * @param serviceProxy            the service proxy
     * @return service proxy
     */
    public static <T> T createDynamicProxy(Class<T> serviceClassOrInterface, MyInvocationHandler<T> serviceProxy) {
        try {
            return new ByteBuddy()
                .subclass(serviceClassOrInterface)
                .method(isDeclaredBy(serviceClassOrInterface))
                .intercept(InvocationHandlerAdapter.of(serviceProxy))
                .make()
                .load(serviceClassOrInterface.getClassLoader())
                .getLoaded().getConstructor().newInstance();
        } catch (Exception exception) {
            throw new RuntimeException("Error creating dynamic proxy of " + serviceClassOrInterface.getName(), exception);
        }
    }

可以这样使用:

MyInvocationHandler<ServiceInterface> serviceProxy = new MyInvocationHandler<>();
proxiedService = createDynamicProxy(serviceInterface, serviceProxy);