equals-Methode bestimmer Klassen abfangen

SimProtect

Aktives Mitglied
Hallo Leute,
Ich habe mal wieder eine Frage, zu welcher meine Google-Suchergebnisse unzureichend waren.
Kurzform der Problemstellung:
In unserem aktuellen Framework soll es eine Möglichkeit geben, eine bestimmte Implementierung der equals-Methode beim Programmstart zu verwenden/nutzen, wenn die Klasse mit einer bestimmten Annotation versehen worden ist.
Dabei sind die koknrete Implementierung oder Objekthierarchien der jeweiligen Klasse unbekannt. Ich weiß also auch nichts über die Oberklassen oder implementierten Interfaces bzw. ob solche überhaupt vorhanden sind

Ich habe in Java noch nie mit einer entsprechenden Mechanik gearbeitet - wohl aber in anderen Programmiersprachen. Dort wurden die entsprechenden Instanzen der Klasse zur Laufzeit mit einem Proxy versehen, der entweder Methodenaufrufe an das originale Objekt weiterleiten oder durch einen anderen Aufruf ersetzen.

Leider waren alle meine Versuche, etwas entsprechendes in Java umzusetzen nicht von Erfolg geprägt - meine Google-Suchen ebensowenig.

Daher wollte ich mal hier fragen, welchen Ansatz ich hier am besten verfolgen soll oder ob das so überhaupt möglich ist.

Noch als relevante Information: Wir haben die aktuellste Java-Version im Einsatz und wir nutzen Spring inklusive AOP. Allerdings habe ich persönlich bisher wenig mit Spring AOP gearbeitet. Generell "komme" ich aus einem anderen Programmiersprachenkontext - daher bitte ich mein ggf. vorhandenes Unwissen über die Java-Mechaniken zu entschuldigen und bitte Euch um Hilfe.

Liebe Grüße

PS: Ich habe folgenden Proxy in Java entwickelt, welcher die Mechanik bereits umsetzt. Allerdings erfordert dieser einen Default-Konstruktor, der nicht public sein darf. Das ist damit nicht zufriedenstellend für die aktuelle angestrebte Architektur. Da sollen nämlich solche Konstruktoren vermieden werden.

Code:
  public static Object createProxyOf(Object object) {
     return Enhancer.create(object.getClass(), new MethodInterceptor() {

       public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
         if ("equals".equals(method.getName())) {
           return checkEqualityOf(o, args[0]);
         } else {
           return methodProxy.invokeSuper(o, args);
         }
       }
     });
   }
 
Zuletzt bearbeitet:
Grundsätzlich hast du zwei Möglichkeiten. Einmal, wie von dir vorgeschlagen, über Proxys, oder aber per Bytecode-Modifikation. Du/Ihr habt dich/euch aber ja anscheinend schon für den Weg über die Proxys entschieden, was auch vollkommen OK ist. Ansonsten konnte ich in deinem Post keine wirkliche Frage entdecken...

Allerdings erfordert dieser einen Default-Konstruktor, der nicht public sein darf.

Das wird schwierig, denn der default-Konstruktor IST public.
 
Ach ich und Kommunikation - wir sind manchmal nicht die besten Freunde...

Ich greife zunächst einmal Deinen letzten Satz auf:
Da habe ich einen Schreibfehler eingebaut: Natürlich erfordert Spring bzw. CGLib einen Default-Konstruktor, der public sein MUSS (bzw. nicht private sein darf). Entschuldige bitte diesen Fehler.

Warum haben wir damit ein Problem? Nun, in den meisten(!) Fällen, soll das Objekt in der (eigenen) BusinessLogik natürlich über seinen "Hauptkonstruktor" aufgebaut werden. Ein sichtbarer Default-Konstruktor umgeht da ggfs. Logiken. Unser aktuelles Projekt verwendet kein Hibernate o.Ä., weshalb wir bisher keinen entsprechenden Konstruktor brauchten und auch nicht wollten.
Dieses Projekt soll später von Nutzern genutzt und erweitert werden, die nicht aus unserem Hause sind. Da hält unser Architekt sichtbare Schnittstellen, die aber nicht verwendet werden soll, für eine äußerst unschöne Lösung.
Daher belassen wir den Default-Konstruktor nur in Objekten, die keine Parameter benötigen. Ansonsten gibt es immer einen konkreten Konstruktor oder der Default wird mit dem Modifier private versehen (z.B. Util-Klassen, die nicht initialisiert werden sollen.)

Dann zu Deinem ersten Punkt:
So wirklich entschieden habe ich mich hier noch nicht. Ich habe nur das Ziel vorgegeben, nicht aber die technische Umsetzung. Die Proxy-Lösung kannte ich noch aus früheren Projekten bzw. anderen Sprachen. Daher war das die Lösung, die mir natürlich als erstes in den Kopf kam. Allerdings wusste ich zu diesem Zeitpunkt nicht, wie gangbar oder ungangwar diese Lösung in Java sein würde.

Daher war meine Frage, wie ich das in Java am sinnigsten löse?

Für die Proxy-Lösung habe ich (in meiner bisherigen Umsetzung und in Betrachtung unserer Architekturvorgaben) folgende Nachteile entdeckt:
-> Ich muss einen Default-Konstruktor angeben (hier könnte ich zwar mit dem Architekten sicherlich reden, aber grundsätzlich sollte ich natürlich erstmal Versuchen, eine Lösung zu finden, durch welche die Architektur eingehalten wird)
-> Es besteht zur Laufzeit der Aufwand, dass man neue Instanzen der entsprechenden Klassen "abfangen" und durch Proxy-Objekte ersetzen muss. Aktuell ist dies noch kein großes Problem, da sich die aktuellen BO im System registrieren müssen und ich sie in diesem Vorgang natürlich ersetzen kann, wirklich fein ist das auch nicht. Es bietet viel Raum für Fehler.

Kann ich diese Nachteile umgehen? Hat da jemand eine Idee für mich? Oder eine bestimmte Bibliothek?

Wie sähe denn eine Bytecodemanipulation aus?
Welche Vorteile bzw. welche Nachteile hätte eine solches Vorgehen?

Liebe Grüße und einen schönen Sonntag 🙂
 

Neue Themen


Zurück
Oben