EN · DE · RU · FR · ES

#1875: BeanHelper.java

projectforge-common/src/main/java/org/projectforge/common/BeanHelper.java Вспомогательный класс — пакет org.projectforge.common, projectforge-common/src/main/java/org/projectforge/common/BeanHelper.java 678 строк · 481 код · 150 комментариев · 47 пустых
Комплексная утилита для интроспекции и рефлексии JavaBeans. Базовая инфраструктура для уровня интеграции ORM/Wicket в ProjectForge — обеспечивает разрешение имён свойств из методов getter/setter, поиск методов getter/setter с обширным кэшированием (пять внутренних кэшей для производительности), обнаружение аннотаций полей, доступ к вложенным/индексированным свойствам, копирование свойств с обнаружением различий и создание объектов на основе рефлексии. Широко используется во всех модулях ProjectForge для сортировки списков Wicket, привязки форм и преобразования DO в DTO.

Архитектура

Импорты

Внутренняя архитектура кэширования

BeanHelper использует пять статических синхронизированных кэшей для избежания повторных вызовов рефлексии, которые дороги в Java. Это критически важно для страниц списков Wicket, где BeanHelper вызывается для каждой ячейки в сортируемой таблице данных.

КэшКлючЗначениеПреимущество
declaredFieldsCacheClassField[]Избегает повторного сканирования иерархии классов для полей
declaredMethodsCacheClassMethod[]Избегает повторного сканирования иерархии классов для методов
declaredFieldAnnotationsCache"класс:имяполя"Annotation[]Избегает повторного разрешения аннотированных полей (критично для сортировки колонок Wicket)
getterMethodsCache"класс:имяполя"MethodИзбегает повторного поиска методов getter
declaredGetterMethodsCacheStringMethod[]Объявлен, но, похоже, не используется в предоставленном коде — может заполняться в другом месте

Ключевые операции

Разрешение имени свойства

Доступ к аннотациям

getDeclaredAnnotations(Class, имяполя) поддерживает пути к вложенным свойствам (разделённые точкой, например, "address.city.name") путём обхода цепочки полей через рефлексию для поиска аннотаций конечного поля. Это необходимо для таблиц данных Wicket, которые отображают вложенные свойства объектов с сортируемыми колонками.

Доступ к свойствам (вложенные + индексированные)

Копирование свойств (copyProperties)

Копирует указанные свойства из исходного объекта в целевой, возвращая true, если какое-либо свойство фактически изменилось. Поддерживает:

Утилиты рефлексии

Функция тестового режима

Флаг TEST_MODE (управляется enterTestMode()/exitTestMode()) подавляет логирование ошибок во время выполнения тестов. Это позволяет тестам выполнять операции рефлексии, которые, как ожидается, завершатся ошибкой, не засоряя журналы тестов трассировками стека. Методы logInstantiationException() учитывают этот флаг.

Проектные решения

  1. Агрессивное кэширование: Существует пять кэшей, потому что рефлексия медленна, а BeanHelper вызывается на горячих путях (рендеринг и сортировка таблиц данных Wicket)
  2. Фильтрация bridge-методов: determineGetter() пропускает bridge-методы (синтетические методы, создаваемые компилятором для стирания обобщённых типов), чтобы вернуть фактически реализованный метод
  3. Безопасный обход null: getNestedProperty() возвращает null в любой точке цепочки, где промежуточное значение равно null, вместо выброса NPE
  4. Доступность конструкторов: newInstance() вызывает constructor.setAccessible(true) для создания экземпляров классов с приватными конструкторами
  5. Отсутствие внешней библиотеки bean: Несмотря на зависимость от commons-beanutils в сборке Gradle, BeanHelper реализует собственное разрешение свойств вместо прямого использования Apache BeanUtils — вероятно, для контроля производительности и кэширования
Вспомогательный метод isEqualList() (пакетно-приватный) выполняет поэлементное сравнение с использованием итераторов, а не equals(). Это означает, что равенство коллекций основано на идентичности/равенстве элементов на соответствующих позициях, а не на равенстве множеств — два списка с одинаковыми элементами в разном порядке не считаются равными.

История Git

868d6abb7 2025 -> 2026
63081666f Заголовки исходных файлов: 2024 -> 2025.
a73905c14 Исправление опечаток в каталогах projectforge*/ Найдено с помощью codespell
694987647 Миграция в процессе... (все тесты всех пакетов: OK).
ae50b2522 BeanHelper.getProperty теперь поддерживает вложенные свойства с помощью нового PropertyUtils.
b6092df09 Авторское право 2023 -> 2024
ab45d51fa Авторское право 2001-2022 -> 2001-2023.
0203e3261 AbstractListPage: длительные запросы: изменение порядка сортировки показывает список результатов без кнопки поиска. BeanHelper: множество кэшей для более быстрой сортировки в списках результатов Wicket.