Spring Event Listeners

  Spring is the core ApplicationContext , which is responsible for managing the complete lifecycle of Bean; when loading Bean, ApplicationContext to publish certain types of events; for example, when the context start, ContextStartedEvent announced, when the context is stopped, ContextStoppedEvent news release;

  Interface to provide event handling in the ApplicationContext class and by ApplicationEvent ApplicationListener; if a Bean implementation ApplicationListener interface, each ApplicationEvent be published to the ApplicationContext, the Bean instance will be notified; similar MQ publish-subscribe;

   

  ApplicationEvent UML diagram is as follows:

  

 

  • Spring Common events

No. Spring Event
1 ContextRefreshedEvent: when the ApplicationContext is initialized or refreshed, the event is released; it can also occur using the refresh () method in ConfigurableApplicationContext interface; container refresh is complete (all bean are created entirely) will be released this event;
2 ContextStartedEvent: When ConfigurableApplicationContext interface start () method to start ApplicationContext, the event is released;
3 ContextStoppedEvent: When ConfigurableApplicationContext interface stop () method to stop ApplicationContext, released this event;
4 ContextClosedEvent: When ConfigurableApplicationContext interface close () method to close ApplicationContext, the event is released;
5 RequestHandledEvent: In Web applications, when the end of a http request triggers the event ;

 

  • ApplicationContext

  That ApplicationContext application context inherited from the BeanFactory interface can be used to obtain Bean Spring managed object instances;

  ApplicationContextAware: Aware property is injected, and the ApplicationContextAware ApplicationContext difference is, when initialization Spring container, realized Bean ApplicationContextAware interface automatically injected ApplicationContext;

 

  Custom ApplicationContextAware

@Component
public class ApplicationContextProvider implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    /**
     * Context instances
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * Get context
     * @return
     */
    public ApplicationContext getApplicationContext() {
        return this.applicationContext;
    }

    /**
     * Get Bean instances by class name
     * @param name
     * @return
     */
    public Object getBean(String name) {
        return this.applicationContext.getBean(name);
    }

    /**
     * Get Bean instance bytecode
     * @Param clazz
     * @param <T>
     * @return
     */
    public <T> T getBean(Class<T> clazz) {
        return this.applicationContext.getBean(clazz);
    }
}

  

  

  • ApplicationListener

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}

  

  ApplicationListenerMonitor ApplicationEventevents and their subclasses;

 

  AbstractApplicationContext.java

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
    ...
}

  

  ConfigurableApplicationContext: SPI interfaces implemented by most application context; in addition to providing a method of client application context, the configuration also provides the application context ApplicationContext interface functionality;

 

  refresh method to execute loading the container

public void refresh() throws BeansException, IllegalStateException {
    ...
    // Initialize event multicaster for this context.
    initApplicationEventMulticaster();
    
    ...
    // Last step: publish corresponding event.
	finishRefresh();
    ...
    
}


protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // find out whether there is "applicationEventMulticaster" component container
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isDebugEnabled()) {
            logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    else {
        // not the new "applicationEventMulticaster" components, and added to the vessel, is injected into the "applicationEventMulticaster", registerSingleton looks listener's existence within all registered listeners map, there is no operation is performed to put the map
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                         APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                         "': using default [" + this.applicationEventMulticaster + "]");
        }
    }
}

  

  finshRefresh method

protected void finishRefresh() {
    // Clear context-level resource caches (such as ASM metadata from scanning).
    clearResourceCaches();

    // Initialize lifecycle processor for this context.
    initLifecycleProcessor();

    // Propagate refresh to lifecycle processor first.
    getLifecycleProcessor().onRefresh();

    // Publish the final event.
    publishEvent(new ContextRefreshedEvent(this));

    // Participate in LiveBeansView MBean, if active.
    LiveBeansView.registerApplicationContext(this);
}

  

  publishEvent way to publish events

@Override
public void publishEvent(ApplicationEvent event) {
    publishEvent(event, null);
}


protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
    Assert.notNull(event, "Event must not be null");
    if (logger.isTraceEnabled()) {
        logger.trace("Publishing event in " + getDisplayName() + ": " + event);
    }

    // Decorate event as an ApplicationEvent if necessary
    ApplicationEvent applicationEvent;
    if (event instanceof ApplicationEvent) {
        applicationEvent = (ApplicationEvent) event;
    }
    else {
        applicationEvent = new PayloadApplicationEvent<>(this, event);
        if (eventType == null) {
            eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
        }
    }

    // Multicast right now if possible - or lazily once the multicaster is initialized
    if (this.earlyApplicationEvents != null) {
        this.earlyApplicationEvents.add(applicationEvent);
    }
    else {
        getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
    }

    // Publish event via parent context as well...
    // determine the current ApplicationContext there is no parent ApplicationContext
    if (this.parent != null) {
        if (this.parent instanceof AbstractApplicationContext) {
            ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
        }
        else {
            this.parent.publishEvent(event);
        }
    }
}

  

  AbstractApplicationEventMulticaster provide basic listener registration function

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

}

  

 

  SimpleApplicationEventMulticaster.java

// given application is distributed to the corresponding event listener
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        Executor executor = getTaskExecutor();
        if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
        }
        else {
            invokeListener(listener, event);
        }
    }
}

// call the given event listener
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
    ErrorHandler errorHandler = getErrorHandler();
    if (errorHandler != null) {
        try {
            doInvokeListener(listener, event);
        }
        catch (Throwable err) {
            errorHandler.handleError(err);
        }
    }
    else {
        doInvokeListener(listener, event);
    }
}


private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
    try {
        onApplicationEvent // method call implementation ApplicationListener interface
        listener.onApplicationEvent(event);
    }
    catch (ClassCastException ex) {
        String msg = ex.getMessage();
        if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
            // Possibly a lambda-defined listener which we could not resolve the generic event type for
            // -> let's suppress the exception and just log a debug message.
            Log logger = LogFactory.getLog(getClass());
            if (logger.isDebugEnabled()) {
                logger.debug("Non-matching event type for listener: " + listener, ex);
            }
        }
        else {
            throw ex;
        }
    }
}

  

 

Guess you like

Origin www.cnblogs.com/coder-zyc/p/12232723.html
Recommended