Gibt es einen praktikablen Weg, um meinen eigenen Code auszuführen, wenn eine Klasse in Java geladen wird, ohne den Benutzer explizit dazu zu zwingen, alle Klassen manuell mit einem benutzerdefinierten Classloader zu laden?
Ohne zu sehr in die Details zu gehen, wenn eine Klasse, die eine bestimmte Schnittstelle implementiert, ihre Annotation liest, die sie mit einer anderen Klasse verbindet, und das Paar einer dritten Klasse zuweist.
Edit: Verdammt, ich gehe zu den Details: Ich mache eine Ereignisbehandlungsbibliothek. Was ich mache ist, dass der Client-Code eigene Listener / Event-Paare hat, die in meiner Bibliothek als Paar registriert werden müssen. (Hm, das war nicht lange her).
Weiter Bearbeiten: Gegenwärtig muss der Client-Code das Paar Klassen / Schnittstellen manuell registrieren, was ziemlich gut funktioniert. Meine Absicht ist es, dies zu automatisieren, und ich dachte, dass die Verknüpfung der beiden Klassen mit Anmerkungen helfen würde. Als nächstes möchte ich den Client-Code loswerden, der die Liste der Registrierungen immer auf dem neuesten Stand halten muss.
PS: Der statische Block funktioniert nicht, da meine Schnittstelle in einer Bibliothek gebündelt ist und der Client-Code weitere Schnittstellen erzeugt. Daher werden abstrakte Klassen auch nicht, da es eine Schnittstelle sein muss.
Wenn Sie das Verhalten auf einer Schnittstelle basieren wollen, könnten Sie einen statischen Initializer in dieser Schnittstelle verwenden.
%Vor%Ich sage nicht, dass es eine gute Übung ist, aber es wird definitiv initialisiert, wenn eine der implementierenden Klassen das erste Mal geladen wird.
Update: statische Blöcke in Schnittstellen sind illegal. Verwenden Sie stattdessen abstrakte Klassen!
Referenz:
Aber wenn ich Sie richtig verstehe, möchten Sie, dass die Initialisierung einmal pro implementierender Klasse erfolgt. Das wird schwierig sein. Mit einer schnittstellenbasierten Lösung können Sie das definitiv nicht machen. Sie könnten dies mit einer abstrakten Basisklasse tun, die einen dynamischen Initialisierer (oder Konstruktor) hat, der prüft, ob das angeforderte Mapping bereits existiert und fügt es hinzu, wenn dies nicht der Fall ist, aber solche Dinge in Konstruktoren zu tun, ist ein hack.
>Ich würde sagen, dass die saubersten Optionen sind, Code entweder zur Build-Zeit (durch Annotationsverarbeitung mit apt oder durch Bytecode-Analyse mit einem Tool wie asm) zu erzeugen oder einen Agenten zur Ladezeit der Klasse zu verwenden, um das Mapping dynamisch zu erstellen / p>
Ah, mehr Input. Sehr gut. Clients verwenden Ihre Bibliothek und stellen auf Annotationen basierende Zuordnungen bereit. Dann würde ich sagen, dass Ihre Bibliothek eine Initialisierungsmethode bereitstellen sollte, bei der Client-Code Klassen registrieren kann. Etwas wie das:
%Vor%Oder, noch besser, einen Paket-Scan-Mechanismus (Beispielcode, um dies zu implementieren, finden Sie bei dieser Frage ):
%Vor%Wie auch immer, es gibt im Grunde keine Möglichkeit zu vermeiden, dass Ihre Kunden diese Art von Arbeit machen, weil Sie weder ihren Build-Prozess noch ihren Classloader kontrollieren können (aber Sie könnten natürlich Anleitungen für den Classloader oder die Build-Konfiguration bereitstellen).
Wenn Sie wollen, dass ein Code bei jedem Laden von Klassen ausgeführt wird, sollten Sie:
Abhängig davon, welche Art von Umgebung Sie verwenden, besteht die Möglichkeit, dass nicht alle Klassen in Ihren benutzerdefinierten ClassLoader geladen werden (einige Hilfsprogramme verwenden ihren eigenen CL, einige Java EE-Container einige räumliche Bereiche mit bestimmten ClassLoadern usw.). , aber es ist eine Art Annäherung an das, was du verlangst.
Tags und Links java classloader