美文网首页
SpringBoot2.1监听的使用

SpringBoot2.1监听的使用

作者: 也许________ | 来源:发表于2018-12-16 18:42 被阅读26次

什么是监听?
https://www.cnblogs.com/w-wfy/p/6425357.html

监听的用途很多,根据业务需要可以选择适当的监听来完成想要处理的功能,这里使用监听来完成业务的解耦。

用户注册流程:
①数据入库 -> ②发送激活用户邮件 -> ③赠送初始积分

当用户注册时,主流程其实只需完成①数据入库,然后返回注册成功信息给用户,主流程其实就可以结束了,如果②和③也跟①写到一起,那么注册耗时将变长,用户体验变差,这时需要进行业务的拆分,主流程只需要完成①,子流程②和③拆分出来。使用监听器,当应用监听到用户注册事件,单独去完成②和③,从而达到不阻塞主流程的目的。
截图是伪代码,需要你脑补一下实际代码。。。😄

创建事件

监听是围绕着事件进行处理的,所以需要先创建用户注册的事件,继承ApplicationEvent,并重载方法
public ApplicationEvent(Object source) {
super(source);
}

public class RegistUserEvent extends ApplicationEvent {

    private User user;

    public RegistUserEvent(Object source, User user) {
        super(source);
        this.user = user;
    }

    public User getUser() {
        return user;
    }
}
创建监听(注解形式)

使用注解来注册监听事件@EventListener,类的注解@Component不能忽略,否则事件将不会被监听到

/**
 * 注解形式的监听
 */
@Component
public class AnnotationRegistUserListen {

    Logger logger = LoggerFactory.getLogger(AnnotationRegistUserListen.class);

//    @Async
    @EventListener
    public void registUser(RegistUserEvent registUserEvent) {
        try {
            Thread.sleep(5000L);
        } catch (Exception e) {
            e.printStackTrace();
        }
        User user = registUserEvent.getUser();
        logger.info("注解形式的监听{}", JSONObject.toJSONString(user));

    }

}
创建监听(接口形式)

实现接口ApplicationListener并指定泛型为RegistUserEvent,重载方法onApplicationEvent,当调用监听时方法将会被执行。

/**
 * 实现接口形式的监听
 */
@Component
public class InterfaceRegistUserListen implements ApplicationListener<RegistUserEvent> {

    Logger logger = LoggerFactory.getLogger(InterfaceRegistUserListen.class);

    //@Async
    @Override
    public void onApplicationEvent(RegistUserEvent registUserEvent) {

        try {
            Thread.sleep(5000);
            User user = registUserEvent.getUser();
            logger.info("实现接口形式的监听{}", JSONObject.toJSONString(user));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
创建监听(可以指定调用顺序的方式)

前面两种方式创建的监听是无序的,通过这种方式创建的监听,使用getOrder可以指定执行的顺序,值越小将优先调用
ps:
只有在方法为同步状态下时,排序才有效

/**
 * 同步状态下,可以指定顺序的监听实现
 */
@Component
public class SendMailListen implements SmartApplicationListener {

    Logger logger = LoggerFactory.getLogger(SendMailListen.class);

    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        return RegistUserService.class == sourceType;
    }

    @Override
    public int getOrder() {
        return 100;
    }

    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) {
        return RegistUserEvent.class == aClass;
    }

    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        RegistUserEvent registUserEvent = (RegistUserEvent)applicationEvent;
        logger.info("发送邮件的监听{}", JSONObject.toJSONString(registUserEvent.getUser()));
    }

}
调用监听

在业务层使用上下文发布事件,参数传入前面创建的注册事件,监听方法就会被调用,由于前面创建的三种监听都依赖于RegistUserEvent,所以三个监听内的方法都会被调用执行

@RestController
public class RegistUserController {

    Logger logger = LoggerFactory.getLogger(RegistUserController.class);

    @Autowired
    private RegistUserService registUserService;

    @RequestMapping("/registUser")
    public String registUser() {

        User user = new User();
        user.setUsername("test");
        user.setPassword("123456");
        registUserService.registUser(user);

        return UUID.randomUUID().toString();
    }
    
}

@Service
public class RegistUserService {

    @Autowired
    ApplicationContext applicationContext;

    /**
     * 注册用户
     * @param user
     * @return
     */
    public String registUser(User user) {
        // 发布事件
        applicationContext.publishEvent(new RegistUserEvent(this, user));
        return "success";
    }

}

使用监听的注意事项:

①前两种方式创建的监听是无序执行的
②第三种方式实现接口SmartApplicationListener创建的监听方法必须在同步状态下才有效
③创建的监听,默认是同步执行的,换句话说,监听方法会阻塞主线程,必须所有监听方法完成后,才会反馈注册成功信息给用户(所以使用SmartApplicationListener创建的监听方法就不适用于解决业务解耦)

关于第三点怎么验证,观察代码,在监听方法中日志输出前,程序会睡眠5秒再输出日志,跑起程序会发现注册成功信息会在所有监听方法执行完成后才会反馈给用户,这样做哪里实现了业务的解耦?
只需在监听方法上添加注解@async,声明是异步方法即可,这个注解其实就是另起线程执行方法,所以就不会阻塞主进程的执行,这样就完成了业务的解耦。

ps:
现在业务的解耦都使用MQ,MQ的功能远比监听强大的多,当然监听的作用还有很多,具体业务具体分析,选择最合适的功能来达成目的就可以。

相关文章

  • SpringBoot2.1监听的使用

    什么是监听?https://www.cnblogs.com/w-wfy/p/6425357.html监听的用途很多...

  • SpringBoot+FreeMarker+SiteMesh环境

    准备搭建SpringBoot+FreeMarker+SiteMesh的框架,选用了springBoot2.1版本,...

  • vue监听和webpack基本使用

    vue监听 使用keyup监听 使用watch监听文本框变化,watch 使用这个属性可以监视data中的数据变化...

  • 1.Vue- Watch(监听props/data)

    监听基本使用 监听props/data deep 深度监听,可监听到对象、数组的变化

  • 监听音量键的两种方法

    1、使用KVO监听属性outputVolume 首先,注册监听 在监听的回调中判断是否是我们监听的属性,所有使用K...

  • KVO如何才能直接监听到数组的变化

    转自关于使用KVO监听数组的问题 首先,数组不能直接使用KVO使用监听。当我们想要使用KVO监听数组的状态时改变然...

  • DOM事件委托

    使用场景 监听重复的事件===>用于节省监听数(内存小) 监听当前暂时还没有的元素===>动态监听元素 使用方法

  • KVO使用及实现原理

    KVO使用及实现原理 KVO使用 对属性进行监听 对属性的属性进行监听 容器监听 触发(手动触发,kvc赋值) 添...

  • KVO

    基础使用 监听一个对象的属性变化,比如监听TCKVOObject的name属性 监听 回调 移除监听 触发 打印 ...

  • KVO - NSKeyValueObserving

    KVO: 三个步骤: 1. 注册监听 2. 使用回调,对监听对象处理 3. 移除监听 // 使用UITextFie...

网友评论

      本文标题:SpringBoot2.1监听的使用

      本文链接:https://www.haomeiwen.com/subject/gwsxkqtx.html