一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 在spring中使用自定義注解注冊監聽器的方法

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

2021-03-25 11:10silenceyawen Java教程

本篇文章主要介紹了在spring中使用自定義注解注冊監聽器的方法,本文就是在分析監聽器回調原理的基礎上,在spring環境中使用自定義的注解實現一個監聽器。小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小

接口回調

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

實現一個監聽器案例

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

1. 定義回調的接口

?
1
2
3
4
5
6
7
8
9
package com.yawn.demo.listener;
 
/**
 * @author Created by yawn on 2018-01-21 13:53
 */
public interface WorkListener {
 
  void onStart(String name);
}

2. 定義動作

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.yawn.demo.service;
 
import com.yawn.demo.listener.WorkListener;
 
/**
 * @author Created by yawn on 2018-01-21 13:39
 */
@Service
public 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. 監聽測試

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@RunWith(SpringRunner.class)
@SpringBootTest
public 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 + " !");
    }
  }
}

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

?
1
2
Start work for boss !
working hard ...

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

使用注解實現監聽器

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

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

1. 定義一個注解

?
1
2
3
4
5
package com.yawn.demo.anno;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface WorkListener {
}

2. 解析注解

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
 */
@Component
public 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. 測試

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
 */
@RestController
public 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()方法,可以看到結果:

?
1
2
Start work for boss !
working hard ...

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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://my.oschina.net/silenceyawen/blog/1610900

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 高清女主播一区二区三区 | 3d动漫免费 | 大乳奶水bbw | 国产伦精一区二区三区视频 | 久久最新地址获取 | 国产肥臀| 天天操天天射天天色 | 天堂在线看 | 免费看60分钟大片视频播放 | 成人精品网 | 3d蒂法受辱在线播放 | 97精品国产自在现线免费 | 久久婷婷丁香五月色综合啪免费 | 高清女主播一区二区三区 | 91免费精品国自产拍在线不卡 | 乌克兰黄色录像 | www.色香蕉| 国产特级毛片aaaaaa | 美女逼逼软件 | 日本人妖在线 | 911精品国产亚洲日本美国韩国 | 免费人成网址在线观看国内 | 92精品国产成人观看免费 | 2020年国产精品午夜福利在线观看 | 欧美日韩中文字幕久久伊人 | 91精品啪在线观看国产91九色 | 欧美日韩国产成人综合在线影院 | 99视频精品国在线视频艾草 | 日本mv精品中文字幕 | 97色伦 | 婷婷日韩 | 99re这里只有精品在线观看 | 青青草99热这里都是精品 | 久久精品视频免费 | 欧美同志video 在线观看 | 秋霞理论一级在线观看手机版 | 高清在线看 | 四虎2020紧急免费入口 | 羞羞私人影院可以直接免费观影吗 | 俺去也亚洲色图 | www.四虎com|