preface

An introduction on the use of internationalization and the initialization source source, then keep reading, will enter initApplicationEventMulticaster, onRefresh and registerListeners related operation logic.

This section is mainly about initializing event broadcasters and registering listeners. The onRefresh part needs to be subclassed. Therefore, this paper mainly introduces the following parts:

  1. What are Spring events?
  2. How are listeners used?

What are Spring events?

This section is introduced in 1.15.2. Standard and Custom Events on the official website.

Spring provides event handling in ApplicationContext through the ApplicationEvent class and the ApplicationListener interface. If a bean that implements the ApplicationListener interface is deployed into the context, the bean will be notified each time an ApplicationEvent is published to the ApplicationContext. In essence, this is the standard observer design pattern.

There are three main parts: event, event publisher, and event listener.

  1. Event: ApplicationEvent. To customize the event, you need to create a class that inherits ApplicationEvent.
  2. Event Publisher: To achieve a ApplicationEventPublisher and ApplicationEventMulticaster because ApplicationContext ApplicationEventPublisher, So event publishing can use ApplicationContext directly.
  3. Event Listener: ApplicationListener, which receives messages by creating a class that implements ApplicationListener and registers it as a Spring bean.

Spring also provides and has some built-in listeners, which can be viewed on the official website without being described here.

Using listeners

In brief, it is mainly divided into the following parts:

  1. Register event
  2. Register listeners
  3. Publish event

When the interface invokes the publish event, the listener acts accordingly.

1. Register events

Create the MyApplicationEvent class and inherit ApplicationEvent

public class MyApplicationEvent extends ApplicationEvent {

	private static final long serialVersionUID = 5366526231219883438L;
	private String message;

	/**
	 * Create a new {@code ApplicationEvent}.
	 *
	 * @param source the object on which the event initially occurred or with
	 *               which the event is associated (never {@code null})
	 */
	public MyApplicationEvent(Object source, String message) {
		super(source);
		this.message = message;
	}

	public String getMessage(a) {
		returnmessage; }}Copy the code

2. Register listeners

@Component
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {

	@Override
	public void onApplicationEvent(MyApplicationEvent event) {

		System.out.println("MyApplicationListener receives message:"+ event.getMessage()); }}Copy the code

You can also use the @eventListener annotation here.

@Component
public class MyAnnotationApplicationListener {

	@EventListener(classes = MyApplicationEvent.class)
	public void myApplicationEventListener(MyApplicationEvent event) {

		System.out.println("Received events using annotations:"+ event.getMessage()); }}Copy the code

Use 3.

Because AnnotationConfigApplicationContext implements ApplicationContext, and realized the ApplicationEventPublisher ApplicationContext, So there’s no problem passing in the current context.

public class AnnotationConfigApplicationTest {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

		context.register(JavaConfig.class);


		context.refresh();

		MyApplicationEvent myApplicationEvent = new MyApplicationEvent(context, "Call potatoes, call potatoes!"); context.publishEvent(myApplicationEvent); }}Copy the code

Log output:

The source code section

initApplicationEventMulticaster

This is similar to initializing the message source above, which looks for the Bean with the specified name and uses the default if it cannot be found.

protected void initApplicationEventMulticaster(a) {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();

    / / contains applicationEventMulticaster Bean
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isTraceEnabled()) {
            logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); }}else {
        / / use the SimpleApplicationEventMulticaster create an event publishing
        SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        simpleApplicationEventMulticaster.setApplicationStartup(getApplicationStartup());
        this.applicationEventMulticaster = simpleApplicationEventMulticaster;
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isTraceEnabled()) {
            logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
                    "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]"); }}}Copy the code

onRefresh

This one needs to be subclassed, so I’m not going to get in here by powering off. So I won’t introduce you.

registerListeners

protected void registerListeners(a) {
    // Add a bean that implements ApplicationListener as a listener.
    // Other listeners can be added as non-beans without affecting them.

    // Register statically specified listeners first.
    // Register statically specified listeners first
    for(ApplicationListener<? > listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); }// Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let post-processors apply to them!
    // Only the addition is not executed
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true.false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // Publish early application events now that we finally have a multicaster...
    // Publish the early time and set earlyApplicationEvents to null
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if(! CollectionUtils.isEmpty(earlyEventsToProcess)) {for(ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); }}}Copy the code

conclusion

Main content of this article is to introduce the use of Spring events, at the same time introduced initApplicationEventMulticaster, onRefresh and registerListeners part of the source code.

Related to recommend

  • Spring source learning 13: initMessageSource
  • The Spring source learning 12: registerBeanPostProcessors
  • Spring source study 11: invokeBeanFactoryPostProcessors