EN · DE · RU · FR · ES

#1875: BeanHelper.java

projectforge-common/src/main/java/org/projectforge/common/BeanHelper.java Hilfsklasse — Paket org.projectforge.common, projectforge-common/src/main/java/org/projectforge/common/BeanHelper.java 678 Zeilen · 481 Code · 150 Kommentare · 47 Leer
Umfassendes JavaBean-Introspektions- und Reflektionswerkzeug. Kerninfrastruktur für die ORM/Wicket-Integrationsschicht von ProjectForge — bietet Eigenschaftsnamenauflösung aus Getter/Setter-Methoden, Getter/Setter-Methodensuche mit umfangreichem Caching (fünf interne Caches für die Leistung), Feldannotationserkennung, verschachtelten/indexierten Eigenschaftszugriff, Eigenschaftskopieren mit Differenzerkennung und reflektionsbasierte Objektinstanziierung. Weit verbreitet in allen ProjectForge-Modulen für Wicket-Listensortierung, Formularbindung und DO-zu-DTO-Konvertierung.

Architektur

Importe

Internes Caching-Architektur

BeanHelper verwendet fünf statische synchronisierte Caches, um wiederholte Reflektionsaufrufe zu vermeiden, die in Java teuer sind. Dies ist entscheidend für Wicket-Listenseiten, bei denen BeanHelper für jede Zelle in einer sortierbaren Datentabelle aufgerufen wird.

CacheSchlüsselWertNutzen
declaredFieldsCacheClassField[]Vermeidet erneutes Durchsuchen der Klassenhierarchie nach Feldern
declaredMethodsCacheClassMethod[]Vermeidet erneutes Durchsuchen der Klassenhierarchie nach Methoden
declaredFieldAnnotationsCache"Klasse:Feldname"Annotation[]Vermeidet erneutes Auflösen annotierter Felder (entscheidend für Wicket-Spaltensortierung)
getterMethodsCache"Klasse:Feldname"MethodVermeidet erneute Suche nach Getter-Methoden
declaredGetterMethodsCacheStringMethod[]Deklariert, aber im bereitgestellten Code scheinbar ungenutzt — könnte anderswo befüllt werden

Schlüsseloperationen

Eigenschaftsnamenauflösung

Annotationszugriff

getDeclaredAnnotations(Class, Feldname) unterstützt verschachtelte Eigenschaftspfade (punktgetrennt, z. B. "adresse.stadt.name"), indem die Feldkette durch Reflektion durchlaufen wird, um die Annotationen des Endfelds zu finden. Dies ist essentiell für Wicket-Datentabellen, die verschachtelte Objekteigenschaften mit sortierbaren Spalten anzeigen.

Eigenschaftszugriff (Verschachtelt + Indiziert)

Eigenschaftskopieren (copyProperties)

Kopiert angegebene Eigenschaften vom Quell- zum Zielobjekt und gibt true zurück, wenn sich eine Eigenschaft tatsächlich geändert hat. Unterstützt:

Reflektionshilfsprogramme

Testmodus-Funktion

Das TEST_MODE-Flag (gesteuert durch enterTestMode()/exitTestMode()) unterdrückt die Fehlerprotokollierung während der Testausführung. Dies ermöglicht Tests, Reflektionsoperationen zu versuchen, die voraussichtlich fehlschlagen, ohne die Testprotokolle mit Stacktraces zu verschmutzen. Die Methoden logInstantiationException() beachten dieses Flag.

Entwurfsentscheidungen

  1. Aggressives Caching: Fünf Caches existieren, weil Reflektion langsam ist und BeanHelper auf heißen Pfaden aufgerufen wird (Wicket-Datentabellen-Rendering und -Sortierung)
  2. Brückenmethoden-Filterung: determineGetter() überspringt Brückenmethoden (synthetische Methoden, die vom Compiler für generische Typlöschung erstellt wurden), um die tatsächlich implementierte Methode zurückzugeben
  3. Nullsichere Traversierung: getNestedProperty() gibt an jedem Punkt der Kette null zurück, an dem ein Zwischenwert null ist, anstatt eine NPE zu werfen
  4. Konstruktorzugänglichkeit: newInstance() ruft constructor.setAccessible(true) auf, um Klassen mit privaten Konstruktoren zu instanziieren
  5. Keine externe Bean-Bibliothek: Trotz der Abhängigkeit von commons-beanutils im Gradle-Build implementiert BeanHelper seine eigene Eigenschaftsauflösung anstatt Apache BeanUtils direkt zu verwenden — wahrscheinlich aus Leistungs- und Cache-Kontrollgründen
Der Helfer isEqualList() (paketprivat) führt einen elementweisen Vergleich unter Verwendung von Iteratoren durch, nicht equals(). Dies bedeutet, dass die Collection-Gleichheit auf der Elementidentität/Gleichheit korrespondierender Positionen basiert, nicht auf der Mengengleichheit — zwei Listen mit denselben Elementen in unterschiedlicher Reihenfolge sind nicht gleich.

Git-Verlauf

868d6abb7 2025 -> 2026
63081666f Quelltextdatei-Header: 2024 -> 2025.
a73905c14 Korrigiere Tippfehler in projectforge/*-Verzeichnissen Gefunden via codespell
694987647 Migration stuff in progress... (alle Tests aller Pakete: OK).
ae50b2522 BeanHelper.getProperty unterstützt jetzt verschachtelte Eigenschaften durch einfache Verwendung von new PropertyUtils.
b6092df09 Copyright 2023 -> 2024
ab45d51fa Copyright 2001-2022 -> 2001-2023.
0203e3261 AbstractListPage: langlaufende Abfragen: Änderung der Sortierreihenfolge zeigt Ergebnisliste ohne Suchbutton. BeanHelper: viele Caches für schnellere Sortierung in Wicket-Ergebnislisten.