2009-10-16 8 views
8

¿Hay alguna manera de obtener archivos de propiedades como clases fuertemente tipadas? Supongo que hay generadores de código pero hacerlo con anotaciones sería mucho más genial.Java .properties archivos como clases fuertemente tipadas

Lo que quiero decir es;

foo.properties file 
keyFoo = valuefoo 
keyBar = valuebar 

quizás con

@properties(file="foo.properties") 
class foo { } 

convierte

class foo { 
    String getKeyFoo() { } 
    String getKeyBar() { } 
} 

si no he de comenzar un proyecto de código abierto para que?

ADICIÓN A LA PREGUNTA;

Creo que tenemos un archivo foo.properties con, por ejemplo, más de 10 entradas; y creo que se usa como un archivo de configuración simple. Lo que creo es que estas entradas de configuración se deben proporcionar como una clase de configuración con métodos getXXX relacionados a otras partes del diseño. Luego, el resto del sistema accede a la configuración a través de la clase proporcionada en lugar de tratar con los nombres de las claves y no necesita preocuparse de dónde viene la configuración. Luego puede reemplazar esta clase con un simulacro cuando está probando llamadas y la dependencia al sistema de archivos desaparece. Por otro lado, es muy bueno para obtener todas las entradas de una manera fuertemente tipada.

Por lo tanto, este problema es un problema de generación de código entre bastidores, no tiene nada que ver con el tiempo de ejecución. Pero la generación de código con algo externo en lugar de anotaciones no me pareció agradable. Aunque no estoy muy familiarizado con las anotaciones, creo que esto podría lograrse (pero tendré en cuenta que las anotaciones no pueden generar clases como puntos McDowell)

+1

lo que sería el caso de uso para esto? un ejemplo sería genial – Chii

Respuesta

2

Hay un somewhat similar project para hacer la configuración como archivos estáticos. Se requiere para declarar una interfaz, pero se llena en la aplicación en sí:

public interface AppConfig extends Config { 
    long getTimeout(); 
    URL getURL(); 
    Class getHandlerClass(); 
} 
+0

El enlace está muerto ... – Kukeltje

+0

El marco PROPIETARIO proporciona esta configuración, consulte http://owner.aeonbits.org/ – vorburger

0

Si desea hacerlo estáticamente, es una generación de código problema que puede resolverse con bastante facilidad (para cada elemento del archivo, produzca un nuevo método getXXX).

Pero si desea esto en tiempo de ejecución, entonces tiene el problema de tener su método de referencia de código que no existía en tiempo de compilación; No creo que se pueda hacer.

(Tenga en cuenta que si usted está buscando una idead proyecto, a la inversa, que tiene una interfaz con método de acceso y anotación, y una implementación generada en tiempo de ejecución, que se basa en los métodos anotados, se puede hacer.)

+0

Sí, se puede hacer: Java es un lenguaje altamente dinámico, y puede escupir y modificar clases a voluntad. La pregunta es "¿cuánto esfuerzo se requiere?" –

+0

Por supuesto, siempre es posible generar un objeto desde el archivo conf, pero sin conocer los métodos de antemano, no podrá usarlo sin recurrir a la reflexión o cosas como esta, y eso hace que esto sea menos interesante. . – penpen

+0

@Jonathan: IMO, la verdadera pregunta es "¿cuál es el punto?" como @penpen señala, solo puede llamar a los métodos novedosos getXXX utilizando la reflexión (o desde otro código generado). –

1

La herramienta de procesamiento de anotación (apt) no puede modificar clases (aunque puede crear otros nuevos). Para modificar la clase en tiempo de compilación, probablemente necesite editar el AST (como lo hace Project Lombok). El enfoque más simple probablemente sería generar las clases y luego usar la biblioteca generada como una dependencia para otro código.

3

Existen innumerables marcos que logran eso para XML con varios grados de configuración necesarios. El estándar incluido con Java es JaxB pero no es exactamente un marco de persistencia xml de liner ...

El problema es que usar el archivo de propiedades solo funcionará mejor que XML (o JSON, ...) en la mayoría clases triviales.Cuando la clase se vuelva un poco más compleja, el archivo de propiedades se convertirá en una pesadilla. Otro problema es que con las clases triviales, no hay mucha diferencia entre Xml y las propiedades.

Eso significa que el alcance del proyecto será bastante limitado. Principalmente útil para proyectos que tienen un montón de archivos de propiedades simples.

En la gran aplicación con la que trabajé, la lectura de propiedades de tipo fuerte se realiza con bastante frecuencia utilizando un simple método de fábrica.

Foo foo = Foo.loadFrom("foo.properties"); 

class Foo { 
    static Foo loadFrom(String fileName) { 
     Properties props = new Properties(); 
     props.load(...); 

     Foo foo = new Foo(); 
     foo.setKeyFoo(props.get("KeyFoo")); 
     ... 
     return foo; 
    } 
    ... 
} 
+0

Probablemente o use la reflexión en tiempo de ejecución para cargar el objeto dinámicamente: puede leer la anotación (disponible desde la clase, el método y Field Objects) y obtener/establecer propiedades dinámicamente (usar apache common-beans puede ayudarlo). Trate de mantenerlo simple, aunque si tiene pocas configuraciones. Para cargas de configuración, Xml le brinda estructura, validación y documentación (en XSD), ... – vdr

+0

+1 para JAXB. Lo cambié por mis configuraciones. También me obligó a limpiar mi distinción de configuración/estado. –

1

Algo así como JFig (fea OMI), Commons Configuration o EasyConf?

+0

OT: Interesante: aunque hay muchas bibliotecas para leer propiedades, ninguna de ellas proporciona iteración ordenada, por lo que no puedo obtener las propiedades en el orden en que están definidas en el archivo. Así que extendí Propiedades y delegué todos los métodos de Map a ListOrderedMap. –

+0

Nueva alternativa a JFig: https://github.com/sofdes/config-generation-maven-plugin – user1016765

0

El OP desea asignar un archivo de propiedades a una API de Java de modo que cada propiedad nombrada en el archivo corresponda a un método getter de nombre similar en la API. Supongo que una aplicación usaría esta API para obtener valores de propiedad sin tener que usar cadenas de nombre de propiedad.

El problema conceptual es que un archivo de propiedades no es fundamentalmente una entidad estáticamente tipada. Cada vez que alguien edita un archivo de propiedades, puede agregar nuevas propiedades y, por lo tanto, cambiar el "tipo" del archivo de propiedades ... y, por implicación, la firma de la API correspondiente. Si verificamos que no hubo propiedades inesperadas cuando la aplicación Java cargó el archivo de propiedades, entonces tenemos una verificación de tipo dinámica explícita. Si no buscamos propiedades inesperadas (por ejemplo, mal nombradas), tenemos una fuente de errores. Las cosas se vuelven aún más complicadas si desea que los tipos de valores de las propiedades sean algo más que una Cadena.

La única manera en que podría hacerlo correctamente sería inventar el concepto de un esquema para un archivo de propiedades que especifica los nombres de las propiedades y los tipos de los valores de las propiedades. Luego, implemente un editor de archivos de propiedades que garantice que el usuario no pueda agregar propiedades que entren en conflicto con el esquema.

Y en este punto debemos reconocer que una mejor solución sería usar XML como representación de archivo de propiedades, un editor de esquemas XML para editar archivos de propiedades y JAXP o algo similar para mapear el archivo de propiedades a API de Java .

+0

No entendí exactamente lo que quiere decir con "y, por lo tanto, cambie el" tipo "del archivo" ... Pero Supongo que lo que te preocupa son los diferentes tipos de datos en el archivo? Si es así; para este caso los tipos de retorno son siempre String ... Entonces agregar una nueva entrada al archivo hará que el generador genere un nuevo método de acceso ... – erdogany

+0

@erdogany: No. Estoy hablando de los nombres de las propiedades cambiando. Si lee la pregunta, verá que el OP desea asignar cada propiedad a un método getter distinto cuyo nombre se deriva del nombre de la propiedad. –

1

Otra forma es utilizar un marco de enlace de datos que hace esto. Incluso uno que no parece soportar directamente que podría funcionar: por ejemplo, Jackson El procesador JSON permitiría que esto se hiciera por algo como:

ObjectMapper m = new ObjectMapper(); MyBean bean = m.convertValue (properties, MyBean.class); // (nota: requiere el código más reciente del tronco; de lo contrario debe escribir primero, leer)

que funciona siempre que las entradas en el mapa de propiedades coincidan con las propiedades lógicas del frijol, y los valores de cadena se pueden convertir a valores subyacentes coincidentes.

0

Creo que esto resolverá su problema He escrito sobre este framework inmobiliario durante el último año. Proporcionará varias formas de cargar propiedades y las tendrá fuertemente tipadas también.

Tenga una mirada en http://sourceforge.net/projects/jhpropertiestyp/

Es de código abierto y totalmente documentado

Aquí está mi breve descripción de SourceForge:

JHPropertiesTyped will give the developer strongly typed properties. Easy to integrate in existing projects. Handled by a large series for property types. Gives the ability to one-line initialize properties via property IO implementations. Gives the developer the ability to create own property types and property io's. Web demo is also available, screenshots shown above. Also have a standard implementation for a web front end to manage properties, if you choose to use it. 

Complete documentation, tutorial, javadoc, faq etc is a available on the project webpage. 
Cuestiones relacionadas