监听器如何获取Spring配置文件
我们在做项目的时候,会用到监听器去获取spring的配置文件,然后从中拿出我们需要的bean出来,比如做网站首页,假设商品的后台业务逻辑都做好了,我们需要创建一个监听器,在项目启动时将首页的数据查询出来放到application里,即在监听器里调用后台商品业务逻辑的方法,也就是说我们需要在监听器里获取Spring中配置的相应的bean。先把监听器创建出来:
创建一个监听器InitDataListener继承ServletContextListener:
*/ //@Component //监听器是web层的组件,它是tomcat实例化的,不是Spring实例化的。不能放到Spring中 public class InitDataListener implements ServletContextListener { private ProductService productService = null;//productService中定义了跟商品相关的业务逻辑 @Override public void contextDestroyed(ServletContextEvent event) { } @Override public void contextInitialized(ServletContextEvent event) { }
并在web.xml中配置该监听器:
如上,productService中定义了商品的一些业务逻辑,并且这个productService是交给Spring管理的,那么我们如何得到这个对象呢?首先肯定的一点是:我们不能自己new出来,因为new出来的话就跟Spring的IoC没有关系了……主要有三种方式可以实现,我们先一个个分析,最后比较优劣。
2. 直接加载beans.xml文件这种方式比较简单粗暴,不是要加载配置文件么?那好,我加载就是了,如下:
//@Component //监听器是web层的组件,它是tomcat实例化的,不是Spring实例化的。不能放到Spring中 public class InitDataListener implements ServletContextListener { private ProductService productService = null; //productService中定义了跟商品相关的业务逻辑 @Override public void contextDestroyed(ServletContextEvent event) { } @Override public void contextInitialized(ServletContextEvent event) { // 获取业务逻辑类productService查询商品信息 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); productService = (ProductService) context.getBean("productService"); System.out.println(productService); //输出看看拿到了没有 //下面是具体productService相关操作…… }
这种方法完全没问题,思路很清晰,先加载配置文件beans.xml,然后获取bean,但是启动tomcat后,我们看看控制台输出的信息:
到这里应该发现这种方式的弊端了,加载了两次配置文件,也就是说那些bean被实例化了两次,从打印的信息来看,是拿到我们自己加载配置文件是实例化的bean。这种方式明显不可取。
3. 从ServletContext中获取从上面的方法中,我们最起码可以知道,Spring通过自己的监听器已经加载过一次配置文件了,我们没必要再加载一次,那么很容易想到,如果知道Spring加载后放到哪里了,那我们就可以从那地方获取该配置文件,下面我们看下Spring加载配置文件的过程:
上图中(省略了无关的代码),ContextLoaderListener就是web.xml中我们配置的Spring监听器,它也实现了ServletContextListener并继承了ContextLoader。在监听器中主要通过initWebApplicationContext方法来获取配置文件,并创建WebApplicationContext对象,在initWebApplicationContext方法里主要做两件事:一是拿到Spring的上下文,二是把Spring上下文放到ServletContext中,并且键为:WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE。那么如何拿到Spring的上下文呢?是通过获取web.xml中配置的Spring的路径,CONFIG_LOCATION_PARM其实是个字符串常量,就是上面web.xml中配置Spring监听器下面的:
context-param param-name contextConfigLocation /param-name !--CONFIG_LOCATION_PARM就是contextConfigLocation-- param-value classpath:beans.xml /param-value /context-param
所以就很明显了,通过web.xml中配置的路径拿到beans.xml,然后加载这个配置文件,实例化bean。
现在我们既然知道了Spring在加载配置文件后,把它放在了ServletContext中,那么我们就可以去这里面直接拿!
//@Component //监听器是web层的组件,它是tomcat实例化的,不是Spring实例化的。不能放到Spring中 public class InitDataListener implements ServletContextListener { private ProductService productService = null; @Override public void contextDestroyed(ServletContextEvent event) { // TODO Auto-generated method stub } @Override public void contextInitialized(ServletContextEvent event) { // 获取业务逻辑类查询商品信息 // 解决方案二,项目在启动时,把Spring配置文件通过Spring的监听器加载,存储到ServletContext中,我们只要在ServletContext中获取即可。 ApplicationContext context = (ApplicationContext) event.getServletContext() .getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); productService = (ProductService) context.getBean("productService"); System.out.println(productService); }
这样我们就可以拿到produceService的实例化对象了,这种方法好是好,就是getAttribute中的参数太长,也不知道当时程序员的脑门子被夹了还是咋地,估计是想不到其他更合适的名字了吧~ 4. 通过Spring提供的工具类加载
也许开发Spring的大牛们也意识到了这个参数名字太长了,于是他们提供了一个方法类,可以加载配置文件:
public void contextDestroyed(ServletContextEvent event) { // TODO Auto-generated method stub } @Override public void contextInitialized(ServletContextEvent event) { // 获取业务逻辑类查询商品信息 WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext()); productService = (ProductService) context.getBean("productService"); System.out.println(productService); }
其实,这里的getWebApplicationContext方法就是把上面的那个方法封装了一下而已,我们看看这个方法的源码就知道了:
public static WebApplicationContext getWebApplicationContext(ServletContext sc) { return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); }
这样更加方便程序员调用,仅此而已……所以一般我们使用第三种方法来获取Spring的配置文件,从而获取相应的实例化bean。
_____________________________________________________________________________________________________________________________________________________
-----乐于分享,共同进步!
ActiveMQ系列:结合Spring,基于配置文件的使用ActiveMQ 从activemq脚本可以看出启动ActiveMQ实际是启动,bin文件夹下的其实activemq.jar 包中有一个类为Main,这就是active的启动入口,Main主要是加载lib目录和ClassPath,初始化 类加载器,委托给ShellCommand,由ShellCommand根据命令描述去执行,如果是Version和HELP, 则打印信息,若是启动命令,则通过XBeanBrokerFactory创建BrokerService
这次终于把Spring的监听器讲明白了 监听器可以在使用过程时监听某些事件的发生,然后对这些事件做出响应处理。监听器对应用场景很多,用户的每一个操作都可以被定义为一个事件,通过监听器就能对某些业务场景中的事件进行监听。 Spring中提供了ApplicationListener监听事件,本文会从应用出发讲解Spring的监听器,并逐步深入到源码之中。
Spring Boot 启动事件和监听器,太强大了! 大家都知道,在 Spring 框架中事件和监听无处不在,打通了 Spring 框架的任督二脉,事件和监听也是 Spring 框架必学的核心知识之一。
阿里特邀专家徐雷Java Spring Boot开发实战系列课程(第18讲):制作Java Docker镜像与推送到DockerHub和阿里云Docker仓库 立即下载
相关文章
- 面试题_Spring基础篇
- JavaWeb_(Spring框架)Spring配置文件
- JavaWeb_(Spring框架)xml配置文件
- springmvc + spring + mybatis + maven整合配置文件
- SSM:spring+springmvc+mybatis框架中的XML配置文件功能详细解释(转)
- Spring Boot 配置文件 – 在坑中实践
- [Mockito] Spring Unit Testing with Mockito
- spring boot:分别在jar内部和外部使用配置文件(spring boot v2.5.4)
- spring boot单元测试之三:用mockito在controller/service测试中打桩(spring boot 2.4.3)
- [Java Spring Data] Query by example
- spring dubbo使用 Zookeeper 注册中心
- spring boot配置文件详解
- Spring事务管理---中
- spring schedule定时任务(二):配置文件的方式
- spring boot配置文件【application.yml】常见问题之一,未添加空格
- Spring整合SpringMVC + Mybatis基础框架的配置文件详解
- spring boot 启动读取的配置文件优先级
- spring cloud --- config 配置中心 [本地、git获取配置文件]
- 毕业设计 Spring Boot的汽车租赁系统(含源码+论文)
- Building Microservices with Spring Boot and Apache Thrift. Part 1 with servlet
- 005-Spring Boot配置分析-配置文件application、Environment、PropertySource、@Value、EnvironmentPostProcessor、Profiles
- Spring Boot Tomcat部署