¿Cómo implementar un decorador de contenedor en Java?

El problema es crear una versión dinámica mejorada de los objetos existentes.

No puedo modificar el objetoClass. En cambio tengo que:

subclasearloenvolver el objeto existente en el nuevoClassdelegar todas las llamadas de método originales al objeto envueltoimplementar todos los métodos definidos por otra interfaz

La interfaz para agregar a los objetos existentes es:

public interface EnhancedNode {

  Node getNode();
  void setNode(Node node);

  Set getRules();
  void setRules(Set rules);

  Map getGroups();
  void setGroups(Map groups);

}

ConByte Buddy Logré subclasificar e implementar mi interfaz. El problema es la delegación al objeto envuelto. La única forma de hacer esto que encontré es usar la reflexión lo que es demasiado lento (tengo una gran carga en la aplicación y el rendimiento es crítico).

Hasta ahora mi código es:

Class<? extends Node> proxyType = new ByteBuddy()
     .subclass(node.getClass(), ConstructorStrategy.Default.IMITATE_SUPER_TYPE_PUBLIC)
     .method(anyOf(finalNode.getClass().getMethods())).intercept(MethodDelegation.to(NodeInterceptor.class))
     .defineField("node", Node.class, Visibility.PRIVATE)
     .implement(EnhancedNode.class).intercept(FieldAccessor.ofBeanProperty())
     .defineField("groups", Map.class, Visibility.PRIVATE)
     .implement(EnhancedNode.class).intercept(FieldAccessor.ofBeanProperty())
     .defineField("rules", Set.class, Visibility.PRIVATE)
     .implement(EnhancedNode.class).intercept(FieldAccessor.ofBeanProperty())
     .make()
     .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
     .getLoaded();
enhancedClass = (Class<N>) proxyType;
EnhancedNode enhancedNode = (EnhancedNode) enhancedClass.newInstance();
enhancedNode.setNode(node);

dóndeNode es el objeto de subclase / ajuste. losNodeInterceptor reenvía los métodos invocados a lagetNode propiedad.

Aquí el código de laNodeInterceptor:

public class NodeInterceptor {

  @RuntimeType
  public static Object intercept(@Origin Method method,
                               @This EnhancedNode proxy,
                               @AllArguments Object[] arguments)
        throws Exception {
      Node node = proxy.getNode();
      Object res;
      if (node != null) {
          res = method.invoke(method.getDeclaringClass().cast(node), arguments);
      } else {
          res = null;
      }
      return res;
  }
}

Todo funciona pero el método de intercepción es demasiado lento, estoy planeando usar ASM directamente para agregar la implementación de cada método de Node, pero espero que haya una forma más simple de usar Byte Buddy.

Respuestas a la pregunta(1)

Su respuesta a la pregunta