激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

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

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

延伸 · 閱讀

精彩推薦
1605
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 作爱在线观看 | 九九视频精品在线观看 | 久久精品a一级国产免视看成人 | 国产午夜三级一区二区三桃花影视 | 香蕉久久久精品 | 欧美综合日韩 | 黄色片免费在线 | 粉嫩粉嫩一区二区三区在线播放 | 韩国十九禁高潮床戏在线观看 | 久久久久国产视频 | 中文字幕精品在线视频 | 久久亚洲成人 | 国产精品久久久久久久久久三级 | 精品国产乱码久久久久久丨区2区 | 亚洲影院久久久av天天蜜桃臀 | 色播av在线| 久久精品之 | 欧美精品亚洲人成在线观看 | 久久亚洲美女视频 | 亚洲av毛片成人精品 | 国产亚洲精品久久午夜玫瑰园 | 成人乱人乱一区二区三区 | 久久精品99久久久久久2456 | 欧美在线成人影院 | 91久久另类重口变态 | 精品一区二区免费 | 国产免费久久久久 | 亚洲精品成人久久 | 一区二区三区黄色 | 日韩.www | 日本在线不卡一区二区 | 欧美成人免费小视频 | 天天夜夜操操 | 一级做a爱视频 | 色诱亚洲精品久久久久久 | 成年性羞羞视频免费观看 | 精品av在线播放 | 成人福利电影在线观看 | xnxx 日本免费 | 国产69精品久久久久久久久久 | 综合图区亚洲 |