Pregunta

Supongamos que tengo muchas clases, que se construyen utilizando la reflexión de Java (por alguna razón). Ahora necesito post-inyectar valores a los campos, que son anotado con @PostInject .

public class SomeClass {
  @PostInject
  private final String someString = null;

  public void someMethod() {
    // here, someString has a value.
  }
}

Mi pregunta es: ¿cuál es una forma rápida de establecer un campo usando la reflexión?
Recuerde, necesito hacer esto muy a menudo en muchas clases, eso es por qué el rendimiento es relevante.

Lo que haría por intuición se muestra en este pseudocódigo:

  • obtener todos los campos de la clase
    clazz.getFields();
  • check, que están anotados con @PostInject
    eachField.getAnnotation(PostInject.class);
  • hacer estos campos accesibles
    eachAnnotatedField.setAccessible(true);
  • establecerlos en un cierto valor
    eachAnnotatedField.set (clazz, someValue);

Me temo que obtener todos los campos es lo más lento.
¿Puedo obtener un campo cuando lo conozco desde el principio?

NOTA: No puedo dejar que las clases implementen alguna interfaz, lo que Permitir establecer los campos utilizando un método. Necesito POJOs.

NOTA2: Por qué quiero la inyección posterior al campo: desde el punto de vista de un usuario de API, debe ser posible utilizar los campos finales. Además, cuando la API no conoce los tipos y la cantidad de campos a priori, es imposible lograr la inicialización de los campos utilizando una interfaz.

NOTA2b: Desde el punto de vista del usuario, el contrato final no está roto. Se queda final. Primero, un campo se inicializa, luego no se puede cambiar. Por cierto: hay muchas API que usan este concepto, una de ellas es JAXB (parte del JDK).

¿Fue útil?

Solución

¿Qué tal hacer los pasos 1 a 3 justo después de construir el objeto y guardar el conjunto de campos anotados que obtiene en el propio objeto o al mantener un mapa separado de clase en un conjunto de campos anotados?

Luego, cuando necesite actualizar los campos inyectados en un objeto, recupere el conjunto del objeto o del mapa separado y realice el paso 4.

Otros consejos

No sé si es bueno, pero este proyecto parece que sería Haz lo que quieras. Cita:

  

Un conjunto de utilidades de reflexión y   Utilidades diversas relacionadas con   trabajando con clases y sus campos   sin dependencias que es   compatible con java 1.5 y genéricos.

     

Los datos de reflexión de caché de utilidades   para operación de alto rendimiento pero   utiliza caché débil / suave para evitar   manteniendo abiertos los cargadores de clase y provocando   los cachés para existir en la memoria   permanentemente. La capacidad de anular   el mecanismo de almacenamiento en caché con el suyo es   compatible.

Otra opción, como usted dice que conoce los pocos campos en cuestión desde el principio, es solicitar solo esos campos o métodos.

Ejemplo: vea getDeclaredMethod o getDeclaredField en java / lang / Class.html

Puede explotar los marcos existentes que permiten inyectar dependencias en la construcción de objetos. Por ejemplo, Spring permite hacer eso con aspecto de tejido. La idea general es que defina dependencias de bean en el nivel de primavera y simplemente marque las clases de destino para aconsejar su creación de objetos. La lógica de resolución de dependencia real se inyecta directamente en el código de bytes de la clase (es posible utilizar el tejido de tiempo de compilación o de carga).

La forma más rápida de hacer algo con la reflexión es almacenar en caché las clases reales de API de Reflection siempre que sea posible. Por ejemplo, hace muy poco hice un manipulador POJO más dinámico que creo que es una de esas cosas que todo el mundo termina haciendo en algún momento que me permite hacer esto:

Object o = ...
BeanPropertyController c = BeanPropertyController.of(o);

for (String propertyName : c.getPropertyNames()) {
        if (c.access(propertyName) == null && 
            c.typeOf(propertyName).equals(String.class)) {
                c.mutate(propertyName, "");
        }
}

La forma en que funciona es que básicamente tiene ese único objeto controlador que carga de manera diferida todas las propiedades del bean ( nota: algo de magia involucrada ) y luego las reutiliza siempre que el objeto controlador real sea viva. Todo lo que puedo decir es que simplemente guardando los objetos del Método en sí, logré convertirlo en algo malditamente rápido y estoy muy orgulloso de eso e incluso considerando liberarlo asumiendo que puedo resolver los derechos de autor, etc.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top