Wie implementiere ich einen Wrapper Decorator in Java?

Das Problem besteht darin, eine dynamisch erweiterte Version vorhandener Objekte zu erstellen.

Ich kann das @ des Objekts nicht ändeClass. Stattdessen muss ich:

subclass itwrap das vorhandene Objekt in das neueClassdelegate alle ursprünglichen Methodenaufrufe für das umgebrochene Objektimplementiere alle Methoden, die von einer anderen Schnittstelle definiert werden

Die Schnittstelle zum Hinzufügen zu vorhandenen Objekten lautet:

public interface EnhancedNode {

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

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

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

}

MitByte Buddy Ich habe es geschafft, eine Unterklasse zu erstellen und meine Schnittstelle zu implementieren. Das Problem ist die Delegierung an das umschlossene Objekt. Die einzige Möglichkeit, dies zu tun, ist die Verwendung einer zu langsamen Reflektion (die Anwendung ist stark ausgelastet, und die Leistung ist kritisch).

So weit ist mein Code:

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);

woNode ist das zu untergeordnete / umschließende Objekt. DasNodeInterceptor leitet die aufgerufenen Methoden an das @ weitgetNode Eigentum

Hier ist der Code desNodeInterceptor:

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;
  }
}

Alles funktioniert, aber die Intercept-Methode ist zu langsam. Ich plane, ASM direkt zu verwenden, um die Implementierung jeder Methode von Node hinzuzufügen, aber ich hoffe, es gibt eine einfachere Möglichkeit, Byte Buddy zu verwenden.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage