实现spring监听器的方法有两种,一是实现接口ApplicationListener重写方法其方法
@Component
public class MyApplicationListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("监听器"+event.getSource());
}
}
二是在方法上添加注解
@Component
public class MyServiceListener {
@EventListener
public void myService(ApplicationEvent event){
System.out.println("接收事件"+event);
}
}
在测试类中发布事件
public class Demo9 {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AopConfig.class);
//ApplicationContext applicationContext = new ClassPathXmlApplicationContext("");
applicationContext.publishEvent(new ApplicationEvent("监听事件推送") {
});
Apple bean = applicationContext.getBean(Apple.class);
bean.setId(1);
System.out.println(bean);
UserService userService = (UserService) applicationContext.getBean("userService");
userService.pay();
A a = applicationContext.getBean(A.class);
System.out.println(a.getB());
}
}
运行后可以看到两个地方都执行了监听方法
其原理也很简单,就是实现了接口和加了注解的方法都会被作为监听器添加到一个集合中,在spring启动流程的最后会去调用发布方法,然后就循环调用这些监听器,各个监听器就执行自己的方法;
那么具体是怎么实现的呢?这就需要了解到spring启动原始5大类中的两个DefaultEventListenerFactory、EventListenerMethodProcessor从名字就可以看出这两个是和监听器有关的。
DefaultEventListenerFactory类相对简单主要的作用就是创建监听器
@Override
public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {
return new ApplicationListenerMethodAdapter(beanName, type, method);
}
``
EventListenerMethodProcessor实现了SmartInitializingSingleton、ApplicationContextAware、BeanFactoryPostProcessor,其中`SmartInitializingSingleton的重新方法是在bean初始化后(getBean方法执行后)调用实现了该接口的类
```java
// 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 {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
ApplicationContextAware是在初始化bean时统一调用处理。
BeanFactoryPostProcessor是完成beandefinition信息收集后调用的后置处理器,针对beandefinition做增强处理的。也是这三个接口中本类最先被调用的。在本类中的作用是完成监听器的获取。
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
List<EventListenerFactory> factories = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(factories);
this.eventListenerFactories = factories;
}
在完成bean的初始化后调用SmartInitializingSingleton接口的回调方法afterSingletonsInstantiated()前面部分是找出方法上加了@EventListener注解的类,然后调用processBean(beanName, type)方法,执行下面的代码创建了一个监听器
// 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);
}
context.addApplicationListener(applicationListener);
break;
}
}
这里的factory就是我们上面说到的在beanFactoryPostProcessor后置处理器时操作的DefaultEventListenerFactory,至此监听器的创建和添加就完成了。也就是说订阅已经完成了,接下来就是发布了事件,在spring启动的最后是有一个事件发布的
而我们在测试类中也写了一个事件发布,因此在执行完后我们会看到两个事件的发布,一个是spring发布的事件,一个是我们自己发布的事件。从打印的结果可以看出。
这里我们就来看看事件发布的过程,在spring的启动过程中就是上面我们截图的代码发布的,而我们自己则直接调用对应方法即可。
点击进入方法
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);
}
}
}
在for循环中,首先是获取我们的监听器getApplicationListeners(event, type),这里可以拿到我们实现类和注解的两个监听器。然后循环调用。
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass()) ||
(event instanceof PayloadApplicationEvent &&
matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception.
Log loggerToUse = this.lazyLogger;
if (loggerToUse == null) {
loggerToUse = LogFactory.getLog(getClass());
this.lazyLogger = loggerToUse;
}
if (loggerToUse.isTraceEnabled()) {
loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
这里就找到我们的监听器进行发布,各自监听器接收到事件后就各自做各自的事了。
以上就是我自己梳理的一个流程,如有不妥的地方,请见谅,希望大家一起进步!!!