Spring Framework 004 - Como ejecutar tareas periódicas en Spring
Para hacer que Spring ejecute periódicamente algunos de los métodos de nuestras clases, debemos indicarle scheduled-tasks
en el fichero Spring XML de configuración o bien anotar los métodos de nuestras clases con la anotación @Scheduled
Vamos a hacer un ejemplo tanto con fichero de configuración XML de Spring como con anotaciones. Puedes verlo completo en ScheduledMain.java
Tareas periódicas[editar]
Lo primero es hacer en nuestra clase un método público, con el nombre que más nos guste, al que Spring llamará periódicamente. No hace falta meter ahí bucles o timers, Spring se encarga de ellos. Sólo debemos implementar lo que queremos que se haga en un instante concreto. Un ejemplo puede ser
public class ScheduledXMLSample {
public void repeat(){
System.out.println(getClass().toString() + ".repeat() llamado");
}
}
Spring llamará a nuestro método repeat()
periódicamente cada cierto tiempo, según lo configuremos. Podemos configurar Spring bien en el fichero XML, bien con una anotación en la clase. Veamos ambos casos.
task:scheduled-tasks[editar]
Para configurarlo en el fichero XML de Spring, tendríamos que poner algo así
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.2.xsd">
<bean id="scheduledXMLSample" class="com.chuidiang.pruebas.scheduled.ScheduledXMLSample"/>
<task:scheduled-tasks>
<task:scheduled ref="scheduledXMLSample" method="repeat" fixed-rate="2000"/>
</task:scheduled-tasks>
</beans>
En el tag <beans>
del principio hemos puesto una línea con xmlns:task
y en la parte de xsi:schemaLocation
hemos puesto un par de líneas relativas task
. Esto nos permite usar las etiquetas task:
en nuestro fichero Spring que nos permitirán configurar nuestras tareas periódicas.
Luego simplemente instanciar nuestro bean ScheduleXMLSample
Y finalmente, con <task:scheduled-tasks>
empezamos nuestra lista de tareas periódicas. Podemos poner las que queramos, llamando a distintos métodos de distintas clases. En nuestro ejemplo, sólo llamaremos al método repeat()
de la clase ScheduledXMLSample
Así que en la lista metemos un <task:scheduled>
. En ref
le pasamos el nombre de nuestro bean instanciado scheduledXMLSample
, en method
el método de ese bean al que tiene que llamar y luego podemos indicar cada cuanto llamarlo. Tenemos ahí varias opciones, incluso para poner a la vez, pero solo hemos usado una en el ejemplo
- fixed-rate, la del ejemplo, nos dice cada cuanto llamar a ese método. En el ejemplo, 2000 ms, es decir, 2 segundos. Se hará esto independientemente de que la ejecución anterior haya terminado o no.
- fixed-delay es similar a la anterior, pero espera el tiempo que se indique entre una ejecución y la siguiente. Es decir, entre ejecuciones puede pasar más tiempo de lo que diga el fixed-delay, porque hay que sumar el tiempo que tarda el método en ejecutarse.
- cron. Aquí podríamos poner una expresión de [[1]], que nos permite cosas más complejas que ejecuciones cada x tiempo. Por ejemplo, con cron podemos poner que queremos ejecutar los días laborables (lunes a viernes) a las 12 de la mañana.
- initial-delay. Podemos poner un tiempo de espera antes de la primera llamada periódica. A partir de ahí comenzarán las llamadas periódicas según hayamos indicado con alguna de las opciones anteriores.
Listo, si hacemos un main y ejecutamos, tendríamos algo como esto
class com.chuidiang.pruebas.scheduled.ScheduledXMLSample.repeat() llamado class com.chuidiang.pruebas.scheduled.ScheduledXMLSample.repeat() llamado class com.chuidiang.pruebas.scheduled.ScheduledXMLSample.repeat() llamado ...
Anotación @Scheduled[editar]
La otra opción, si nos gustan más las anotaciones, es anotar los métodos con @Scheduled
. Esta anotación admite las mismas configuraciones que en el fichero XML de Spring. Nuestra clase quedaría
@Component
public class ScheduledAnnotatedSample {
@Scheduled(initialDelay = 2000, fixedRate = 1000)
public void repeat(){
System.out.println(getClass().toString()+".repeat() llamado");
}
}
Ningún truco especial, con @Component
indicamos a Spring que instancie esta clase y con @Scheduled
anotamos el método que queramos que se ejecute periódicamente. Esta vez le hemos puesto initialDelay
de 2 segundos (2000 ms) y un fixedRate
de 1 segundo (1000 ms)
En el fichero de Spring, debemos poner lo siguiente
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.2.xsd">
<context:component-scan base-package="com.chuidiang.pruebas.scheduled"/>
<task:annotation-driven/>
</beans>
En la parte inicial, igual que en el caso anterior, todo lo necesario para poder usar las etiquetas task:
. Con <context:component-scan>
le indicamos a Spring en qué paquetes buscar clase para instanciar, es decir, con anotación @Component
. Y con <task:annotation-driven>
le indicamos a Spring que haga caso a las anotaciones @Scheduled
en los métodos de esas clases que ha instanciado.
Y todo listo, haciendo un main y ejecutando
jun. 10, 2023 7:01:28 P. M. org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor finishRegistration INFORMACIÓN: No TaskScheduler/ScheduledExecutorService bean found for scheduled processing class com.chuidiang.pruebas.scheduled.ScheduledAnnotatedSample.repeat() llamado class com.chuidiang.pruebas.scheduled.ScheduledAnnotatedSample.repeat() llamado class com.chuidiang.pruebas.scheduled.ScheduledAnnotatedSample.repeat() llamado class com.chuidiang.pruebas.scheduled.ScheduledAnnotatedSample.repeat() llamado
Tenemos un mensaje de INFO inicial que es un aviso de Spring indicando que no hemos definido ningún ejecutor de tareas, así que usará el que tiene por defecto. Podríamos crear uno nuestro propio para hacerle alguna configuración especial, pero es tema para otro tutorial.