EN · DE · RU · FR · ES

#1875: BeanHelper.java

projectforge-common/src/main/java/org/projectforge/common/BeanHelper.java Clase de utilidad — paquete org.projectforge.common, projectforge-common/src/main/java/org/projectforge/common/BeanHelper.java 678 líneas · 481 código · 150 comentarios · 47 en blanco
Utilidad integral de introspección y reflexión de JavaBeans. Infraestructura central para la capa de integración ORM/Wicket de ProjectForge — proporciona resolución de nombres de propiedades a partir de métodos getter/setter, búsqueda de métodos getter/setter con amplio almacenamiento en caché (cinco cachés internas para rendimiento), descubrimiento de anotaciones en campos, acceso a propiedades anidadas/indexadas, copia de propiedades con detección de diferencias e instanciación de objetos basada en reflexión. Ampliamente utilizado en todos los módulos de ProjectForge para ordenación de listas en Wicket, enlace de formularios y conversión DO a DTO.

Arquitectura

Importaciones

Arquitectura de almacenamiento en caché interno

BeanHelper utiliza cinco cachés sincronizadas estáticas para evitar llamadas de reflexión repetidas, que son costosas en Java. Esto es crítico para las páginas de listas de Wicket donde se llama a BeanHelper para cada celda en una tabla de datos ordenable.

CachéClaveValorBeneficio
declaredFieldsCacheClassField[]Evita volver a escanear la jerarquía de clases en busca de campos
declaredMethodsCacheClassMethod[]Evita volver a escanear la jerarquía de clases en busca de métodos
declaredFieldAnnotationsCache"clase:nombrecampo"Annotation[]Evita volver a resolver campos anotados (crítico para la ordenación de columnas en Wicket)
getterMethodsCache"clase:nombrecampo"MethodEvita volver a buscar métodos getter
declaredGetterMethodsCacheStringMethod[]Declarado pero parece no usarse en el código proporcionado — puede poblarse en otro lugar

Operaciones clave

Resolución de nombres de propiedades

Acceso a anotaciones

getDeclaredAnnotations(Class, nombrecampo) soporta rutas de propiedades anidadas (separadas por puntos, ej., "direccion.ciudad.nombre") recorriendo la cadena de campos a través de la reflexión para encontrar las anotaciones del campo terminal. Esto es esencial para las tablas de datos de Wicket que muestran propiedades de objetos anidados con columnas ordenables.

Acceso a propiedades (anidadas + indexadas)

Copia de propiedades (copyProperties)

Copia las propiedades especificadas del objeto origen al destino, devolviendo true si alguna propiedad realmente cambió. Soporta:

Utilidades de reflexión

Característica de modo de prueba

La bandera TEST_MODE (controlada por enterTestMode()/exitTestMode()) suprime el registro de errores durante la ejecución de pruebas. Esto permite que las pruebas intenten operaciones de reflexión que se espera que fallen sin contaminar los registros de prueba con trazas de pila. Los métodos logInstantiationException() respetan esta bandera.

Decisiones de diseño

  1. Almacenamiento en caché agresivo: Existen cinco cachés porque la reflexión es lenta y se llama a BeanHelper en rutas críticas (representación y ordenación de tablas de datos de Wicket)
  2. Filtrado de métodos puente: determineGetter() omite los métodos puente (métodos sintéticos creados por el compilador para la eliminación de tipos genéricos) para devolver el método real implementado
  3. Recorrido seguro para nulos: getNestedProperty() devuelve null en cualquier punto de la cadena donde un valor intermedio sea nulo, en lugar de lanzar NPE
  4. Accesibilidad del constructor: newInstance() llama a constructor.setAccessible(true) para instanciar clases con constructores privados
  5. Sin biblioteca de beans externa: A pesar de depender de commons-beanutils en la compilación de Gradle, BeanHelper implementa su propia resolución de propiedades en lugar de usar Apache BeanUtils directamente — probablemente para control de rendimiento y almacenamiento en caché
El ayudante isEqualList() (privado del paquete) realiza una comparación elemento por elemento usando iteradores, no equals(). Esto significa que la igualdad de colecciones se basa en la identidad/igualdad de elementos en posiciones correspondientes, no en la igualdad de conjuntos — dos listas con los mismos elementos en diferente orden no son iguales.

Historial de Git

868d6abb7 2025 -> 2026
63081666f Encabezados de archivos fuente: 2024 -> 2025.
a73905c14 Corrección de errores tipográficos en directorios projectforge*/ Encontrados mediante codespell
694987647 Migración en progreso... (todas las pruebas de todos los paquetes: OK).
ae50b2522 BeanHelper.getProperty ahora soporta propiedades anidadas usando simplemente new PropertyUtils.
b6092df09 Copyright 2023 -> 2024
ab45d51fa Copyright 2001-2022 -> 2001-2023.
0203e3261 AbstractListPage: consultas de larga duración: el cambio de orden de clasificación muestra la lista de resultados sin el botón de búsqueda. BeanHelper: muchas cachés para una clasificación más rápida en las listas de resultados de Wicket.