spring4.2更好的应用事件
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) { } }2.上面只提到了注冊事件和事件定義,再來看看事件的發布.
對于任何一個使用@EventListener注解的方法,你可以定義一個非void返回類型.如果你返回一個非null值作為處理一個常規事件的結果,我們會將此結果作為一個新事件來發送.
你可能注意到OrderCreatedEvent并沒有繼承ApplicationEvent,我們覺得是時候讓你靈活發布任意事件,而不強迫你去繼承ApplicationEvent.ApplicationEventPublisher已被擴展來允許你發布任意對象.當這個對象不是一個ApplicationEvent,我們會使用PayloadApplicationEvent來為你包裝.以下例子演示了你如何使用ApplicationEventPublisher來發送一個OrderCreatedEvent:
3.事務邊界事件
另一個受歡迎的改善是一個事件的監聽器綁定到該事務一個階段的能力。典型的例子是當事務成功完成時,再處理這個事件.下面以這樣的方式重寫上面的例子,當生產者運行的事務已成功完成時,此訂單創建事件才會被處理.
功能的實現大致:
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); } } }?
轉載于:https://www.cnblogs.com/xunianchong/p/6839549.html
總結
以上是生活随笔為你收集整理的spring4.2更好的应用事件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 静默安装Azure CLI
- 下一篇: LRU Cache