观察者模式——Spring中使用

前言

  1. 观察者模式在 Spring 中的应用
  2. 观察者模式,在目标对象发出动作后,触发事件,观察者接收事件,然后执行对应操作。

步骤

  1. 观察者模型。
  2. 参考博客。看大佬博客写的文档学习。
  3. 思维导图。画图讲解清楚流程。(待定)
  4. 学习方法。怎么样学习。
  5. 注意点。
  6. pom 依赖。
  7. Main 方法编写。
  8. Controller 层。Http 请求发送使用
  9. register 层。编写事件类。
  10. service 层,目标对象,事件创建、发送类。
  11. service 层,观察者对象1,事件接收、执行类。
  12. service 层,观察者对象2,事件接收、执行类。

0. 观察者模型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5W3qS7uz-1618732055901)(WEBRESOURCE364d317fc37240740136e2aa75193e62)]

1. 参考博客

  1. 芋道源码《别再面向 for 循环编程了,Spring 自带的观察者模式就很香!》https://mp.weixin.qq.com/s/HrNEI3WcUKVcgbM3CaJmSg

3. 思维导图

  1. 测试方案
  2. 代码编写

4. 学习方法

  1. 看完模型,复制黏贴代码执行。

5. 注意点

  1. Spring 使用异步注解 @Async,需要在 Main 方法中注解 @EnableAsync 开启异步。
  2. 监听事件方式一:实现接口,重写方法
  3. 监听事件方式二:使用注解,方法入参传入要监听的事件。

6. pom 依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Spring-mock</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
        <relativePath/>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

7. Main 方法编写。

package com.jtfr;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync // 开启 Spring 异步的功能
public class SpringBootMain {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootMain.class, args);
    }
}

8. Controller 层。Http 请求发送使用

package com.jtfr.controller;

import com.jtfr.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private UserService userService;

    @GetMapping("/register")
    public String register(String username) {
        userService.register(username);
        return "success";
    }

}

9. register 层。编写事件类。

package com.jtfr.register;

import org.springframework.context.ApplicationEvent;

public class UserRegisterEvent extends ApplicationEvent {

    /**
     * 用户名
     */
    private String username;

    public UserRegisterEvent(Object source) {
        super(source);
    }

    public UserRegisterEvent(Object source, String username) {
        super(source);
        this.username = username;
    }

    public String getUsername() {
        return username;
    }

}
```

### 10. service 层,目标对象,事件创建、发送类。
```java
package com.jtfr.service;

import com.jtfr.register.UserRegisterEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;

// 1. 实现 ApplicationEventPublisherAware 接口,从而将 ApplicationEventPublisher 注入到其中。
@Service
public class UserService implements ApplicationEventPublisherAware {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private ApplicationEventPublisher applicationEventPublisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    public void register(String username) {
        // ... 执行注册逻辑
        System.out.println(Thread.currentThread().getName()+"[register][执行用户({}) 的注册逻辑]" + username);
        // ... 2. 在执行完注册逻辑后,调用 ApplicationEventPublisher 的 #publishEvent(ApplicationEvent event) 方法,发布 UserRegisterEvent 事件。
        applicationEventPublisher.publishEvent(new UserRegisterEvent(this, username));
    }

}
```

### 11. service 层,观察者对象1,事件接收、执行类。
```java
package com.jtfr.service;

import com.jtfr.register.UserRegisterEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

@Service
public class CouponService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @EventListener // 1. 在方法上,添加 @EventListener 注解,并设置监听的事件为 UserRegisterEvent。这是另一种使用方式!
    public void addCoupon(UserRegisterEvent event) {
        System.out.println(Thread.currentThread().getName()+"[addCoupon][给用户({}) 发放优惠劵]" + event.getUsername());
    }

}
```

### 12. service 层,观察者对象2,事件接收、执行类。
```java
package com.jtfr.service;

import com.jtfr.register.UserRegisterEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

// 1. 实现 ApplicationListener 接口,通过 E 泛型设置感兴趣的事件。
@Service
public class EmailService implements ApplicationListener<UserRegisterEvent> {


    @Override // 2. 实现 #onApplicationEvent(E event) 方法,针对监听的 UserRegisterEvent 事件,进行自定义处理。
    @Async // 3. 锦上添花,设置 @Async 注解,声明异步执行。毕竟实际场景下,发送邮件可能比较慢,又是非关键逻辑。
    public void onApplicationEvent(UserRegisterEvent event) {
        System.out.println(Thread.currentThread().getName()+"[onApplicationEvent][给用户({}) 发送邮件]" + event.getUsername());
    }

}
```
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值