最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在spring中使用自定義注解注冊監(jiān)聽器的方法

 更新時間:2018年01月23日 10:45:43   作者:silenceyawen  
本篇文章主要介紹了在spring中使用自定義注解注冊監(jiān)聽器的方法,本文就是在分析監(jiān)聽器回調(diào)原理的基礎(chǔ)上,在spring環(huán)境中使用自定義的注解實現(xiàn)一個監(jiān)聽器。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

接口回調(diào)

監(jiān)聽器本質(zhì)上就是利用回調(diào)機(jī)制,在某個動作發(fā)生前或后,執(zhí)行我們自己的一些代碼。在Java語言中,可以使用接口來實現(xiàn)。

實現(xiàn)一個監(jiān)聽器案例

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

1. 定義回調(diào)的接口

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
 */
@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()方法的適當(dāng)時機(jī),調(diào)用前面定義的接口。此外,在這個動作定義類中,需要提高設(shè)置監(jiān)聽器的方法。

3. 監(jiān)聽測試

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

  @Resource
  private MyService myService;

  @Test
  public void test1() {
    // 接口設(shè)置監(jiān)聽器
    myService.setWorkListener(new WorkListener() {
      @Override
      public void onStart(String name) {
        System.out.println("Start work for " + name + " !");
      }
    });
//    // lambda 表達(dá)式設(shè)置監(jiān)聽器
//    myService.setWorkListener(name -> System.out.println("Start work for " + name + " !"));
    // 工作
    myService.work("boss");
  }

 @Test
  public void test2() {
   // 繼承實現(xiàn)類設(shè)置監(jiān)聽器
   myService.setWorkListener(new myWorkListener());
   // 工作
   myService.work("boss");
  }

  class myWorkListener extends WorkListenerAdaptor {
    @Override
    public void onStart(String name) {
      System.out.println("Start work for " + name + " !");
    }
  }
}

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

Start work for boss !
working hard ...

說明在動作work發(fā)生之前,執(zhí)行了我們在測試類中寫下的監(jiān)聽代碼,實現(xiàn)類監(jiān)聽的目的。

使用注解實現(xiàn)監(jiān)聽器

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

的確,使用變得簡單了,但實現(xiàn)卻不見得。

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
 */
@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 需要進(jìn)行掃描的類級注解類型
   * @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;
  }
}

在注解的解析過程中,設(shè)置監(jiān)聽器。

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

3. 測試

在執(zhí)行完以上代碼后,監(jiān)聽器就已經(jīng)設(shè)置好了,可以進(jìn)行測試了。

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 + " !");
  }
}

寫一個監(jiān)聽方法,參數(shù)類型和個數(shù)與接口相同,然后加上自定義的注解即可。當(dāng)啟動環(huán)境后,監(jiān)聽器就已經(jīng)設(shè)置好了。

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

Start work for boss !
working hard ...

已經(jīng)調(diào)用了監(jiān)聽方法。在接下來的開發(fā)中,就可以使用這個注解注冊監(jiān)聽器了。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java中switch-case結(jié)構(gòu)的使用方法舉例詳解

    Java中switch-case結(jié)構(gòu)的使用方法舉例詳解

    這篇文章主要介紹了Java中switch-case結(jié)構(gòu)使用的相關(guān)資料,switch-case結(jié)構(gòu)是Java中處理多個分支條件的一種有效方式,它根據(jù)一個表達(dá)式的值來執(zhí)行不同的代碼塊,需要的朋友可以參考下
    2025-01-01
  • 淺析Java的Hibernate框架中的緩存和延遲加載機(jī)制

    淺析Java的Hibernate框架中的緩存和延遲加載機(jī)制

    這篇文章主要介紹了Java的Hibernate框架中的緩存和延遲加載機(jī)制,Hibernate是注明的Java下SSH三大web開發(fā)框架之一,需要的朋友可以參考下
    2015-11-11
  • Java?file.delete刪除文件失敗,Windows磁盤出現(xiàn)無法訪問的文件問題

    Java?file.delete刪除文件失敗,Windows磁盤出現(xiàn)無法訪問的文件問題

    這篇文章主要介紹了Java?file.delete刪除文件失敗,Windows磁盤出現(xiàn)無法訪問的文件問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • spring AOP的Around增強(qiáng)實現(xiàn)方法分析

    spring AOP的Around增強(qiáng)實現(xiàn)方法分析

    這篇文章主要介紹了spring AOP的Around增強(qiáng)實現(xiàn)方法,結(jié)合實例形式分析了spring面向切面AOP的Around增強(qiáng)具體步驟與相關(guān)操作方法,需要的朋友可以參考下
    2020-01-01
  • Java full gc觸發(fā)情況實例解析

    Java full gc觸發(fā)情況實例解析

    這篇文章主要介紹了Java full gc觸發(fā)情況實例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • spring boot3整合AI組件及使用方法

    spring boot3整合AI組件及使用方法

    本文介紹了springboot開發(fā)后端服務(wù)中,AI組件(Spring AI)的整合與使用,本文通過實例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • rabbitmq basicReject/basicNack/basicRecover的區(qū)別及說明

    rabbitmq basicReject/basicNack/basicRecover的區(qū)別及說明

    這篇文章主要介紹了rabbitmq basicReject/basicNack/basicRecover的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 淺談關(guān)于Java正則和轉(zhuǎn)義中\(zhòng)\和\\\\的理解

    淺談關(guān)于Java正則和轉(zhuǎn)義中\(zhòng)\和\\\\的理解

    這篇文章主要介紹了淺談關(guān)于Java正則和轉(zhuǎn)義中\(zhòng)\和\\\\的理解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • java ReentrantLock詳解

    java ReentrantLock詳解

    這篇文章主要介紹了java ReentrantLock,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 聊聊@RequestMapping和@GetMapping @PostMapping的區(qū)別

    聊聊@RequestMapping和@GetMapping @PostMapping的區(qū)別

    這篇文章主要介紹了@RequestMapping和@GetMapping及@PostMapping的區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08

最新評論

荣成市| 康保县| 石景山区| 含山县| 临潭县| 邯郸县| 永善县| 天峨县| 周至县| 响水县| 海丰县| 通河县| 海淀区| 彩票| 太湖县| 宿州市| 英超| 雷山县| 甘南县| 八宿县| 邯郸县| 遵义市| 长岭县| 原平市| 兴城市| 陇川县| 鸡东县| 鲜城| 清镇市| 双鸭山市| 深水埗区| 镶黄旗| 壤塘县| 浙江省| 若尔盖县| 板桥市| 东阿县| 上犹县| 新郑市| 江川县| 兴山县|