详解Spring中的ApplicationListener和ContextRefreshedEvent
ApplicationListener和ContextRefreshedEvent一般都是成对出现的。最近在面试中问到了被面试者对于这两个的用法,面试者大多数被问懵了。可见基础知识的掌握程度。基于此本文将介绍它们的用法。
事件机制作为一种编程机制,在许多语言中都提供了支持。JAVA语言也不例外,java中的事件机制的参与者有3种角色:
- event object
- event source
- event listener
这三个角色的含义字面上很好解,它们就定义了事件机制的一个基本模型。作为一种常用的编程设计机制,许多开源框架的设计中都使用了事件机制。SpringFramework也不例外。
在IOC的容器的启动过程,当所有的bean都已经处理完成之后,spring ioc容器会有一个发布事件的动作。从 AbstractApplicationContext 的源码中就可以看出:
protected void finishRefresh() {
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// 业余草:www.xttblog.com
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
这样,当ioc容器加载处理完相应的bean之后,也给我们提供了一个机会(先有InitializingBean,后有ApplicationListener<ContextRefreshedEvent>),可以去做一些自己想做的事。其实这也就是spring ioc容器给提供的一个扩展的地方。我们可以这样使用这个扩展机制。
org.springframework.context.ApplicationEvent
org.springframework.context.ApplicationListener
一个最简单的方式就是,让我们的bean实现ApplicationListener接口,这样当发布事件时,spring的ioc容器就会以容器的实例对象作为事件源类,并从中找到事件的监听者,此时ApplicationListener接口实例中的onApplicationEvent(E event)方法就会被调用,我们的逻辑代码就会写在此处。这样我们的目的就达到了。但这也带来一个思考,有人可能会想,这样的代码我们也可以通过实现spring的InitializingBean接口来实现啊,也会被spring容器去自动调用,但是大家应该想到,如果我们现在想做的事,是必须要等到所有的bean都被处理完成之后再进行,此时InitializingBean接口的实现就不合适了,所以需要深刻理解事件机制的应用场合。
曾经有一位同事利用 ApplicationListener,重复加载了好几次 xml 配置文件。所以基础知识一定要掌握。
下面是一个完整的例子:
public class ApplicationContextListener implements ApplicationListener<ContextRefreshedEvent> {
private static Logger _log = LoggerFactory.getLogger(ApplicationContextListener.class);
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
// root application context
if(null == contextRefreshedEvent.getApplicationContext().getParent()) {
_log.debug(">>>>> spring初始化完毕 <<<<<");
// spring初始化完毕后,通过反射调用所有使用BaseService注解的initMapper方法
Map<String, Object> baseServices =
contextRefreshedEvent.getApplicationContext().getBeansWithAnnotation(BaseService.class);
for(Object service : baseServices.values()) {
_log.debug(">>>>> {}.initMapper()", service.getClass().getName());
try {
Method initMapper = service.getClass().getMethod("initMapper");
initMapper.invoke(service);
} catch (Exception e) {
_log.error("初始化BaseService的initMapper方法异常", e);
e.printStackTrace();
}
}
// 系统入口初始化
Map<String, BaseInterface> baseInterfaceBeans =
contextRefreshedEvent.getApplicationContext().getBeansOfType(BaseInterface.class);
for(Object service : baseInterfaceBeans.values()) {
_log.debug(">>>>> {}.init()", service.getClass().getName());
try {
Method init = service.getClass().getMethod("init");
init.invoke(service);
} catch (Exception e) {
_log.error("初始化BaseInterface的init方法异常", e);
e.printStackTrace();
}
}
}
}
}
以上就是ApplicationListener和ContextRefreshedEvent的相关用法。
详解Spring中的ApplicationListener和ContextRefreshedEvent的更多相关文章
- 用IDEA详解Spring中的IoC和DI(挺透彻的,点进来看看吧)
用IDEA详解Spring中的IoC和DI 一.Spring IoC的基本概念 控制反转(IoC)是一个比较抽象的概念,它主要用来消减计算机程序的耦合问题,是Spring框架的核心.依赖注入(DI)是 ...
- 使用IDEA详解Spring中依赖注入的类型(上)
使用IDEA详解Spring中依赖注入的类型(上) 在Spring中实现IoC容器的方法是依赖注入,依赖注入的作用是在使用Spring框架创建对象时动态地将其所依赖的对象(例如属性值)注入Bean组件 ...
- 详解Spring中Bean的作用域与生命周期
摘要:在利用Spring进行IOC配置时,关于bean的配置和使用一直都是比较重要的一部分,同时如何合理的使用和创建bean对象,也是小伙伴们在学习和使用Spring时需要注意的部分,所以这一篇文章我 ...
- 【Spring】详解Spring中Bean的加载
之前写过bean的解析,这篇来讲讲bean的加载,加载要比bean的解析复杂些,该文之前在小编原文中有发表过,要看原文的可以直接点击原文查看,从之前的例子开始,Spring中加载一个bean的方式: ...
- 详解Spring中的Profile
前言 由于在项目中使用Maven打包部署的时候,经常由于配置参数过多(比如Nginx服务器的信息.ZooKeeper的信息.数据库连接.Redis服务器地址等),导致实际现网的配置参数与测试服务器参数 ...
- 详解Spring中的CharacterEncodingFilter
在项目中有很多让人头疼的问题,其中,编码问题位列其一,那么在Spring框架中是如何解决从页面传来的字符串的编码问题的呢?下面我们来看看Spring框架给我们提供过滤器CharacterEncodin ...
- 详解Spring中的CharacterEncodingFilter--forceEncoding为true在java代码中设置失效--html设置编码无效
在项目中有很多让人头疼的问题,其中,编码问题位列其一,那么在Spring框架中是如何解决从页面传来的字符串的编码问题的呢?下面我们来看看Spring框架给我们提供过滤器CharacterEncodin ...
- applicationContext.xml详解 spring+mybatis+struts
今天给大家详细解释一项关于Spring的applicationContext.xml文件,这对于初学者来说,应该是很有帮助的, 以下是详解Spring的applicationContext.xml文件 ...
- 【转】详解spring 每个jar的作用
spring.jar 是包含有完整发布模块的单个jar 包.但是不包括mock.jar, aspects.jar, spring-portlet.jar, and spring-hibernate2. ...
随机推荐
- 一个简单的 vue.js 实践教程
https://segmentfault.com/a/1190000006776243?utm_source=tuicool&utm_medium=referral 感觉需要改善的地方有: ( ...
- Socket网络编程(一)
1.什么是网络通讯?(udp.tcp.netty.mina) udp:漂流瓶,每个人都可以向大海里面扔漂流瓶,不管有没有人捡到.(不管接收方有没有,我只往指定的地址发送东西,64kb以内) tcp:电 ...
- D3.js+Es6+webpack构建人物关系图(力导向图),动态更新数据,点击增加节点,拖拽增加连线...
觉得不错的麻烦加个Star:https://github.com/zhangzn3/D3-Es6 在线预览地址:https://zhangzn3.github.io/D3-Es6 功能列表:1. 增加 ...
- 【supervisor】监控服务
写了一个ftp服务,用supervisor监控一下 1.先写一个配置文件,路径和名称为/etc/supervisord.conf.d/ftp-server.ini [program:ftp-serve ...
- react 使用draft.js富文本编辑器
参照网址:https://www.cnblogs.com/3body/p/6224010.html 参看网址:https://www.cnblogs.com/mosquito18/p/9787816. ...
- phoenix表操作
phoenix表操作 进入命令行,这是sqlline.py 配置到path环境变量的情况下 sqlline.py localhost如果要退出命令行:!q 或者 !quit 3.4.1 创建表 ...
- 如何让微信里的html应用弹出“点击右上角分享到朋友圈”的图片
一个分享按钮,一个隐藏的图片(这个图片绝对定位在右上角)然后就是点击显示,点击隐藏了... <a href="javascript:;" onclick="docu ...
- mysql表管理
4.1 查看所有表 查看所有表语句: show tables; 例: mysql> show tables; +-----------------+ | Tables_in_emp | +--- ...
- phpmyadmin详细的图文使用教程
做网站用到服务器有很多站长应该都会用到数据库,那么phpmyadmin的使用也会是很多新手站长头大的问题,下面小编详细介绍一下phpmyadmin详细的图文使用教程. 方法/步骤 如何进入ph ...
- springmvc基础使用配置
前言 本案例是在idea编辑器下,maven管理项目的前提下. 步骤 1.新建maven项目 2.配置web.xml <?xml version="1.0" encoding ...