在spring中使用自定义注解注册监听器的方法

2025-05-27 0 44

接口回调

监听器本质上就是利用回调机制,在某个动作发生前或后,执行我们自己的一些代码。在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 ...

已经调用了监听方法。在接下来的开发中,就可以使用这个注解注册监听器了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。

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

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 在spring中使用自定义注解注册监听器的方法 https://www.kuaiidc.com/76202.html

相关文章

发表评论
暂无评论