Spring中的觀察者模式-事件監聽

      在編碼過程當中,咱們常常會遇到完成一個操做須要多個步驟完成的狀況。咱們可能會把多個步驟寫到一個方法裏,假如這個操做須要新增步驟,那麼勢必要修改已有的方法,這違反了開閉原則。spring

     咱們能夠使用spring的事件機制來簡單地實現這種功能。Spring的事件機制用到了觀察者模式,何謂觀察者模式?觀察者模式(有時又被稱爲模型(Model)-視圖(View)模式、源-收聽者(Listener)模式或從屬者模式)是軟件設計模式的一種。在此種模式中,一個目標物件管理全部相依於它的觀察者物件,而且在它自己的狀態改變時主動發出通知。這一般透過呼叫各觀察者所提供的方法來實現。此種模式一般被用來實現事件處理系統。設計模式

     假若有一個下訂單的操做,咱們首先須要建立一個Event繼承ApplicationEvent,並實現構造方法app

import org.springframework.context.ApplicationEvent;

public class OrderEvent extends ApplicationEvent {

    public OrderEvent(Object source) {
        super(source);
    }
}

     接下來須要定義一個OrderService,並注入ApplicationContext對象,向spring發佈下訂單事件OrderEvent,相似以下這樣:ide

import com.study.designer.event.OrderEvent;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

@Service
public class OrderService {

    @Autowired
    private ApplicationContext applicationContext;


    public void order() {
        applicationContext.publishEvent(new OrderEvent("orderService"));
    }
}

 

      向spring發佈了OrderEvent事件以後,須要有對應的Listener來響應這個事件,咱們能夠定義多個事件來監聽這個事件來對應OrderEvent須要的一系列步驟。測試

這裏定義一個OrderSmsListener來虛擬完成短信事件:this

import com.study.designer.event.OrderEvent;

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class OrderSmsListener implements ApplicationListener<OrderEvent> {
    @Override
    public void onApplicationEvent(OrderEvent orderEvent) {
        System.out.println("orderSmsListener receive event from " + orderEvent.getSource());
    }
}

     接下來咱們編寫測試用例來驗證功能,能夠看到SMS功能已經正常實現:編碼

import com.study.designer.service.OrderService;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DesignerApplicationTests {

    @Autowired
    private OrderService orderService;

    @Test
    public void contextLoads() {
    }


    @Test
    public void testOrder() {
        orderService.order();
    }

}

    查看ApplicationContext的publishEvent方法,發現spring會獲取全部的Listener並向監聽對應事件的Listener廣播事件spa

/**
     * 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, @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);
            }
        }
    }
相關文章
相關標籤/搜索