如何实现Application event,观察者模式
spring 事件为bean 与 bean之间传递消息。一个bean处理完了希望其余一个接着处理.这时我们就需要其余的一个bean监听当前bean所发送的事件.
spring事件使用步骤如下:
1.先自定义事件:你的事件需要继承 ApplicationEvent
2.定义事件监听器: 需要实现 ApplicationListener
3.使用容器对事件进行发布
- 首先定义一个事件
/**
* @Title:
* @Auther: hangyu
* @Date: 2019/3/13
* @Description
* @Version:1.0
*/
public class TestEvent extends ApplicationEvent {
private String name;
private String msg;
public TestEvent(Object source){
super(source);
}
public TestEvent(Object source, String name, String msg) {
super(source);
this.name = name;
this.msg = msg;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
- 其次定义事件监听
/**
* @Title:
* @Auther: hangyu
* @Date: 2019/3/13
* @Description
* @Version:1.0
*/
@Component
public class TestEventListener implements ApplicationListener<TestEvent> {
@Async
@Override
public void onApplicationEvent(TestEvent testEvent) {
System.out.println("姓名:"+testEvent.getName()+"得到消息:"+testEvent.getMsg());
}
}
- 使用容器发布事件
/**
* @Title:
* @Auther: hangyu
* @Date: 2019/3/13
* @Description
* @Version:1.0
*/
@Component
public class TestEventPublisher {
@Autowired
private ApplicationContext applicationContext;
public void pushlish(String name, String msg){
applicationContext.publishEvent(new TestEvent(this, name,msg));
}
}
- 测试事件是否能够生效
/**
* @Title:
* @Auther: hangyu
* @Date: 2019/3/13
* @Description
* @Version:1.0
*/
@Configuration
@ComponentScan("cn.*.event")
public class EventConfig {
}
/**
* @Title:
* @Auther: hangyu
* @Date: 2019/3/13
* @Description
* @Version:1.0
*/
public class TestMain {
private static AnnotationConfigApplicationContext context;
public static void main(String[] args) {
start();
}
private static void start() {
if (context == null) {
context=new AnnotationConfigApplicationContext(EventConfig.class);
}
context.getBean(TestEventPublisher.class).pushlish("hangyu","申请退款!");
}
}

最后有一个思考:ApplicationEvent事件执行部分和起一个TaskExecutor去执行 有啥区别吗?反正都是异步。
可以这样实现;
@Autowired
private AsyncExecutor asyncExecutor;
Executor executor = asyncExecutor.getAsyncExecutor();
executor.execute(
//具体业务
});
@Configuration
@EnableAsync
public class AsyncExecutor implements AsyncConfigurer {
// 日志
static final Logger logger = LoggerFactory.getLogger(AsyncExecutor.class);
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5);
taskExecutor.setMaxPoolSize(10);
taskExecutor.setQueueCapacity(20000);
taskExecutor.setKeepAliveSeconds(120);
taskExecutor.setAllowCoreThreadTimeOut(true);
taskExecutor.initialize();
return taskExecutor;
}
}
还可以这样实现;
<!-- 异步线程池 -->
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<!-- 核心线程数 -->
<property name="corePoolSize" value="3" />
<!-- 最大线程数 -->
<property name="maxPoolSize" value="10" />
<!-- 队列最大长度 >=mainExecutor.maxSize -->
<property name="queueCapacity" value="25" />
<!-- 线程池维护线程所允许的空闲时间 -->
<property name="keepAliveSeconds" value="300" />
<!-- 线程池对拒绝任务(无线程可用)的处理策略 ThreadPoolExecutor.CallerRunsPolicy策略 ,调用者的线程会执行该任务,如果执行器已关闭,则丢弃. -->
<property name="rejectedExecutionHandler">
<bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
</property>
</bean>
@Resource
private TaskExecutor taskExecutor;
taskExecutor.execute(new Runnable() {
@Override
public void run() {
//具体业务
}
}

我的思考:ApplicationEvent是观察者设计模式,这种设计模式使得主题和观察者之间的耦合度降低,松耦合是面向对象设计中很重要的一个原则,最终也是使用@Async来实现异步。而TaskExecutor则是启动一个线程池任务异步执行任务,两者效果一样,但原理不同。
通过我的思考,又带来一个疑问:那观察者模式是不是就是我们MQ中的发布订阅模式呢?只不过观察者模式是进程内的,而MQ是跨进程的?就这唯一的区别吗?
经过一些资料的查阅:大多数地方观察者模式约等于发布订阅模式,但是观察者模式是由具体目标调度的,而发布/订阅模式是统一由调度中心调的,所以观察者模式的订阅者与发布者之间是存在依赖的,而发布/订阅模式则不会。
所以说观察者模式是小米加步枪,发布订阅模式是95式自动步枪,是它的进化版!
作者:杭宇_8ba6
链接:https://www.jianshu.com/p/e03c5c53d2e9
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
如何实现Application event,观察者模式的更多相关文章
- Spring 事件:Application Event
Spring Application Event Spring 的事件(Application Event)为 Bean 与 Bean 之间的消息通信提供了支持.当一个 Bean 处理完一个任务之后, ...
- Spring Application Event Example
Spring Application Event 项目结构 工程下载 https://github.com/xiaoheike/SpringApplicationEventExample.git Sp ...
- Spring Boot实战笔记(四)-- Spring常用配置(事件Application Event)
一.事件(Application Event) Spring的事件为Bean和Bean之间的消息通信提供了支持.当一个Bean处理完一个任务之后,希望另一个Bean知道并能做相应的处理,这时我们就需要 ...
- SpringBoot -- 事件(Application Event)
Spring的事件为Bean与Bean之间的消息通信提供了支持,当一个Bean处理完一个任务之后,希望另外一个Bean知道并能做相应的处理,这时我们就需要让一个Bean监听当前Bean所发送的事件. ...
- spring boot: 一般注入说明(五) @Component, application event事件为Bean与Bean之间通信提供了支持
spring的事件,为Bean与Bean之间通信提供了支持,当一个Bean处理完成之后,希望另一个Bean知道后做相应的事情,这时我们就让另外一个Bean监听当前Bean所发送的事件. spring的 ...
- 从命令模式的维度理解Spring 之Application Event
Spring的事件(Application Event)为Bean与Bean之间的信息通讯提供了支持.当一个Bean处理完一个任务之后,希望另一Bean指定并能做相应的处理,这时我们就需要让另外一个B ...
- spring 事件(Application Event)
spring 事件为bean 与 bean之间传递消息.一个bean处理完了希望其余一个接着处理.这时我们就需要其余的一个bean监听当前bean所发送的事件. spring事件使用步骤如下: 1.先 ...
- c++ 设计模式5 (Observer / Event 观察者模式)
3.3 观察者模式 (Observer)/发布-订阅模式 动机: 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都能得 ...
- 事件(Application Event)
Spring的事件(Appllcation Event)为Bean与Bean之间的消息通信提供了支持.当一个Bean处理完一个任务后,希望另一个Bean知道并能做相应的处理,这种情况可以让另一个Bea ...
随机推荐
- IdentityServer4系列 | 资源密码凭证模式
一.前言 从上一篇关于客户端凭证模式中,我们通过创建一个认证授权访问服务,定义一个API和要访问它的客户端,客户端通过IdentityServer上请求访问令牌,并使用它来控制访问API.其中,我们也 ...
- 使用Docker快速部署各类服务
使用Docker快速部署各类服务 一键安装Docker #Centos环境 wget -O- https://gitee.com/iubest/dinstall/raw/master/install. ...
- vue上传视屏或者图片到七牛云
首先下载七牛云的JavaScript-SDK npm install qiniu-js 下载完成JavaScript-SDK以后就可以上传图片信息了 <template> <div& ...
- KafKa简介和利用docker配置kafka集群及开发环境
KafKa的基本认识,写的很好的一篇博客:https://www.cnblogs.com/sujing/p/10960832.html 问题:1.kafka是什么?Kafka是一种高吞吐量的分布式发布 ...
- 记阿里云 RDS MySQL 的一个大坑
花了一个下午的时间,终于把一个阿里云 RDS MySQL 的一个大坑填上了,解决方法令人匪夷所思!绝对会让各位看官感到大吃一惊,阿里云 RDS MySQL 居然有这样 xx 的大坑! 问题 最近应业务 ...
- 第五篇 Scrum 冲刺博客
一.站立式会议 1. 会议照片 2. 工作汇报 团队成员名称 昨日(26日)完成的工作 今天(27日)计划完成的工作 工作中遇到的困难 陈锐基 - 完成发布页面的布局- 完成发布动态的功能 - 优化当 ...
- 使用JMeter进行负载测试快速入门
相信JMeter是很多测试人员必备技能之一,今天简单讲一下开发人员如何使用JMeter进行简单的压力测试快速入门. 安装JMeter Jmter官方地址 按提示下载JMeter,然后直接解压就可以用了 ...
- 【题单】最近遇见的 SHIT DP题 三连
Hint: 本题单适合用于自虐和消磨时间. CF-Gym101620E https://codeforces.com/gym/101620 ARC109F https://atcoder.jp/con ...
- 题解-Infinite Path
题解-Infinite Path \(\color{#9933cc}{\texttt{Infinite Path}}\) \(T\) 组测试数据.每次给你一个 \(n\) 的排列 \(\{p_n\}\ ...
- Angular:使用前端proxy代理解决跨域问题
①在项目文件的根目录下新建文件proxy.config.json { "/": { "target": "http://127.0.0.1:3000& ...