如何實現Application event,觀察者模式

  • 時間:2019-06-11 02:24 作者:杭宇_8ba6 來源:杭宇_8ba6 閱讀:162
  • 掃一掃,手機訪問
摘要:spring 事件為bean 與 bean之間傳遞消息。一個bean解決完了希望其他一個接著解決.這時我們就需要其他的一個bean監聽當前bean所發送的事件.spring事件使用步驟如下:1.先自己設置事件:你的事件需要繼承 ApplicationEvent2.定義事件監聽器: 需要實現 Appli

spring 事件為bean 與 bean之間傳遞消息。一個bean解決完了希望其他一個接著解決.這時我們就需要其他的一個bean監聽當前bean所發送的事件.

spring事件使用步驟如下:

1.先自己設置事件:你的事件需要繼承 ApplicationEvent

2.定義事件監聽器: 需要實現 ApplicationListener

3.使用容器對事件進行發布

  • 首先定義一個事件
/** * @Title: * @Auther: hangyu * @Date: 2019/3/13 * @Description * @Version:1.0 */public class TestEvent extends ApplicationEvent {    private String name;    private String msg;    public TestEvent(Object source){        super(source);    }    public TestEvent(Object source, String name, String msg) {        super(source);        this.name = name;        this.msg = msg;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getMsg() {        return msg;    }    public void setMsg(String msg) {        this.msg = msg;    }}
  • 其次定義事件監聽
/** * @Title: * @Auther: hangyu * @Date: 2019/3/13 * @Description * @Version:1.0 */@Componentpublic class TestEventListener implements ApplicationListener<TestEvent> {    @Async    @Override    public void onApplicationEvent(TestEvent testEvent) {        System.out.println("姓名:"+testEvent.getName()+"得到消息:"+testEvent.getMsg());    }}
  • 使用容器發布事件
/** * @Title: * @Auther: hangyu * @Date: 2019/3/13 * @Description * @Version:1.0 */@Componentpublic class TestEventPublisher {    @Autowired    private ApplicationContext applicationContext;    public void pushlish(String name, String msg){        applicationContext.publishEvent(new TestEvent(this, name,msg));    }}
  • 測試事件能否能夠生效
/** * @Title: * @Auther: hangyu * @Date: 2019/3/13 * @Description * @Version:1.0 */@[email protected]("cn.*.event")public class EventConfig {}/** * @Title: * @Auther: hangyu * @Date: 2019/3/13 * @Description * @Version:1.0 */public class TestMain {    private static AnnotationConfigApplicationContext context;    public static void main(String[] args) {        start();    }    private static void start() {        if (context == null) {             context=new AnnotationConfigApplicationContext(EventConfig.class);        }        context.getBean(TestEventPublisher.class).pushlish("hangyu","申請退款!");    }}
輸出打印結果

最后有一個思考:ApplicationEvent事件執行部分和起一個TaskExecutor去執行 有啥區別嗎?反正都是異步。

可以這樣實現;

 @Autowired private AsyncExecutor asyncExecutor;Executor executor = asyncExecutor.getAsyncExecutor();executor.execute(           //具體業務});@[email protected] class AsyncExecutor implements AsyncConfigurer {// 日志static final Logger logger = LoggerFactory.getLogger(AsyncExecutor.class);public Executor getAsyncExecutor() {ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();taskExecutor.setCorePoolSize(5);taskExecutor.setMaxPoolSize(10);taskExecutor.setQueueCapacity(20000);taskExecutor.setKeepAliveSeconds(120);taskExecutor.setAllowCoreThreadTimeOut(true);taskExecutor.initialize();return taskExecutor;}}

還可以這樣實現;

    <!-- 異步線程池 -->    <bean id="taskExecutor"          class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">        <!-- 核心線程數 -->        <property name="corePoolSize" value="3" />        <!-- 最大線程數 -->        <property name="maxPoolSize" value="10" />        <!-- 隊列最大長度 >=mainExecutor.maxSize -->        <property name="queueCapacity" value="25" />        <!-- 線程池維護線程所允許的空閑時間 -->        <property name="keepAliveSeconds" value="300" />        <!-- 線程池對拒絕任務(無線程可用)的解決策略 ThreadPoolExecutor.CallerRunsPolicy策略 ,調用者的線程會執行該任務,假如執行器已關閉,則丟棄.  -->        <property name="rejectedExecutionHandler">            <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />        </property>    </bean> @Resource private TaskExecutor taskExecutor; taskExecutor.execute(new Runnable() {            @Override            public void run() {              //具體業務            }}
這就是注解方式和直接引用方式,本質是一樣的

我的思考:ApplicationEvent是觀察者設計模式,這種設計模式使得主題和觀察者之間的耦合度降低,松耦合是面向對象設計中很重要的一個準則,最終也是使用@Async來實現異步。而TaskExecutor則是啟動一個線程池任務異步執行任務,兩者效果一樣,但原理不同。

通過我的思考,又帶來一個疑問:那觀察者模式是不是就是我們MQ中的發布訂閱模式呢?只不過觀察者模式是進程內的,而MQ是跨進程的?就這唯一的區別嗎?

經過少量資料的查閱:大多數地方觀察者模式約等于發布訂閱模式,但是觀察者模式是由具體目標調度的,而發布/訂閱模式是統一由調度中心調的,所以觀察者模式的訂閱者與發布者之間是存在依賴的,而發布/訂閱模式則不會。
所以說觀察者模式是小米加步槍,發布訂閱模式是95式自動步槍,是它的進化版!

  • 全部評論(0)
最新發布的資訊信息
【系統環境|服務器應用】Discuz隱藏后臺admin.php網址修改路徑(2019-12-15 14:52)
【系統環境|服務器應用】Discuz發布帖子時默認顯示第一個主題分類的修改方法(2019-12-09 00:13)
【系統環境|軟件環境】Android | App內存優化 之 內存泄漏 要點概述 以及 處理實戰(2019-12-04 14:27)
【系統環境|軟件環境】MySQL InnoDB 事務(2019-12-04 14:26)
【系統環境|軟件環境】vue-router(單頁面應用控制中心)常見用法(2019-12-04 14:26)
【系統環境|軟件環境】Linux中的Kill命令(2019-12-04 14:26)
【系統環境|軟件環境】Linux 入門時必學60個文件解決命令(2019-12-04 14:26)
【系統環境|軟件環境】更新版ThreeJS 3D粒子波浪動畫(2019-12-04 14:26)
【系統環境|軟件環境】前臺開發WebStorm常用快捷鍵,火速收藏!(2019-12-04 14:25)
【系統環境|軟件環境】微博H5登錄和發微博組件(2019-12-04 14:25)
手機二維碼手機訪問領取大禮包
返回頂部
3d开机号查询