了解专栏完整的内容,请点击跳转:
Spring framework专栏导航页
gitee注释版源码
作为一款优先的框架,怎么能少得了监听器呢?虽然说现基于web开发的项目很少用到监听器(大多使用消息队列),但是有些时候又需要用到。以及我们想监听Spring容器的初始化相关事件时候,就可以用到Spring自带的的监听器实现方式。
重要组件:事件多播器
监听器思维导图
两种监听器实现方式 接口方式
@Lazy @Component public class ContextRefreshedInterfaceListener implements ApplicationListener注解方式{ @Override public void onApplicationEvent(ContextRefreshedEvent event) { System.out.println("接口监听"); } }
@Lazy // 加了懒加载 这个Bean不会被创建 但是 里边用注解标记的监听事件会被通过后置处理器创建出来
@Component
public class ContextRefreshedAnnotationListener {
@EventListener(ContextRefreshedEvent.class)
public void onAppllicationEvent(ContextRefreshedEvent event) {
System.out.println("注解监听");
}
}
创建多播器
// refresh().initApplicationEventMulticaster();
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//判断容器中是没有有我们的applicationEventMulticaster 应用多播器组件
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
//直接显示的调用我们的getBean获取出来赋值给我们的applicationContext对象
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
//spring ioc显示的new 一个SimpleApplicationEventMulticaster对象保存在applicatoinContext对象中
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
//并且注入到容器中
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() + "]");
}
}
}
注册接口方式监听器的后置处理器
// refresh().prepareBeanFactory(ConfigurableListableBeanFactory beanFactory); ...... // 用于处理实现了ApplicationListener接口的bean,bean初始化后将其添加到监听器集合中 来监听事件 // Register early post-processor for detecting inner beans as ApplicationListeners. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); ......
注册监听器BeanName
// 注册接口方式的监听器 其实只是注册监听器名字
// 防止懒加载监听器漏掉
// 事件发布时候 会再根据这里注册的名字 把懒加载的bean进行实例化 然后再发布事件
// refresh().registerListeners();
protected void registerListeners() {
// 获取容器中所有的监听器对象
// 这个时候正常流程是不会有监听器的
// Register statically specified listeners first.
for (ApplicationListener> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
//获取bean定义中的监听器对象
// 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 earlyEventsToProcess = this.earlyApplicationEvents;
// 在这里赋null。 也就是值此之后都将没有早期事件了
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
//通过多播器进行播发早期事件
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
Bean初始化后注册接口方式监听器到多播器中
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (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
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;
}
所有Bean创建完成后注册注解方式监听器
// DefaultListableBeanFactory#preInstantiateSingletons
// 所有bean都创建完了 可以实现SmartInitializingSingleton来做扩展
// 解析注解方式监听器就是在这里进行的
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
@Override
public void afterSingletonsInstantiated() {
ConfigurableListableBeanFactory beanFactory = this.beanFactory;
Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
if (!ScopedProxyUtils.isScopedTarget(beanName)) {
Class> type = null;
try {
type = AutoProxyUtils.determineTargetClass(beanFactory, beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
}
}
if (type != null) {
if (ScopedObject.class.isAssignableFrom(type)) {
try {
Class> targetClass = AutoProxyUtils.determineTargetClass(
beanFactory, ScopedProxyUtils.getTargetBeanName(beanName));
if (targetClass != null) {
type = targetClass;
}
}
catch (Throwable ex) {
// An invalid scoped proxy arrangement - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target bean for scoped proxy '" + beanName + "'", ex);
}
}
}
try {
// 开始创建事件监听器
processBean(beanName, type);
}
catch (Throwable ex) {
throw new BeanInitializationException("Failed to process @EventListener " +
"annotation on bean with name '" + beanName + "'", ex);
}
}
}
}
}
private void processBean(final String beanName, final Class> targetType) {
if (!this.nonAnnotatedClasses.contains(targetType) &&
AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
!isSpringContainerClass(targetType)) {
Map annotatedMethods = null;
try {
annotatedMethods = MethodIntrospector.selectMethods(targetType,
(MethodIntrospector.metadataLookup) method ->
AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
}
catch (Throwable ex) {
// An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
}
}
if (CollectionUtils.isEmpty(annotatedMethods)) {
this.nonAnnotatedClasses.add(targetType);
if (logger.isTraceEnabled()) {
logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());
}
}
else {
// Non-empty set of methods
ConfigurableApplicationContext context = this.applicationContext;
Assert.state(context != null, "No ApplicationContext set");
// 这个监听器工厂在注册内置后置处理器时候注册了bean定义 然后由EventListenerMethodProcessor将其放进集合中
// EventListenerMethodProcessor实现了多个接口 有多个功能
List factories = this.eventListenerFactories;
Assert.state(factories != null, "EventListenerFactory List not initialized");
for (Method method : annotatedMethods.keySet()) {
for (EventListenerFactory factory : factories) {
if (factory.supportsMethod(method)) {
Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
// 创建事件监听器
ApplicationListener> applicationListener =
factory.createApplicationListener(beanName, targetType, methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
}
// 注册事件到Context中
context.addApplicationListener(applicationListener);
break;
}
}
}
if (logger.isDebugEnabled()) {
logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
beanName + "': " + annotatedMethods);
}
}
}
}
发布事件
// refresh().finishRefresh().publishEvent(new ContextRefreshedEvent(this));
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// 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();
}
}
// 这里是唯一添加早期事件的地方。所以一定要发布事件才能添加早期事件
// 只有当执行refresh-->registerListeners 才会将earlyApplicationEvents赋为null
// 所以registerListeners之前发布的事件都是早期事件
// 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);
}
}
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
//从多播器中获取出所有的监听器
// 如果是懒加载的接口方式监听器 会在这里获取监听器时候进行创建
for (ApplicationListener> listener : getApplicationListeners(event, type)) {
//判断多播器中是否支持异步多播的
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
//同步播发
invokeListener(listener, event);
}
}
}



