/** * Resolve the method arguments to use for the specified {@link ApplicationEvent}. * <p>These arguments will be used to invoke the method handled by this instance. Can * return {@code null} to indicate that no suitable arguments could be resolved and * therefore the method should not be invoked at all for the specified event. */ protected Object[] resolveArguments(ApplicationEvent event) { ResolvableType declaredEventType = getResolvableType(event); if (declaredEventType == null) { return null; } if (this.method.getParameterTypes().length == 0) { return new Object[0]; } if (!ApplicationEvent.class.isAssignableFrom(declaredEventType.getRawClass()) && event instanceof PayloadApplicationEvent) { return new Object[] {((PayloadApplicationEvent) event).getPayload()}; } else { return new Object[] {event}; } }
private ResolvableType getResolvableType(ApplicationEvent event) { ResolvableType payloadType = null; if (event instanceof PayloadApplicationEvent) { PayloadApplicationEvent<?> payloadEvent = (PayloadApplicationEvent<?>) event; payloadType = payloadEvent.getResolvableType().as( PayloadApplicationEvent.class).getGeneric(0); } for (ResolvableType declaredEventType : this.declaredEventTypes) { if (!ApplicationEvent.class.isAssignableFrom(declaredEventType.getRawClass()) && payloadType != null) { if (declaredEventType.isAssignableFrom(payloadType)) { return declaredEventType; } } if (declaredEventType.getRawClass().isAssignableFrom(event.getClass())) { return declaredEventType; } } return null; }
/** * Resolve the method arguments to use for the specified {@link ApplicationEvent}. * <p>These arguments will be used to invoke the method handled by this instance. Can * return {@code null} to indicate that no suitable arguments could be resolved and * therefore the method should not be invoked at all for the specified event. */ protected Object[] resolveArguments(ApplicationEvent event) { ResolvableType declaredEventType = getResolvableType(event); if (declaredEventType == null) { return null; } if (this.method.getParameterTypes().length == 0) { return new Object[0]; } if (!ApplicationEvent.class.isAssignableFrom(declaredEventType.getRawClass()) && event instanceof PayloadApplicationEvent) { return new Object[]{((PayloadApplicationEvent) event).getPayload()}; } else { return new Object[]{event}; } }
protected ResolvableType getResolvableType(ApplicationEvent event) { ResolvableType payloadType = null; if (event instanceof PayloadApplicationEvent) { PayloadApplicationEvent<?> payloadEvent = (PayloadApplicationEvent<?>) event; payloadType = payloadEvent.getResolvableType().as(PayloadApplicationEvent.class).getGeneric(); } for (ResolvableType declaredEventType : this.declaredEventTypes) { if (!ApplicationEvent.class.isAssignableFrom(declaredEventType.getRawClass()) && payloadType != null) { if (declaredEventType.isAssignableFrom(payloadType)) { return declaredEventType; } } if (declaredEventType.getRawClass().isInstance(event)) { return declaredEventType; } } return null; }
@EventListener public void websiteIsOnline(PayloadApplicationEvent<WebsiteOnlineEvent> websiteOnlineEvent) { Website website = websiteRepository.findById(websiteOnlineEvent.getPayload().websiteId()); try { sendClient.sendTextMessage(website.userId().getId(), "Alles OK. Die Website " + website.url() + " ist gerade online gegangen."); } catch (MessengerApiException | MessengerIOException e) { LoggerFactory.getLogger(getClass()).warn("Could not send website online message to user "+ website.userId() + " for website " + website.url()); } }
@EventListener public void websiteIsOffline(PayloadApplicationEvent<WebsiteOfflineEvent> websiteOfflineEvent) { Website website = websiteRepository.findById(websiteOfflineEvent.getPayload().websiteId()); try { sendClient.sendTextMessage(website.userId().getId(), "Oh Schreck! Die Website " + website.url() + " ist gerade offline gegangen! Bitte kümmere dich um das Problem! Ich melde mich, wenn sie wieder online ist."); } catch (MessengerApiException | MessengerIOException e) { LoggerFactory.getLogger(getClass()).error("Could not send website offline message to user "+ website.userId() + " for website " + website.url()); } }
/** * Publish the given event to all listeners. * @param event the event to publish (may be an {@link ApplicationEvent} * or a payload object to be turned into a {@link PayloadApplicationEvent}) * @param eventType the resolved event type, if known * @since 4.2 */ 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 = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass()); } } // 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 boolean supportsEventType(ResolvableType eventType) { for (ResolvableType declaredEventType : this.declaredEventTypes) { if (declaredEventType.isAssignableFrom(eventType)) { return true; } else if (PayloadApplicationEvent.class.isAssignableFrom(eventType.getRawClass())) { ResolvableType payloadType = eventType.as(PayloadApplicationEvent.class).getGeneric(); if (declaredEventType.isAssignableFrom(payloadType)) { return true; } } } return eventType.hasUnresolvableGenerics(); }
@Test public void invokeListenerWithGenericPayload() { Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleGenericStringPayload", EntityWrapper.class); EntityWrapper<String> payload = new EntityWrapper<>("test"); invokeListener(method, new PayloadApplicationEvent<>(this, payload)); verify(this.sampleEvents, times(1)).handleGenericStringPayload(payload); }
@Test public void invokeListenerWithWrongGenericPayload() { Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleGenericStringPayload", EntityWrapper.class); EntityWrapper<Integer> payload = new EntityWrapper<>(123); invokeListener(method, new PayloadApplicationEvent<>(this, payload)); verify(this.sampleEvents, times(0)).handleGenericStringPayload(any()); }
@Test public void invokeListenerWithAnyGenericPayload() { Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleGenericAnyPayload", EntityWrapper.class); EntityWrapper<String> payload = new EntityWrapper<>("test"); invokeListener(method, new PayloadApplicationEvent<>(this, payload)); verify(this.sampleEvents, times(1)).handleGenericAnyPayload(payload); }
@Test public void invokeListenerWithPayload() { Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleString", String.class); PayloadApplicationEvent<String> event = new PayloadApplicationEvent<>(this, "test"); invokeListener(method, event); verify(this.sampleEvents, times(1)).handleString("test"); }
@Test public void invokeListenerWithPayloadWrongType() { Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleString", String.class); PayloadApplicationEvent<Long> event = new PayloadApplicationEvent<>(this, 123L); invokeListener(method, event); verify(this.sampleEvents, never()).handleString(anyString()); }
@Test public void invokeListenerWithAnnotationValue() { Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleStringAnnotationClasses"); PayloadApplicationEvent<String> event = new PayloadApplicationEvent<>(this, "test"); invokeListener(method, event); verify(this.sampleEvents, times(1)).handleStringAnnotationClasses(); }
@Test public void invokeListenerWithAnnotationValueAndParameter() { Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleStringAnnotationValueAndParameter", String.class); PayloadApplicationEvent<String> event = new PayloadApplicationEvent<>(this, "test"); invokeListener(method, event); verify(this.sampleEvents, times(1)).handleStringAnnotationValueAndParameter("test"); }
@Test public void invokeListenerWithSeveralTypes() { Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleStringOrInteger"); PayloadApplicationEvent<String> event = new PayloadApplicationEvent<>(this, "test"); invokeListener(method, event); verify(this.sampleEvents, times(1)).handleStringOrInteger(); PayloadApplicationEvent<Integer> event2 = new PayloadApplicationEvent<>(this, 123); invokeListener(method, event2); verify(this.sampleEvents, times(2)).handleStringOrInteger(); PayloadApplicationEvent<Double> event3 = new PayloadApplicationEvent<>(this, 23.2); invokeListener(method, event3); verify(this.sampleEvents, times(2)).handleStringOrInteger(); }
/** * Publish the given event to all listeners. * @param event the event to publish (may be an {@link ApplicationEvent} * or a payload object to be turned into a {@link PayloadApplicationEvent}) * @param eventType the resolved event type, if known * @since 4.2 */ 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); } } }
protected void publishEvent(Object instance, Object event) { if (event != null) { if (event instanceof ApplicationEvent) { this.events.publish((ApplicationEvent) event); } else { this.events.publish(new PayloadApplicationEvent<>(instance, event)); } } }
@EventListener public void addLoadInstant(final PayloadApplicationEvent<SystemInfo.LoadInstant> event) { synchronized (MONITOR) { initSystemInfo(); SYSTEM_INFO.getLoad().add(event.getPayload()); } }
@TransactionalEventListener public void handle(PayloadApplicationEvent<TestModel> event) { System.err.println(event.getPayload().getName()); //这里可以记录日志, 发送消息等操作. //这里抛出异常, 会导致addTestModel方法异常, 但不会回滚事务. //注意, ApplicationEventPublisher不能使用线程池, 否则不会执行到这里 //因为, 包装类是通过ThreadLocal来判断当前是否有活动的事务信息. //TransactionalEventListener.fallbackExecution就是为了决定当当前线程没有事务上下文时, //是否还调用 handle 方法, 默认不调用. }
private static Object getEventToPersist(ApplicationEvent event) { return PayloadApplicationEvent.class.isInstance(event) ? ((PayloadApplicationEvent<?>) event).getPayload() : event; }
@Override public void onApplicationEvent(PayloadApplicationEvent event) { this.seenPayloads.add(event.getPayload()); }
@EventListener public void handleString(PayloadApplicationEvent<String> event) { collectEvent(event.getPayload()); }
@Test public void listenerWithPayloadTypeErasure() { // Always accept such event when the type is unknown Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleString", String.class); supportsEventType(true, method, ResolvableType.forClass(PayloadApplicationEvent.class)); }
private ResolvableType createGenericEventType(Class<?> payloadType) { return ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, payloadType); }
@Override public void publishEvent(Object event) { publishEvent(new PayloadApplicationEvent<Object>(this, event)); }