java dynamic configuration guice

java - ¿Cómo se hacen enlaces dinámicos en Guice que requieren una instancia inyectada?



dynamic configuration (1)

Recuerde que todos los métodos de configuración configuran todas las vinculaciones en un Injector antes de que pueda ocurrir cualquier inyección. Dicho eso, algunas cosas:

  1. La vinculación de las propiedades de @Named a los contenidos de una única instancia de Properties es muy útil, hay un Names.bindProperties(...) que lo hace automáticamente. El único truco es que necesita tener la instancia de Properties en el momento en que se ejecuta configure() .

    Si están todos disponibles al mismo tiempo, no se preocupe por vincular las propiedades en un módulo y vincular la aplicación en otro. Mientras todos entren en el mismo Injector , Guice los combinará a todos y les permitirá satisfacer las dependencias de los demás.

  2. Los proveedores pueden devolver diferentes instancias, y generalmente lo hacen, pero tiene razón en que no lo ayudará a diferenciar entre las claves. Si inyectar directamente la instancia de Properties es demasiado feo, considere hacer una fábrica liviana en su lugar:

    public class ConfigOracle { @Inject private Properties properties; public String getAsString(String key) { ... } public int getAsInt(String key) { ... } } public class SomeConfigUser { @Inject private ConfigOracle configOracle; public void doStuff() { doStuffBasedOn(configOracle.getAsString("my.properties.key")); } }

  3. Nunca debe necesitar inyectar una Binder (o cualquier otra cosa) en un Módulo.

    • Si implementa Module , la binder será un parámetro de configure() . Si extiende AbstractModule como debería, simplemente llame al método binder() .
    • Puede pasar dependencias mediante argumentos de constructor al Módulo, si es necesario, que (en lo que a mí respecta) es la única forma en que los Módulos deberían variar los enlaces que crean.
    • No hay ninguna razón por la que no puedas crear un Módulo a través de un Inyector, pero primero tendrás que tener un Inyector, y parece que estás tratando de escapar con solo tener uno.
    • Si necesita otras instancias desde el inyector, siempre puede escribir una implementación de Provider con @Inject fields / methods / constructors, o incluso tomar los parámetros en un método @Provides (que se completará con las dependencias automáticamente ).

En general, todavía estoy a favor del enfoque de inyector hijo (¡gracias por el enlace y complemento a mi respuesta anterior!), Que se ajusta mejor a su descripción de "consolidaciones dinámicas basadas en una instancia inyectada", y sería literalmente así de simple:

class PropertiesModule extends AbstractModule { Properties properties; PropertiesModule(Properties properties) { this.properties = properties; } @Override public void configure() { Names.bindProperties(binder(), properties); } } Injector oldInjector = Guice.createInjector(allYourOtherModules); Module myModule = new PropertiesModule(oldInjector.get(Properties.class)); Injector injector = oldInjector.createChildInjector(myModule);

Me gustaría crear un Módulo que enlace dinámicamente instancias a anotaciones con nombre. El caso de uso es que me gustaría vincular automáticamente los valores en mi configuración con la clave en el archivo de propiedades que es el valor @Named.

Sin embargo, la configuración está vinculada en un módulo diferente, así que necesito la configuración para ser inyectado. Las soluciones que he analizado son:

  1. Enlace en el método de configuración () Este método no se inyecta y no puedo obtener la configuración base.

  2. Usar un proveedor / @ Provides. Los proveedores solo enlazan una sola instancia.

  3. Usando MultiBinder. Mi caso de uso es un poco diferente de lo que proporciona esta extensión. El enlace múltiple le permite vincular varias instancias por separado y luego inyectarlas como un tipo de colección más complejo. Me gustaría vincular cada instancia por separado y tenerlas identificadas de forma única para inyección posterior.

  4. Use un childinyector. Lamentablemente, esto no es posible sin una modificación extensa del código existente. Esta respuesta es una muy buena descripción de cómo resolver este problema de esta manera.

  5. Inyecte la carpeta de alguna manera. (Empecé a tener un poco de hackier) Guice permite inyectar el Inyector para su uso posterior, intenté inyectar el Binder en el Módulo a través de un método @Provides y luego usar el encuadernador directamente para hacer múltiples binds dentro del método. Guice no inyectaría la carpeta.