2010-11-03 17 views
5

Tengo un archivo de propiedad y, utilizando el titular del lugar de la propiedad Spring, establezco valores para los beans Spring. Ahora, este archivo de propiedades puede modificarse durante el tiempo de ejecución. ¿Hay alguna manera de actualizar las propiedades de los granos de primavera con este valor de propiedad recientemente modificado? Especialmente, tengo muchos frijoles singleton? ¿Cómo puedo actualizarlos con los nuevos valores? ¿Ya hay una solución para esto o debería ser un código personalizado? Si aún no existe, ¿alguien puede dar el mejor enfoque para lograr esto? ¡Gracias!Muelle - Sustitución de los valores de las propiedades de los frijoles con los nuevos valores del Archivo de propiedades

PD: Mi aplicación es una aplicación por lotes. Utilizo la configuración de cuarzo basada en Spring para programar los lotes.

Respuesta

3

Voy a dejar esto en referencia, pero la respuesta actualizada está por debajo del divisor:

bien la interfaz ConfigurableApplicationContext contiene un método refresh(), que debe ser lo que quiera, pero la pregunta es: ¿Cómo acceder ese método. Cualquiera que sea la forma en que lo hace, usted comenzará con un grano que tiene una dependencia de tipo ConfigurableApplicationContext:

private ConfigurableApplicationContext context; 
@Autowired 
public void setContext(ConfigurableApplicationContext ctx){ 
    this.context = ctx; 
} 

Ahora las dos opciones básicas Yo sugeriría sería ya sea

  1. utilice el Task Execution Framework y permita que su bean observe los recursos de la propiedad con regularidad, actualizando el ApplicationContext cuando encuentre cambios o
  2. expose the bean to JMX, lo que le permite activar manualmente la actualización.

relación con los comentarios: ya que parece imposible para refrescar todo el contexto, una estrategia alternativa sería la creación de un grano de propiedades de la fábrica e inyectar que en todos los otros granos.

public class PropertiesFactoryBean implements FactoryBean<Properties>{ 

    public void setPropertiesResource(Resource propertiesResource){ 
     this.propertiesResource = propertiesResource; 
    } 

    private Properties value=null; 
    long lastChange = -1L; 

    private Resource propertiesResource; 

    @Override 
    public Properties getObject() throws Exception{ 
     synchronized(this){ 
      long resourceModification = propertiesResource.lastModified(); 
      if(resourceModification != lastChange){ 
       Properties newProps = new Properties(); 
       InputStream is = propertiesResource.getInputStream(); 
       try{ 
        newProps.load(is); 
       } catch(IOException e){ 
        throw e; 
       } finally{ 
        IOUtils.closeQuietly(is); 
       } 
       value=newProps; 
       lastChange= resourceModification; 
      } 
     } 
     // you might want to return a defensive copy here 
     return value; 
    } 

    @Override 
    public Class<?> getObjectType(){ 
     return Properties.class; 
    } 

    @Override 
    public boolean isSingleton(){ 
     return false; 
    } 

} 

Usted podría inyectar este grano de propiedades en todos sus otros granos, sin embargo, usted tiene que tener cuidado de utilizar siempre el alcance de prototipo. Esto es particularmente complicado dentro de los granos simples, a solution can be found here.

Si no desea inyectar métodos de búsqueda por todo el lugar, también se puede inyectar un grano de PropertyProvider así:

public class PropertiesProvider implements ApplicationContextAware{ 

    private String propertyBeanName; 
    private ApplicationContext applicationContext; 

    public void setPropertyBeanName(final String propertyBeanName){ 
     this.propertyBeanName = propertyBeanName; 
    } 

    @Override 
    public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException{ 
     this.applicationContext = applicationContext; 
    } 

    public String getProperty(final String propertyName){ 
     return ((Properties) applicationContext.getBean(propertyBeanName)).getProperty(propertyName); 
    } 

} 
+0

¿No sería esta carga todo el contexto de la aplicación? ¿Puedes compartir alguna muestra? Soy bastante nuevo en Spring, así que puedo estar equivocado. También pensé en volver a cargar todo el contexto de la aplicación de primavera, pero eso significaría que otros procesos actualmente en ejecución podrían verse afectados. ¡O tal vez estoy pensando mal! – SJoe

+0

No, tienes razón, el contexto completo se actualizará. –

+0

En ese caso, mi proceso actual no se interrumpiría. La mía es una aplicación por lotes y podría llevar horas completar un proceso. Además, tengo un SchedularFactoryBean configurado a través de Spring. Mi pregunta es, si recargo completamente el contexto de la aplicación, ¿no se reiniciaría el planificador? – SJoe

Cuestiones relacionadas