国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > Java > 正文

在spring中使用自定義注解注冊監聽器的方法

2024-07-13 10:17:09
字體:
來源:轉載
供稿:網友

接口回調

監聽器本質上就是利用回調機制,在某個動作發生前或后,執行我們自己的一些代碼。在Java語言中,可以使用接口來實現。

實現一個監聽器案例

為了方便,直接在spring環境中定義:以工作(work)為例,定義工作開始時(或結束時)的監聽器。

1. 定義回調的接口

package com.yawn.demo.listener;/** * @author Created by yawn on 2018-01-21 13:53 */public interface WorkListener {  void onStart(String name);}

2. 定義動作

package com.yawn.demo.service;import com.yawn.demo.listener.WorkListener;/** * @author Created by yawn on 2018-01-21 13:39 */@Servicepublic class MyService {  @Resource  private PersonService personService;  private WorkListener listener;  public void setWorkListener(WorkListener workListener) {    this.listener = workListener;  }  public void work(String name) {    listener.onStart(name);    personService.work();  }}

動作work為一個具體的方法,在work()方法的適當時機,調用前面定義的接口。此外,在這個動作定義類中,需要提高設置監聽器的方法。

3. 監聽測試

@RunWith(SpringRunner.class)@SpringBootTestpublic class DemoSpringAnnotationApplicationTests {  @Resource  private MyService myService;  @Test  public void test1() {    // 接口設置監聽器    myService.setWorkListener(new WorkListener() {      @Override      public void onStart(String name) {        System.out.println("Start work for " + name + " !");      }    });//    // lambda 表達式設置監聽器//    myService.setWorkListener(name -> System.out.println("Start work for " + name + " !"));    // 工作    myService.work("boss");  } @Test  public void test2() {   // 繼承實現類設置監聽器   myService.setWorkListener(new myWorkListener());   // 工作   myService.work("boss");  }  class myWorkListener extends WorkListenerAdaptor {    @Override    public void onStart(String name) {      System.out.println("Start work for " + name + " !");    }  }}

使用以上兩種方法測試,得到了結果為:

Start work for boss !working hard ...

說明在動作work發生之前,執行了我們在測試類中寫下的監聽代碼,實現類監聽的目的。

使用注解實現監聽器

在以上代碼中,調用 setWorkListener(WorkListener listener)  方法一般稱作設置(注冊)監聽器,就是將自己寫好的監聽代碼,設置為動作的監聽器。然而,在每次注冊監聽器時,一般需要寫一個類,實現定義好的接口或繼承實現接口的類,再重寫接口定義的方法即可。因此,聰明的程序員就想簡化這個過程,所以就想出了使用注解的方法。使用注解,將監聽代碼段寫在一個方法中,使用一個注解標記這個方法即可。

的確,使用變得簡單了,但實現卻不見得。

1. 定義一個注解

package com.yawn.demo.anno;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface WorkListener {}

2. 解析注解

package com.yawn.demo.anno;import com.yawn.demo.service.MyService;import org.springframework.beans.BeansException;import org.springframework.beans.factory.InitializingBean;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;import javax.annotation.Resource;import java.lang.annotation.Annotation;import java.lang.reflect.Method;import java.util.LinkedHashMap;import java.util.Map;/** * @author Created by yawn on 2018-01-21 14:46 */@Componentpublic class WorkListenerParser implements ApplicationContextAware, InitializingBean {  @Resource  private MyService myService;  private ApplicationContext applicationContext;  @Override  public void afterPropertiesSet() throws Exception {    Map<String, Object> listenerBeans = getExpectListenerBeans(Controller.class, RestController.class, Service.class, Component.class);    for (Object listener : listenerBeans.values()) {      for (Method method : listener.getClass().getDeclaredMethods()) {        if (!method.isAnnotationPresent(WorkListener.class)) {          continue;        }        myService.setWorkListener(name -> {          try {            method.invoke(listener, name);          } catch (Exception e) {            e.printStackTrace();          }        });      }    }  }  /**   * 找到有可能使用注解的bean   * @param annotationTypes 需要進行掃描的類級注解類型   * @return 掃描到的beans的map   */  private Map<String, Object> getExpectListenerBeans(Class<? extends Annotation>... annotationTypes) {    Map<String, Object> listenerBeans = new LinkedHashMap<>();    for (Class<? extends Annotation> annotationType : annotationTypes) {      Map<String, Object> annotatedBeansMap = applicationContext.getBeansWithAnnotation(annotationType);      listenerBeans.putAll(annotatedBeansMap);    }    return listenerBeans;  }  @Override  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {    this.applicationContext = applicationContext;  }}

在注解的解析過程中,設置監聽器。

在解析類中,實現了接口ApplicationContextAware,為了在類中拿到ApplicationContext的引用,用于得到 IOC 容器中的 Bean;而實現接口InitializingBean,則是為了在一個合適的時機執行解析注解、設置監聽器的代碼。 如果不這樣做,可以在CommandLineRunner執行時調用解析、設置的代碼,而ApplicationContext也可以自動注入。

3. 測試

在執行完以上代碼后,監聽器就已經設置好了,可以進行測試了。

package com.yawn.demo.controller;import com.yawn.demo.anno.WorkListener;import com.yawn.demo.service.MyService;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/** * @author Created by yawn on 2018-01-21 13:28 */@RestControllerpublic class TestController {  @Resource  private MyService myService;  @GetMapping("/work")  public Object work() {    myService.work("boss");    return "done";  }  @WorkListener  public void listen(String name) {    System.out.println("Start work for " + name + " !");  }}

寫一個監聽方法,參數類型和個數與接口相同,然后加上自定義的注解即可。當啟動環境后,監聽器就已經設置好了。

然后通過url調用myService的work()方法,可以看到結果:

Start work for boss !working hard ...

已經調用了監聽方法。在接下來的開發中,就可以使用這個注解注冊監聽器了。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 锡林郭勒盟| 安泽县| 乌拉特后旗| 庄浪县| 乌拉特前旗| 喀喇沁旗| 菏泽市| 海原县| 耿马| 咸丰县| 库尔勒市| 印江| 大冶市| 红河县| 铜山县| 黄陵县| 宝坻区| 昌宁县| 白城市| 澳门| 湖南省| 安顺市| 平陆县| 浮梁县| 伊金霍洛旗| 延川县| 三河市| 固安县| 吴川市| 福贡县| 威远县| 凤山县| 岳普湖县| 沙坪坝区| 泌阳县| 龙山县| 云龙县| 平顺县| 精河县| 水富县| 吴川市|