Spring expone el patrón Observable para que las aplicaciones puedan responder a eventos generados por el contexto, e incluso implementar una gestión personalizada de eventos propios.

Eventos

Para que un bean reciba eventos tiene que implementar la interface ApplicationListener. Los eventos que se reciben son por defecto de la clase ApplicationEvent, aunque están subclasificados, y además se permite definir eventos propios.

Spring detecta automáticamente cuando un bean implementa la interface y le notifica por defecto los siguientes tipos de eventos referidos al contexto:

ContextRefreshedEvent: Enviado cuando se inicializa el contexto o se llama a su método refresh, y todos los beans han sido detectados y activados.

ContextStartedEvent: Enviado cuando se llama al método start del contexto, y todos los beans que implementan una interface Lifecycle para el control de ciclo de vida han recibido una notificación de arranque.

ContextStoppedEvent: Enviado cuando se llama al método stop del contexto, y todos los beans que implementan una interface Lifecycle para el control de ciclo de vida han recibido una notificación de parada.

ContextClosedEvent: Enviado cuando se llama al método close del contexto, todos los beans de tipo Singleton han sido destruidos, y el contexto ya no puede recuperarse.

RequestHandledEvent: Este evento aplica sólo a entornos web, para su gestión por parte de los servlets, y es enviado cuando un petición HTTP (request) ha sido completada.

Event

Los eventos propios se crean extendiendo de la clase base ApplicationEvent y añadiendo los atributos que se quieran:

public class Quejido extends ApplicationEvent {

    private String motivo;

    public Quejido(Object source, String motivo) {
        super(source);

        this.motivo = motivo;
    }
}

Listener

Para que una clase adopte el rol de listener basta con que implemente la interface ApplicationListener, tantas veces como tipos distintos de mensajes quiera recibir:

public class Cotilla implements ApplicationListener<Quejido> {

    public void onApplicationEvent(Quejido quejido) {
    }
}

Y declarar el bean correspondiente en el fichero de configuración:

<bean id="cotilla" class="com.empresa.Cotilla"/>

Publisher

Para que un bean publique eventos se le tiene que inyectar una dependencia de tipo ApplicationEventPublisher. Y la forma recomendada es utilizar una de las interfaces de tipo Aware que ofrece Spring, para cuando se quiere acceder a alguna de las interfaces que implementa el contexto, concretamente la interface ApplicationEventPublisherAware:

public class Quejica implements ApplicationEventPublisherAware {

    private ApplicationEventPublisher publisher;

    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    public void queja(String motivo) {
        Quejido quejido = new Quejido(this, motivo);

        this.publisher.publishEvent(quejido);
    }
}

Y declarar el bean correspondiente en el fichero de configuración:

<bean id="quejica" class="com.empresa.Quejica"/>

Spring detecta automáticamente cuando un bean implementa la interface, e inyecta directamente la dependencia, de forma que pueda utilizarla para publicar eventos.

Finalmente, se puede probar el sistema con las siguientes líneas de código:

Cotilla cotilla = context.getBean(Cotilla.class);

Quejica quejica = context.getBean(Quejica.class);
quejica.queja("¡Como está el país!");

Por último, comentar que por defecto los eventos se consumen de forma asíncrona, dentro de un mismo contexto, para permitir utilizar una misma transacción en caso de existir. No obstante, Spring permite implementar otro tipo de estrategias más avanzadas.