如何实现Application event,观察者模式

  • 时间:2019-06-11 02:24 作者:杭宇_8ba6 来源:杭宇_8ba6 阅读:119
  • 扫一扫,手机访问
摘要:spring 事件为bean 与 bean之间传递消息。一个bean解决完了希望其他一个接着解决.这时我们就需要其他的一个bean监听当前bean所发送的事件.spring事件使用步骤如下:1.先自己设置事件:你的事件需要继承 ApplicationEvent2.定义事件监听器: 需要实现 Appli

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 */@Componentpublic 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 */@Componentpublic 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@EnableAsyncpublic 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式自动步枪,是它的进化版!

  • 全部评论(0)
最新发布的资讯信息
【系统环境|】2019年web前端开发技术框架有哪些(2019-07-20 12:06)
【系统环境|】什么是Web?零基础能不能学Web前端开发?(2019-07-19 07:04)
【网页前端|HTML】为什么学Web前端?选择Web前端理由(2019-07-17 20:28)
【网页前端|JS】Java面经-百度新入职老哥整理近半年学习经验,面试刷题路线!(2019-07-16 22:16)
【网页前端|HTML】最全面的前端开发指南(2019-07-15 12:57)
【系统环境|数据库】零基础如何快速学好大数据?(2019-06-29 12:27)
【系统环境|Linux】零基础如何学好大数据?必备需要学习知识(2019-06-18 11:54)
【系统环境|】Hadoop环境中管理大数据存储八大技巧(2019-06-15 11:01)
【系统环境|服务器应用】现在国内IT行业是不是程序员过多了?(2019-06-11 06:34)
【系统环境|服务器应用】新贵 Flutter(2) 自己设置 Widget(2019-06-11 06:34)
手机二维码手机访问领取大礼包
返回顶部