九、ApplicationListener接口
ApplicationListener接口是Spring提供的接口,基于事件发布机制实现的。实现该接口的同时会指定一个泛型,当发布的事件类型于实现ApplicationListener接口的bean的泛型一致时,会回调这个bean的监听方法,并且把事件传递过去
@Component
public class SysApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
// 这里可以使用传递过来的事件参数, 来获得ApplicationContext
// 因此可以考虑在此处开启一些任务。比如缓存初始化, 读取定时任务, 开启线程任务等。
// 因为这个时候, Spring容器已经初始化好了, 并且还能获取到ApplicationContext。
ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();
System.out.println("==============Spring容器刷新完毕, 应用启动成功!!!==============");
}
}
原理剖析:
// 同样的,我们来到AbstractApplicationContext的refresh方法, 我们只看finishRefresh();
public class AbstractApplicationContext{
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory); <<------//往BeanFactory中放了ApplicationListenerDetector对象
// 并且把当前对象ApplicationContext传进去了
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster(); <<----------------// 初始化事件发布的多播器
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners(); <<----------------------------// 注册监听器
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh(); <<------------------------------// 发布对应的事件
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
// 进入finishRefresh()方法
protected void finishRefresh() {
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this)); // 发布ContextRefreshEvent事件, 注意this代表当前对象
// 即, 这个事件对象包装了ApplicationContext
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
// 具体发布的方法publishEvent, 第二个参数是null
protected void publishEvent(Object event, 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<Object>(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... // 同样的, 通知父容器发布该事件
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
// 好的, 我们来到多播器的源码SimpleApplicationEventMulticaster,
// 注意到SimpleApplicationEventMulticaster继承自AbstractApplicationEventMulticaster,
// 而AbstractApplicationEventMulticaster实现了BeanFactoryAware接口, 所以多播器能够拿到beanFactory,
// 进而能从bean工厂中拿到所有的监听器, 也就是实现了ApplicationListener接口的bean
public class SimpleApplicationEventMulticaster{
@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
// 这里在解析事件的类型
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
// 那么这里还存留着一个问题, 多播器是怎么拿到spring容器中所有的监听器的, 在后面我们来看看
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event); // ??多线程
}
});
}
else {
invokeListener(listener, event); // 回调监听器, 下面具体看看这个方法是怎么回调的
}
}
}
}
public class SimpleApplicationEventMulticaster{
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); // 好的, 继续调用
}
}
}
public class SimpleApplicationEventMulticaster{
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event); // 终于看到了, 这里在回调监听器重写的onApplicationEvent方法!!!
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || msg.startsWith(event.getClass().getName())) {
// Possibly a lambda-defined listener which we
// could not resolve the generic event type for
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
// 好的,到了这里, 我们来看看这个方法是怎么拿到所有的监听器的 getApplicationListeners
protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event,
ResolvableType eventType)
{
Object source = event.getSource();
Class<?> sourceType = (source != null ? source.getClass() : null);
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
// Quick check for existing entry on ConcurrentHashMap...
ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
if (this.beanClassLoader == null ||
(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader)
&&(sourceType == null ||
ClassUtils.isCacheSafe(sourceType, this.beanClassLoader))))
{
// Fully synchronized building and caching of a ListenerRetriever
synchronized (this.retrievalMutex) {
retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
// 前面似乎是在做一些缓存之类的, 重点看这里, retrieveApplicationListeners这里查询所有的监听器
retriever = new ListenerRetriever(true);
Collection<ApplicationListener<?>> listeners =
retrieveApplicationListeners(eventType, sourceType, retriever);
this.retrieverCache.put(cacheKey, retriever);
return listeners;
}
}
else {
// No ListenerRetriever caching -> no synchronization necessary
return retrieveApplicationListeners(eventType, sourceType, null);
}
}
private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType,
Class<?> sourceType,
ListenerRetriever retriever)
{
LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>();
Set<ApplicationListener<?>> listeners;
Set<String> listenerBeans;
synchronized (this.retrievalMutex) {
listeners =
// 这里在拿到多播器中的defaultRetriever的属性中的applicationListener
// 那么问题来了:首先知道defaultRetriever是多播器SimpleApplicationEventMulticaster中的私有内部类,
// applicationListenerBeans和applicationListeners是这个私有类的public属性。
// 那么这个监听器是怎样加入到defaultRetriever这个对象当中去的呢?
new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners);
listenerBeans =
new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans);
}
for (ApplicationListener<?> listener : listeners) {
if (supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
retriever.applicationListeners.add(listener);
}
allListeners.add(listener);
}
}
if (!listenerBeans.isEmpty()) {
BeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : listenerBeans) {
try {
Class<?> listenerType = beanFactory.getType(listenerBeanName);
if (listenerType == null || supportsEvent(listenerType, eventType)) {
ApplicationListener<?> listener =
beanFactory.getBean(listenerBeanName, ApplicationListener.class);
if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType))
{
if (retriever != null) {
retriever.applicationListenerBeans.add(listenerBeanName);
}
allListeners.add(listener);
}
}
}
catch (NoSuchBeanDefinitionException ex) {
// Singleton listener instance (without backing bean definition) disappeared -
// probably in the middle of the destruction phase
}
}
}
AnnotationAwareOrderComparator.sort(allListeners);
return allListeners;
}
// 我们可以看到AbstractApplicationContext的refresh方法中的调用的registerListener方法
public abstract class AbstractApplicationContext
protected void registerListeners() {
// Register statically specified listeners first.
// 获取到所有的监听器, 并且把它加入到多播器中的私有内部类对象defaultRetriever中去
// 这个getApplicationListener()方法可以获取到ApplicationContext的ApplicationListener的集合,
// 那么这个监听器的集合是什么时候添加进去的呢?我们可以看下ApplicationListenerDetector这个类,
// 它实现类BeanPostProcessor接口, 在识别bean实现了ApplicationListener接口的话,
// 就把它放到ApplicationContext的监听器集合里面去, 源码在下面
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!
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...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
}
class AbstractApplicationEventMulticaster{
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
synchronized (this.retrievalMutex) {
// Explicitly remove target for a proxy, if registered already,
// in order to avoid double invocations of the same listener.
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
// 添加到retriever的applicationListeners属性
this.defaultRetriever.applicationListeners.add(listener);
this.retrieverCache.clear();
}
}
@Override
public void addApplicationListenerBean(String listenerBeanName) {
synchronized (this.retrievalMutex) {
// 添加到retrivever的applicationListenerBeans属性
this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
this.retrieverCache.clear();
}
}
}
class ApplicationListenerDetector{
// 虽然ApplicationListenerDetector并没有实现BeanFactoryAware接口,但是这里它有了ApplicationContext属性
private transient final AbstractApplicationContext applicationContext;
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
// 判断是否实现了ApplicationListener接口
if (this.applicationContext != null && bean instanceof ApplicationListener) {
// potentially not detected as a listener by getBeanNamesForType retrieval
Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) {
// singleton bean (top-level or inner): register on the fly
// 添加到ApplicationContext中去,
// 那么问题又来了, applicationContext属性是怎样给到这个类的?
// 答案是在refresh方法中的prepareBeanFactory(beanFactory);方法中传进去了
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
}
else if (Boolean.FALSE.equals(flag)) {
if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
// inner bean with other scope - can't reliably process events
logger.warn("Inner bean '" + beanName
+ "' implements ApplicationListener interface "
+ "but is not reachable for event multicasting by its containing
ApplicationContext " + "because it does not have singleton scope. Only
top-level listener beans are allowed " +"to be of non-singleton
scope.");
}
this.singletonNames.remove(beanName);
}
}
return bean;
}
}
// 还有一点 多播器的抽象父类AbstractApplicationEventMulticaster实现了BeanFactoryWare接口,
// 重写的setBeanFactory方法会被回调。那么问题又来了, 为什么这个方法会被回调呢?
// 或者说多播器是因为加入了spring容器作为bean被回调, 还是代码手动回调的呢?
// 答案是手动回调的,我们可以看看多播器初始化的代码。
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster,
BeanClassLoaderAware, BeanFactoryAware
{
// 默认初始化了私有的内部类(私有内部类:外界不可以访问, 外部类可以访问私有内部类中的public属性和方法)
private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
private Object retrievalMutex = this.defaultRetriever;
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
if (beanFactory instanceof ConfigurableBeanFactory) {
ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;
if (this.beanClassLoader == null) {
this.beanClassLoader = cbf.getBeanClassLoader();
}
// cbf.getSingletonMutex()返回的就是singletonObjects【spring容器保存单例bean的地方】
this.retrievalMutex = cbf.getSingletonMutex();
}
}
}
// 我们看下refresh()方法调用了initApplicationEventMulticaster()这个方法
class AbstractApplicationContext{
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 这里先看容器里面有没有名字叫做'applicationEventMulticaster'的bean。
// 需要注意的是: 我们配置的bean, 此时在beanFactory中还只是BeanDefinition,
// 还没有开始bean创建的预初始化过程。
// getBean方法会先从singleObjects中找, 找不到的话, 会找beanDefintion, 从而完成初始化的过程
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
// 再从容器里面拿ApplicationEventMulticaster接口的实现类, 名字是'applicationEventMulticaster'
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster ["
+ this.applicationEventMulticaster + "]");
}
}
else {
// 在这里, 看到是手动创建的多播器, 并且把beanFactory传了进去, 在这里继续跟进
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 + "]");
}
}
}
}
class SimpleApplicationEventMulticaster{
/**
* Create a new SimpleApplicationEventMulticaster for the given BeanFactory.
*/
public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
// 在构造方法里面调用了setBeanFactory, 这个方法在父类里面, 重写的BeanFactory接口的方法被调用了
setBeanFactory(beanFactory);
}
}
public abstract class AbstractApplicationEventMulticaster{
@Override
public void setBeanFactory(BeanFactory beanFactory) { // 好的, 也就是这个方法被调用了
this.beanFactory = beanFactory;
if (beanFactory instanceof ConfigurableBeanFactory) {
ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;
if (this.beanClassLoader == null) {
this.beanClassLoader = cbf.getBeanClassLoader();
}
this.retrievalMutex = cbf.getSingletonMutex();
}
}
}