`

ApplicationEvent&ApplicationListener使用

阅读更多

在SpringBoot使用ApplicationEvent&ApplicationListener完成业务解耦

 

前言:

   项目中往往各个业务逻辑之间耦合性较强,因为我们在service都是直接引用的关联service或者jpa来作为协作处理逻辑,然而这种方式在后期更新、维护性难度都是大大提高了。通过使用事件通知、事件监听形式来处理逻辑时耦合性则是可以降到最小。

 

spring中事件监听实现   

ApplicationEvent、ApplicationListener是Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式,设计初衷也是为了系统业务逻辑之间的解耦,提高可扩展性以及可维护性。事件发布者并不需要考虑谁去监听,监听具体的实现内容是什么,发布者的工作只是为了发布事件而已。   

 

下面我们通过使用ApplicationEvent和ApplicationListener来完成简单的用户注册,以及注册成功后发送邮件的例子。

 

1、开始我们的示例之前,我们先定义一个User对象

public class User implements java.io.Serializable{

    

    private static final long serialVersionUID = 110406535439289650L;

    private String username;

    private String password;

 

//省略get/set方法

}

 

2、创建UserRegisterEvent

 

   定义一个用户注册事件,监听都是围绕着事件来挂起的。

 

public class UserRegisterEvent extends ApplicationEvent{

    

    private static final long serialVersionUID = -2493647928101170759L;

    

    //注册用户事件

    private User user;

    

    //重写构造函数

    public UserRegisterEvent(Object source,User user) {

        super(source);

        this.user = user;

    }

 

    public User getUser() {

        return user;

    }

 

    public void setUser(User user) {

        this.user = user;

    }

}

 

我们自定义事件UserRegisterEvent继承了ApplicationEvent,继承后必须重载构造函数,构造函数的参数可以任意指定,其中source参数指的是发生事件的对象,一般我们在发布事件时使用的是this关键字代替本类对象,而user参数是我们自定义的注册用户对象,该对象可以在监听内被获取。

 

3、创建UserService

UserService类中添加一个registerUser方法,该方法实现注册事件发布功能

 

@Service

public class UserService {

    

    @Autowired

    private ApplicationContext applicationContext;

    

    public void registerUser(User user){

//发布注册事件      

        applicationContext.publishEvent(new UserRegisterEvent(this, user));

    }

}

 

事件发布是由ApplicationContext对象管控的,我们发布事件前需要注入ApplicationContext对象调用publishEvent方法完成事件发布。

 

4、创建UserController

创建一个@RestController控制器,对应添加一个注册方法简单实现

 

@RestController

public class UserController {

 

    @Autowired

    private UserService userService;

    

    @RequestMapping("/user/register")

    public String registerUser(){

        

        User user = new User();

        user.setPassword("12346");

        user.setUsername("admin");

        //调用注册业务逻辑

        userService.registerUser(user);

        

        return "success";

    }

}

 

5、监听UserRegisterEvent事件

   在Spring内部中有多种方式实现监听如:@EventListener注解、实现ApplicationListener泛型接口、实现SmartApplicationListener接口等,我们下面来讲解下这三种方式分别如何实现。

 

6、@EventListener实现

   

@Component

public class AnnotationRegisterListener {

 

@EventListener

public void userRegister(UserRegisterEvent registerEvent){

System.out.println("注册的用户信息如下:"+registerEvent.getUser());

}

 

@EventListener

public void userRegisterEmail(UserRegisterEvent registerEvent){

System.out.println("用户注册成功"+registerEvent.getUser().getUsername()+",发送邮件");

}

}

 

我们只需要让我们的监听类被Spring所管理即可,在我们用户注册监听实现方法上添加@EventListener注解,该注解会根据方法内配置的事件完成监听。下面我们启动项目来测试下我们事件发布时是否被监听者所感知。

 

    测试事件监听

 

浏览器访问http://localhost:8080/user/register,调用接口注册用户,输出信息如下:

 

注册的用户信息如下:User [username=admin, password=12346]

    用户注册成功admin,发送邮件

 

可以看到我们使用@EventListener注解配置的监听已经生效了,当我们在UserService内发布了注册事件时,监听方法自动被调用并且输出内信息到控制台。

 

7、ApplicationListener实现监听

   在实现ApplicationListener接口时需要将监听事件作为泛型传递,监听实现代码

   

    @Component

public class RegisterApplicationListener implements ApplicationListener<UserRegisterEvent>{

 

@Override

public void onApplicationEvent(UserRegisterEvent event) {

System.out.println("用户注册信息如下:"+event.getUser());

}

}

 

@Component

public class RegisterEmailApplicationListener implements ApplicationListener<UserRegisterEvent>{

 

@Override

public void onApplicationEvent(UserRegisterEvent event) {

System.out.println("用户注册成功,发送邮件");

}

}

 

我们实现接口后需要使用@Component注解来声明该监听需要被Spring注入管理,当有UserRegisterEvent事件发布时监听程序会自动调用onApplicationEvent方法并且将UserRegisterEvent对象作为参数传递。

 

测试成功,同步骤6测试

 

8、SmartApplicationListener实现监听

   当多个listener监听同一个事件时,监听是无序的,监听到的事件先后顺序完全随机出现的,通过SmartApplicationListener可以实现监听逻辑的有序性。

   

    @Component

public class RegisterSmartApplicationListener implements SmartApplicationListener{

 

//supportsEventType和supportsSourceType返回为true时,才会执行监听

@Override

public void onApplicationEvent(ApplicationEvent event) {

 

System.out.println("用户注册信息如下:"+((UserRegisterEvent)event).getUser());

}

/**

* 同步情况下的事件监听顺序

* @see org.springframework.core.Ordered#getOrder()

*/

@Override

public int getOrder() {

//值越小,优先级越高,执行越靠前

return 0;

}

 

@Override

public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {

 

return eventType == UserRegisterEvent.class;

}

 

@Override

public boolean supportsSourceType(Class<?> sourceType) {

return sourceType == UserService.class;

}

}

       

@Component

public class RegisterEmainSmartApplicationListener implements SmartApplicationListener{

 

//supportsEventType和supportsSourceType返回为true时,才会执行监听

@Override

public void onApplicationEvent(ApplicationEvent event) {

System.out.println("用户注册成功,发送电子邮件"+((UserRegisterEvent)event).getUser());

}

 

/**

* 同步情况下的事件监听顺序

* @see org.springframework.core.Ordered#getOrder()

*/

@Override

public int getOrder() {

//值越小,优先级越高,执行越靠前,用户注册成功后才发送邮件

return 1;

}

 

@Override

public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {

 

return eventType == UserRegisterEvent.class;

}

 

@Override

public boolean supportsSourceType(Class<?> sourceType) {

return sourceType == UserService.class;

}

}   

 

通过SmartApplicationListener提供的getOrder方法,该方法可以实现监听的有序性,return的数值越小证明优先级越高,执行顺序越靠前。

 

测试同步骤6的测试

 

9、使用@Async实现异步监听

@Aysnc其实是Spring内的一个组件,可以完成对类内单个或者多个方法实现异步调用,这样可以大大的节省等待耗时。内部实现机制是线程池任务ThreadPoolTaskExecutor,通过线程池来对配置@Async的方法或者类做出执行动作。

 

配置线程池,如下:

 

@Configuration

@EnableAsync

public class AsyncConfig {

@Bean

public AsyncTaskExecutor getAsyncExecutor() {

ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();

threadPool.setCorePoolSize(2);//当前线程数

threadPool.setMaxPoolSize(50);// 最大线程数

threadPool.setQueueCapacity(100);//线程池所使用的缓冲队列

threadPool.setWaitForTasksToCompleteOnShutdown(true);//等待任务在关机时完成--表明等待所有线程执行完

threadPool.setThreadNamePrefix("provider-demo-");

threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

return threadPool;

}

}

 

使用@Async实现异步监听,在具体的监听方法onApplicationEvent上面添加Async注解,用法同普通的方法上面加Async注解一致

@Override

    @Async

    public void onApplicationEvent(ApplicationEvent applicationEvent) {

       

        System.out.println("用户注册成功,发送邮件通知。");

    }

 

 

注意:如果存在多个监听同一个事件时,并且存在异步与同步同时存在时则不存在执行顺序。

分享到:
评论

相关推荐

    Spring ApplicationListener的使用详解

    Spring ApplicationListener的使用详解 Spring ApplicationListener是Spring事件机制的一部分,通常与ApplicationEvent抽象类结合完成ApplicationContext的事件通知机制。下面我们将详细介绍Spring Application...

    SpringMVC事件监听ApplicationListener实例解析

    要使用ApplicationListener,需要实现ApplicationListener接口,其中T是监听的事件类型。例如,想要监听ServletRequestHandledEvent事件,可以定义一个类,实现ApplicationListener接口。然后,将该类注册为Spring...

    Spring ApplicationListener监听器用法详解

    本文主要介绍了Spring框架中的ApplicationListener监听器的用法详解,通过示例代码对 listeners 的实现和使用进行了详细的讲解,对大家的学习或者工作具有一定的参考学习价值。 一、什么是ApplicationListener? ...

    Java Spring框架面试题大全

    Spring使用ApplicationEvent和ApplicationListener两个核心接口实现了事件监听机制。开发者可以自定义事件类和事件监听器,并通过应用程序上下文的publishEvent方法来发布事件,Spring框架会自动分发事件给所有对该...

    SpringBoot事件发布及订阅详解含代码示例(值得珍藏)

    本文将深入探讨ApplicationEvent、ApplicationListener以及@EventListener这三个核心概念,并通过示例展示如何在SpringBoot应用中使用它们。 1. ApplicationEvent ApplicationEvent是Spring框架中的基础类,它代表...

    Java中介者模式实现类库组件Java版MediatR

    内容:中介者模式、观察者模式/监听者模式实现,用来消息发送和消息处理的解耦,以单播和多播形式同步或异步的模式发布消息,...能学到:ApplicationContext、ApplicationEvent、ApplicationListener,@EventListener

    Springboot事件监听源码

    Spring Boot使用Spring框架中的ApplicationEvent和ApplicationListener接口来实现事件发布和监听。首先,`ApplicationEvent`是所有自定义事件的基类,它继承了`java.util.EventObject`。当你创建一个新的事件时,...

    Spring的ApplicationEvent事件和监听器的测试Demo

    public class CustomEventListener implements ApplicationListener&lt;CustomEvent&gt; { @Override public void onApplicationEvent(CustomEvent event) { System.out.println("监听到事件:" + event.getEventData()...

    Spring Boot 详细启动原理

    public interface ApplicationListener&lt;E extends ApplicationEvent&gt; extends EventListener { void onApplicationEvent(E event); } ``` 在 SpringApplication 的 run 方法中,会调用 SpringApplication 的实例的...

    springboot07

    在SpringBoot中,我们可以利用ApplicationEvent和ApplicationListener进行事件驱动编程。发布一个事件(ApplicationEvent),然后注册监听器(ApplicationListener)来响应这个事件,这为系统间的解耦提供了便利。 ...

    tiny-spring-step-6-invite-application-context.zip

    3. 事件发布:通过ApplicationEvent和ApplicationListener机制,ApplicationContext可以广播自定义事件。 4. 更丰富的资源加载:ApplicationContext可以从多种来源(如文件系统、类路径、URL等)加载配置。 三、...

    跟着 Guava、Spring 学习如何设计观察者模式.doc

    Spring框架则提供了ApplicationEvent和ApplicationListener接口来实现观察者模式。当你有某个应用级别的事件需要广播时,可以创建一个继承自ApplicationEvent的自定义事件类。然后,通过ApplicationContext的publish...

    观察者模式java实现观察者设计模式

    在Java中,我们可以利用Java提供的内置监听器机制来实现观察者模式,例如`ApplicationListener`和`ApplicationEvent`,这两个类主要用于Swing或JavaFX应用程序中的事件处理。 首先,我们来看`ApplicationListener`...

    spring event

    监听器通过实现`ApplicationListener`接口或使用`@EventListener`注解来接收事件。 2. **创建和发布事件** 创建自定义事件类,继承自`ApplicationEvent`,然后在需要触发事件的地方,实例化这个类并调用`...

    SpringBoot + Redis实现事件的发布订阅功能

    - 如果你希望在Spring的事件模型中使用Redis,可以创建自定义的ApplicationEvent和ApplicationListener。发布事件时,使用`ApplicationEventPublisher`发布自定义事件,事件处理逻辑则在`ApplicationListener`中...

    spring boot 监听容器启动代码实例

    在本文中,我们将通过示例代码详细介绍如何使用自定义 ApplicationListener 来实现监听容器启动代码实例。 什么是 ApplicationListener? ApplicationListener 是 Spring 框架中的一种监听器接口,它可以在 Spring...

    spring技术手册demo

    Spring提供了一种事件驱动的模型,允许Bean之间通过ApplicationEvent和ApplicationListener进行解耦合的消息传递。这里会详细解释如何发布和监听自定义事件,以及Spring的事件处理机制。 **CH4_SpringAOP** Spring ...

    Spring的配置以及事件注入

    Spring提供了ApplicationEvent和ApplicationListener接口来实现事件处理。当你有一个事件需要在整个应用中传播时,可以创建一个自定义的事件类,继承自ApplicationEvent。例如: ```java public class CustomEvent ...

    spring 监听器浅析.docx

    这背后的关键接口是`ApplicationEvent`和`ApplicationListener`。 `ApplicationEvent`是Spring提供的基类,所有的自定义事件都应该继承自这个类。例如,`ContextRefreshedEvent`表示ApplicationContext被刷新,`...

Global site tag (gtag.js) - Google Analytics