1.基于注解驱动事件监听器:现在可以在一个Bean的方法上使用@EventListener注解来自动注册一个ApplicationListener来匹配方法签名.
@Component public class MyListener { @EventListener public void handleContextRefresh(ContextRefreshedEvent event) { } }此方法签名定义了你感兴趣的事件类型.也可以定义SpELg表达式来匹配处理这个事件.假设事件的定义如下:
public class OrderCreatedEvent implements CreationEvent<Order> { private boolean awesome; public boolean isAwesome() { return this.awesome; } }下面的例子事件监听器将同时满足以下情况才会被调用:a.它是CreationEvent<Order>类型的事件;b.此事件的awesome标志为true.
@Component public class MyComponent { @EventListener(condition = "#creationEvent.awesome") public void handleOrderCreatedEvent(CreationEvent<Order> creationEvent) { } }
@Component public class MyComponent { private final ApplicationEventPublisher publisher; @Autowired public MyComponent(ApplicationEventPublisher publisher) { this.publisher=publisher; } public void createOrder(Order order) { this.publisher.publishEvent(new OrderCreatedEvent(order)); } }
@Component public class MyComponent { @TransactionalEventListener(condition = "#creationEvent.awesome") public void handleOrderCreatedEvent(CreationEvent<Order> creationEvent) { } }
功能的实现大致:
a.注册Listener:实例化spring容器的时候会注册一个org.springframework.context.event.EventListenerMethodProcessor这样的Bean,完成初始化,会调用它的兵后置回调afterSingletonsInstantiated()方法:
@Override public void afterSingletonsInstantiated() { List<EventListenerFactory> factories = getEventListenerFactories(); String[] allBeanNames = this.applicationContext.getBeanNamesForType(Object.class); for (String beanName : allBeanNames) { if (!ScopedProxyUtils.isScopedTarget(beanName)) { Class<?> type = this.applicationContext.getType(beanName); try { processBean(factories, beanName, type); }catch (RuntimeException e) { throw new BeanInitializationException("Failed to process @EventListener " + "annotation on bean with name '" + beanName + "'", e); } } } }迭代每个Bean进行processBean(factories, beanName, type)处理.
protected void processBean(List<EventListenerFactory> factories, String beanName, final Class<?> type) { Class<?> targetType = getTargetClass(beanName, type); if (!this.nonAnnotatedClasses.contains(targetType)) { final Set<Method> annotatedMethods = new LinkedHashSet<Method>(1); Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(targetType); for (Method method : methods) { //在这个方法上查找EventListener注解 EventListener eventListener = AnnotationUtils.findAnnotation(method, EventListener.class); if (eventListener == null) { continue; } for (EventListenerFactory factory : factories) { if (factory.supportsMethod(method)) { if (!type.equals(targetType)) { method = getProxyMethod(type, method); } //使用这个方法创建一个ApplicationListener对象 ApplicationListener<?> applicationListener = factory.createApplicationListener(beanName, type, method); if (applicationListener instanceof ApplicationListenerMethodAdapter) { ((ApplicationListenerMethodAdapter)applicationListener) .init(this.applicationContext, this.evaluator); } //添加到applicationContext的事件广播器 this.applicationContext.addApplicationListener(applicationListener); annotatedMethods.add(method); break; } } } if (annotatedMethods.isEmpty()) { this.nonAnnotatedClasses.add(type); if (logger.isTraceEnabled()) { logger.trace("No @EventListener annotations found on bean class: " + type); } } else { // Non-empty set of methods if (logger.isDebugEnabled()) { logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" + beanName + "': " + annotatedMethods); } } } }b.通过ApplicationEventPublisher发布事件:入口在org.springframework.context.support.AbstractApplicationContext#publishEvent(java.lang.Object),再调用重载方法
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); } final ApplicationEvent applicationEvent; //这里可以看出如果event不是ApplicationEvent类型,就会使用PayloadApplicationEvent进行包装 if (event instanceof ApplicationEvent) { applicationEvent = (ApplicationEvent) event; } else { applicationEvent = new PayloadApplicationEvent<Object>(this, event); if (eventType == null) { eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass()); } } //通过事件广播器进行广播事件 getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); if (this.parent != null) { if (this.parent instanceof AbstractApplicationContext) { ((AbstractApplicationContext) this.parent).publishEvent(event, eventType); } else { this.parent.publishEvent(event); } } }