2009-10-28 12 views
5

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 anotados con @PostInject.Java: ¿Cuál es la forma más rápida de inyectar campos usando la reflexión?

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 utilizando la reflexión?
Recuerde, tengo que hacer esto muy a menudo en muchas clases, eso es por qué el rendimiento es relevante.

Lo que yo haría por la intuición se desprende de este pseudo-código:

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

Me temo que conseguir todos los campos es lo más lento que hacer.
¿Alguien puede obtener un campo, cuando lo sé desde el principio?

NOTA: No puedo dejar que las clases implementen alguna interfaz, lo que permitiría configurar los campos utilizando un método. Necesito POJOs.

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

NOTE2b: Desde el punto de vista del usuario, el contrato final es no roto. Se mantiene 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).

+0

Tengo curiosidad de por qué tendrías que hacer esto? ¿Hay alguna historia interesante detrás de esta, y si la hay, puedes compartirla? –

+0

Estoy escribiendo un marshaller | unmarshaller similar a JAXB, pero más especial (por lo tanto, más limitado). Los POJO con anotaciones son muy flexibles. –

+1

Si está requiriendo que los implementadores usen su anotación, en realidad no está ganando nada con el uso de una interfaz aquí y no está realmente usando un POJO - http://en.wikipedia.org/wiki/Plain_Old_Java_Object#Contextual_variations – Nate

Respuesta

7

¿Qué tal hacer los pasos 1 a 3 justo después de construir el objeto y guardar el conjunto de campos anotados que obtienes en el objeto mismo o manteniendo un mapa de clase por separado para los campos de conjunto de anotaciones?

Entonces, cuando se necesita para actualizar los campos inyectados en un objeto, recuperar el conjunto, ya sea del objeto o el mapa separada y realice el paso 4.

+0

¡¡idea perfecta !!! –

1

1 Me gusta la idea de RSP.


Otra opción, como dices que conoces los pocos campos en cuestión desde el principio, es pedir solo esos campos o métodos.

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

1

No sé si es bueno, pero this project parece que sería hacer lo que quiera. Cita:

Un conjunto de utilidades de reflexión y diversos servicios públicos relacionados con que trabajan con las clases y sus campos sin dependencias que es compatible con Java 1.5 y los genéricos.

datos de reflexión

La utilidad de memoria caché para un funcionamiento de alto rendimiento, pero utiliza el almacenamiento en caché débil/blanda para evitar la celebración de cargadores de clases abiertas y causando los cachés de existir en la memoria de forma permanente. La capacidad de reemplazar el mecanismo de caché con el suyo es compatible con .

0

Puede explotar los marcos existentes que permiten inyectar dependencias de construcción de objetos. Por ejemplo, Spring allows to do that con aspectj weaving. La idea general es definir las dependencias de bean a nivel de primavera y simplemente marcar las clases de destino para asesorar sobre la creación de objetos. La lógica de resolución de dependencia real se inyecta directamente al código de byte de la clase (es posible utilizar el entrelazado de tiempo de carga o compilación).

0

La forma más rápida de hacer cualquier cosa con la reflexión es almacenar en caché las clases reales de Reflection API siempre que sea posible. Por ejemplo hace poco hice un todavía-otra-dinámico-POJO manipuladora que creo que es una de esas cosas 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, ""); 
     } 
} 

El modo de funcionamiento es que básicamente tiene ese objeto controlador que aplica perezosas a todas las propiedades del bean (nota : alguna magia involucrada en) y luego las reutiliza mientras el objeto controlador real esté activo. Todo lo que puedo decir es que solo al guardar los objetos del Método yo mismo logré convertir esa cosa en una maldita cosa rápida y estoy muy orgulloso de ello e incluso considerando liberarlo suponiendo que puedo resolver los derechos de autor, etc.

Cuestiones relacionadas