浅谈Spring事件机制

柔光的暖阳◎ 2021-08-28 17:05 594阅读 0赞

一、同步事件和异步事件

同步事件:在一个线程里,按顺序执行业务,做完一件事再去做下一件事。

异步事件:在一个线程里,做一个事的同事,可以另起一个新的线程执行另一件事,这样两件事可以同时执行。

用一个例子来解释同步事件和异步事件的使用场景,有时候一段完整的代码逻辑,可能分为几部分,拿最常见的注册来说,假设完整流程是:

1、点击注册;

2、检验信息并存库;

3、发送邮件;

4、返回给用户。

代码这么写是正确,但不是最好的,缺点如下:

① 逻辑复杂,业务耦合。

② 效率低

加入2和3分别需要1秒,那么用户在点击注册2秒后才能有结果。

同步事件可以帮我们解决①问题,我们把发邮件的方法独立处理,放到事件里执行,这样注册的这个方法就只做两步,完成之后发布一个事件去执行3,可以很好的解决业务耦合的问题。

异步事件可以完美解决以上两个问题,注册方法执行2操作,执行之后发布一个异步事件,另起一个线程执行3操作,注册方法所在的线程可直接返回给用户,这样不仅实现了业务解耦还提高了效率,用户点击注册,1秒后就能看到响应。

二、Spring事件机制

Spring事件发送监听涉及三个部分

1、ApplicationEvent

表示事件本身,自定义事件需要继承该类,可以用来传递数据,比如上述发邮件操作

2、ApplicationEventPublishAware

事件发送器,通过实现这个接口,来触发事件

3、ApplicationListener

事件监听器接口,事件的业务逻辑封装在监听器里面

三、异步事件机制模拟实现注册

配置文件和注解两种方式。

1、配置文件方式

TestEvent

  1. public class TestEvent extends ApplicationEvent {
  2. private TestParam source;
  3. public TestEvent(TestParam source) {
  4. super(source);
  5. this.source = source;
  6. }
  7. }
  8. @Data
  9. public class TestParam {
  10. private String email;
  11. }

TestListener

  1. @Component
  2. public class TestListener implements ApplicationListener<TestEvent> {
  3. @Override
  4. public void onApplicationEvent(TestEvent testEvent) {
  5. TestParam param = (TestParam) testEvent.getSource();
  6. System.out.println(".......开始.......");
  7. System.out.println("发送邮件:"+param.getEmail());
  8. System.out.println(".......结束.....");
  9. }
  10. }

TestPublish

  1. @Component
  2. public class TestPublish implements ApplicationEventPublisherAware {
  3. private static ApplicationEventPublisher applicationEventPublisher;
  4. @Override
  5. public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
  6. TestPublish.applicationEventPublisher = applicationEventPublisher;
  7. }
  8. public static void publishEvent(ApplicationEvent communityArticleEvent) {
  9. applicationEventPublisher.publishEvent(communityArticleEvent);
  10. }
  11. }

spring-context.xml

  1. <bean id="applicationEventAsyncMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster">
  2. <property name="taskExecutor">
  3. <bean class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
  4. <property name="corePoolSize" value="5"/>
  5. <property name="keepAliveSeconds" value="3000"/>
  6. <property name="maxPoolSize" value="50"/>
  7. <property name="queueCapacity" value="200"/>
  8. </bean>
  9. </property>
  10. </bean>

注意:如果加<propery name=”taskExecutor”,则使用异步方式执行,否则为同步方式。

2、注解方式

使用@Async需要在配置文件添加一下支持,线程池也是需要配置一下的

  1. <!-- 开启@AspectJ AOP代理 -->
  2. <aop:aspectj-autoproxy proxy-target-class="true"/>
  3. <!-- 任务执行器 -->
  4. <task:executor id="executor" pool-size="10"/>
  5. <!--开启注解调度支持 @Async -->
  6. <task:annotation-driven executor="executor" proxy-target-class="true"/>
  7. TestListener中在方法中添加@Async
  8. @Component
  9. public class TestListener implements ApplicationListener<TestEvent> {
  10. @Async
  11. @Override
  12. public void onApplicationEvent(TestEvent testEvent) {
  13. TestParam param = (TestParam) testEvent.getSource();
  14. System.out.println(".......开始.......");
  15. System.out.println("发送邮件:"+param.getEmail());
  16. System.out.println(".......结束.....");
  17. }
  18. }

Listener其实还可以做得更彻底一点,使用注解@EventListener可代替实现ApplicationListener,原理是通过扫描这个注解来创建监听器并自动添加到ApplicationContext中。

TestListenerHandler

  1. @Component
  2. public class TestEventHandler {
  3. @Async
  4. @EventListener
  5. public void handleTestEvent(TestEvent testEvent) {
  6. TestParam param = (TestParam) testEvent.getSource();
  7. System.out.println(".......开始.......");
  8. System.out.println("发送邮件:"+param.getEmail());
  9. System.out.println(".......结束.....");
  10. }
  11. }

四、总结

使用Spring事件机制能很好地帮助我们消除不同业务间的耦合关系,也可以提高执行效率,应该根据业务场景灵活选择。

发表评论

表情:
评论列表 (有 0 条评论,594人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Spring AOP

    > AOP(Aspect Oriented Programming):⾯向切⾯编程,它是⼀种思想,它是对某⼀类事情的集中处理。⽐如⽤户登录权限的效验,没学 AOP 之前,我们所

    相关 Spring

    Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。 一、什么是IOC? IoC = Inversion of Control 翻译成中⽂是

    相关 spring

    常用注解: @Component (不推荐使用):注册一个bean到spring,一般使用前三个来指示不同层的bean @Autowired @Resource @R

    相关 Spring注解

    Spring目前的趋势是使用注解结合Java代码而不是配置来定义行为、属性、功能、规则和扩展点,因此梳理注解也是梳理Spring功能点的很好的方式,全面的梳理可以补足我们知识点

    相关 Spring事件机制

    一、同步事件和异步事件 同步事件:在一个线程里,按顺序执行业务,做完一件事再去做下一件事。 异步事件:在一个线程里,做一个事的同事,可以另起一个新的线程执行另一件事,这