Spring内置事件
Spring内置的上下文应用事件包括:
上下文就绪事件:ContextRefreshedEvent
上下文启动事件:ContextStartedEvent
上下文停止事件:ContextStoppedEvent
上下文关闭事件:ContextClosedEvent
在实际开发中,可以监听以上四个内置事件,如果无法满足需求,也可以通过实现 ApplicationEvent来自定义事件,示例如下:
@ComponentScan
@ComponentScan
public class Application {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
context.publishEvent(new MyEvent(context, "hhhhhhhh"));
}
}
//自定义事件
@Getter
@Setter
class MyEvent extends ApplicationEvent {
private String msg;
public MyEvent(Object source, String msg) {
super(source);
this.msg = msg;
}
}
//事件监听器1 - 使用注解的方式注册监听器
@Component
class MyListener1 {
@EventListener(MyEvent.class)
public void sendMsg(MyEvent event) {
String msg = event.getMsg();
System.out.println("MyListener1 获取到了监听消息:" + msg);
}
}
//事件监听器2 - 注册ApplicationListener类型的Bean
@Component
class MyListener2 implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
String msg = event.getMsg();
System.out.println("MyListener2 获取到了监听消息:" + msg);
}
}
//事件监听器3 - 使用ApplicationContext的addApplicationListener方法手动注册
下面从源码的角度看看Spring是如何运行的。
监听器注册阶段
注册阶段主要看 @EventListener怎么解析,以及实现了ApplicationListener接口的Bean是怎么解析的
1、在实例化AnnotatedBeanDefinitionReader对象的时候就注册了EventListenerMethodProcessor和DefaultEventListenerFactory这两个处理器的BeanDefinition。他们用来解析@EventListener注解。
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
2、EventListenerMethodProcessor实现了BeanFactoryPostProcessor接口,在执行refresh方法的invokeBeanFactoryPostProcessors(beanFactory)方法时,postProcessBeanFactory方法会被调用。
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
//获取实现EventListenerFactory接口的类,默认只有DefaultEventListenerFactory,可以看出可以自定义EventListenerFactory
Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
List<EventListenerFactory> factories = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(factories);
//将DefaultEventListenerFactory设置给eventListenerFactories
this.eventListenerFactories = factories;
}
3、refresh方法里的registerListeners() 方法被调用,此时所有手动添加的实现ApplicationListener接口的类会加到DefaultListenerRetriever对象的applicationListeners中,
而通过注册ApplicationListener类型的Bean会加到DefaultListenerRetriever对象的applicationListenerBeans中,当然最终ApplicationListenerDetector也会把这些Bean添加到DefaultListenerRetriever对象的applicationListeners中。
此时通过@EventListener注解方式注册的监听器还尚未被解析。
protected void registerListeners() {
// Register statically specified listeners first.
//首先注册手动调用addApplicationListener方法添加的ApplicationListener,加到applicationListeners集合中
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!
//获取ApplicationListener接口的所有实现类,把名称加到applicationListenerBeans中。
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 (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
4、refresh方法里的finishBeanFactoryInitialization(beanFactory)方法被调用,内部会调用SmartInitializingSingleton接口的afterSingletonsInstantiated方法,EventListenerMethodProcessor实现了该接口,在所有Bean初始化完成后会调用。
@Override
public void preInstantiateSingletons() throws BeansException {
......
// 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<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
//调用SmartInitializingSingleton接口的afterSingletonsInstantiated方法
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
5、解析@EventListener,最终也是包装为ApplicationListener对象加到DefaultListenerRetriever对象的applicationListeners中。
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)) {
processBean(beanName, type);
}
}
}
private void processBean(final String beanName, final Class<?> targetType) {
//排除掉不符合条件的类
if (!this.nonAnnotatedClasses.contains(targetType) &&
AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
!isSpringContainerClass(targetType)) {
Map<Method, EventListener> annotatedMethods = null;
try {
//找到带有EventListener注解的方法
annotatedMethods = MethodIntrospector.selectMethods(targetType,
(MethodIntrospector.MetadataLookup<EventListener>) method ->
AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
}
......
// Non-empty set of methods
ConfigurableApplicationContext context = this.applicationContext;
Assert.state(context != null, "No ApplicationContext set");
List<EventListenerFactory> 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);
}
//包装为ApplicationListener对象加到DefaultListenerRetriever对象的applicationListeners中
context.addApplicationListener(applicationListener);
break;
}
}
......
}
}
}
发布事件
Spring事件发布器默认使用SimpleApplicationEventMulticaster,也可以通过实现ApplicationEventPublisher接口自定义事件发布器。当refresh方法里的initApplicationEventMulticaster() 方法被调用时,就会初始化ApplicationEventMulticaster。
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//判断是否存在applicationEventMulticaster这个bean,存在就直接使用,不存在就用SimpleApplicationEventMulticaster,
//这意味着可以自定义ApplicationEventMulticaster
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 {
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() + "]");
}
}
}
当调用 context.publishEvent(new MyEvent(context, “hhhhhhhh”))时,会借住applicationEventMulticaster来发布事件。
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();
}
}
// 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);
}
}
}
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)) {
//如果有Executor,就异步调用监听器
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
总结
注册事件监听器,也就是把所有的事件监听器解析后管理起来,方便后续查找。发布事件也就是找到符合指定事件的事件监听器,循环调用即可。