Spring(22)——ApplicationEvent

22 ApplicationEvent

Spring allows us to publish ApplicationEvent events in the ApplicationContext, and then the corresponding ApplicationListener can be used to listen to the corresponding events. When an ApplicationEvent is published, the bean instance that implements the ApplicationListener interface in the corresponding bean container will receive the corresponding notification, that is, the corresponding ApplicationListener callback method will be called.

22.1 Built-in events

Spring itself has provided us with several ApplicationEvents, which will be automatically published by Spring at the corresponding time, and users can monitor them if necessary. Specifically, there are the following types.

22.1.1 ContextRefreshedEvent

ContextRefreshedEvent will be published when the corresponding ApplicationContext calls the refresh() method, which also includes directly using the configuration file to initialize the corresponding ApplicationContext, because the corresponding refresh() method will also be called at this time. In the refresh() method, the ContextRefreshedEvent is released at the end of the method, that is to say, when the ContextRefreshedEvent is released, the bean definitions in the corresponding ApplicationContext have been loaded, and the corresponding BeanFactoryPostProcessor has been executed. The beans that need to be instantiated have also been instantiated.

22.1.2 ContextStartedEvent

ContextStartedEvent will be published when the corresponding ApplicationContext calls the start() method. At this point, the corresponding start() method has been called back to all beans that implement the LifeCycle interface.

22.1.3ContextStoppedEvent

ContextStoppedEvent will be published when the corresponding ApplicationContext calls the stop() method. At this point, the corresponding stop() method has been called back to all beans that implement the LifeCycle interface.

22.1.4ContextClosedEvent

ContextClosedEvent will be published when the corresponding ApplicationContext calls the close() method. At this point all resources have been destroyed. ContextRefreshedEvent, ContextStartedEvent, ContextStoppedEvent and ContextClosedEvent all inherit from ApplicationContextEvent because they are events for ApplicationContext.

22.1.5 ServletRequestHandledEvent

ServletRequestHandledEvent will be published after Spring has processed an HttpRequest request, that is, the corresponding HttpRequest has been completed. ServletRequestHandledEvent can only be used when using DispatcherServlet, when DispatcherServlet finishes processing an HttpRequest request, it will publish a ServletRequestHandledEvent. ServletRequestHandledEvent inherits from RequestHandledEvent, so when we need to listen to RequestHandledEvent, we can also listen to ServletRequestHandledEvent.

22.2 Custom Events

The event that Spring can publish is ApplicationEvent, which is an abstract class that inherits EventObject. Its source code is as follows, we can see that it has only one constructor, and an object must be passed in as the publisher of the current event release.

public abstract class ApplicationEvent extends EventObject {

	/** use serialVersionUID from Spring 1.2 for interoperability */
	private static final long serialVersionUID = 7099057708183571937L;

	/** System time when the event happened */
	private final long timestamp;


	/**
	 * Create a new ApplicationEvent.
	 * @param source the component that published the event (never {@code null})
*/publicApplicationEvent(Objectsource) {
		super(source);
		this.timestamp =System.currentTimeMillis();	 
	   
	}


	/**
	 * Return the system time in milliseconds when the event happened.
*/publicfinallonggetTimestamp() {
		returnthis.timestamp;	 
	    
	}

}

If the user needs to customize the event, he should customize a class that inherits ApplicationEvent. Except for the source object that must be provided to construct the parent class, other information can be customized by the user. As follows, we simply implement a custom ApplicationEvent, then we can use the custom MyApplicationEvent to publish as ApplicationEvent when publishing events later.

public  class  MyApplicationEvent  extends  ApplicationEvent {

	private static final long serialVersionUID = 1L;

	public  MyApplicationEvent ( Object  source ) {
		 super (source);
	}

}

22.3 Event Publishing

The publication of events is defined by the publishEvent() method in the ApplicationEventPublisher interface, which is defined as follows.

public interface ApplicationEventPublisher {

	void publishEvent(ApplicationEvent event);

}

The ApplicationContext interface inherits the ApplicationEventPublisher interface, so we can directly use the ApplicationContext to publish events. In the following example, we inject an ApplicationContext into Hello, and then publish a custom MyApplicationEvent through the injected ApplicationContext when calling its doSomething() method.

@Component
public class Hello {

	@Autowired
	private ApplicationContext context;
	
	public  void  doSomething () {
		 System . out . println( " ----do something.... " );
		 // Publish a custom MyApplicationEvent 
		context . publishEvent( new  MyApplicationEvent ( this ));
	}

}

In addition to directly using ApplicationContext for event publishing, Spring also provides us with an Aware interface corresponding to the ApplicationEventPublisher interface for publishing events - ApplicationEventPublisherAware, which is the same as other Aware interfaces provided by Spring. When a bean implements this interface, , Spring will call the callback method to pass in an ApplicationEventPublisher after instantiating the corresponding bean, usually the current ApplicationContext object passed. So we can also make our bean implement the ApplicationEventPublisherAware interface, and then use the ApplicationEventPublisher passed in by Spring to publish the corresponding events. So the above example can also be changed to the way of implementing ApplicationEventPublisherAware, the example is as follows.

@Component
public class Hello implements ApplicationEventPublisherAware {

	private  ApplicationEventPublisher eventPublisher;
	
	public  void  doSomething () {
		 System . out . println( " ----do something.... " );
		 // Publish a custom MyApplicationEvent 
		this . eventPublisher . publishEvent( new  MyApplicationEvent ( this ));
	}

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

}

22.4 Event listener

Event monitoring needs to define the corresponding listener. The listener used to listen to ApplicationEvent in Spring is defined by ApplicationListener. ApplicationListener is an interface, which is defined as follows. We can see that generics are used in this interface, that is, it can be specified to only listen to a certain type of ApplicationEvent.

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	void onApplicationEvent(E event);

}

ApplicationListener will call its onApplicationEvent() method every time it listens to the corresponding ApplicationEvent. So if we want to define a listener that only listens to the previously customized MyApplicationEvent, we can define it as follows. If we want to listen to all ApplicationEvents, we can specify the generic type as ApplicationEvent, that is, change the following MyApplicationEvent to ApplicationEvent.

public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {

	public void onApplicationEvent(MyApplicationEvent event) {
		System.out.println(event.getSource() + "****************" + event.getTimestamp());;
	}

}

Only by implementing the ApplicationListener interface, the corresponding listener cannot listen to the corresponding event. We need to define them as a bean in the bean container so that when Spring publishes an event it will be passed to the matching listener. So for the above listener, we can configure the following in the corresponding XML configuration file when configuring based on XML.

<bean class="com.app.MyApplicationListener"/>

If it is an annotation-based scan, it can be annotated with annotations such as @Component on MyApplicationListener.

(Note: This article is written based on Spring 4.1.0)

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326293754&siteId=291194637