监听器如何获取Spring配置文件
我们在做项目的时候,会用到监听器去获取spring的配置文件,然后从中拿出我们需要的bean出来,比如做网站首页,假设商品的后台业务逻辑都做好了,我们需要创建一个监听器,在项目启动时将首页的数据查询出来放到application里,即在监听器里调用后台商品业务逻辑的方法,也就是说我们需要在监听器里获取Spring中配置的相应的bean。先把监听器创建出来:
1. 创建InitDataListener
创建一个监听器InitDataListener继承ServletContextListener:
/**
* @Description: TODO(用于项目启动的时候数据初始化)
* @author shanheyongmu
*
*/
//@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 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) {
// 获取业务逻辑类查询商品信息
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。
监听器如何获取Spring配置文件的更多相关文章
- 监听器如何获取Spring配置文件(加载生成Spring容器)
Spring容器是生成Bean的工厂,我们在做项目的时候,会用到监听器去获取spring的配置文件,然后从中拿出我们需要的bean出来,比如做网站首页,假设商品的后台业务逻辑都做好了,我们需要创建一个 ...
- 如何手动获取Spring容器中的bean(ApplicationContextAware 接口)
ApplicationContextAware 接口的作用 先来看下Spring API 中对于 ApplicationContextAware 这个接口的描述: 即是说,当一个类实现了这个接口之 ...
- Java代码获取spring 容器的bean几种方式
一.目的 写了一个项目,多个module,然后想在A模块中实现固定的config注入,当B模块引用A时候,能够直接填写相对应的配置信息就行了.但是遇到一个问题,B引用A时候,A的配置信息总是填充不了, ...
- 获取Spring容器中的Bean协助调试
在使用Spring进行开发时,有时调bug真的是很伤脑筋的一件事,我们可以通过自定义一个监听器来获取Spring容器中的Bean实例来协助我们调试. 第一步:编写自定义监听器 /** * 监听serv ...
- SSH框架系列:Spring读取配置文件以及获取Spring注入的Bean
分类: [java]2013-12-09 16:29 1020人阅读 评论(0) 收藏 举报 1.简介 在SSH框架下,假设我们将配置文件放在项目的src/datasource.properties路 ...
- spring 配置文件 获取变量(PropertyPlaceholderConfigurer)
转自:https://hbiao68.iteye.com/blog/2031006 1.Spring的框架中,org.springframework.beans.factory.config.Prop ...
- Spring Web项目spring配置文件随服务器启动时自动加载
前言:其实配置文件不随服务器启动时加载也是可以的,但是这样操作的话,每次获取相应对象,就会去读取一次配置文件,从而降低程序的效率,而Spring中已经为我们提供了监听器,可监听服务器是否启动,然后在启 ...
- 7 -- Spring的基本用法 -- 4... 使用 Spring 容器:Spring 容器BeanFactory、ApplicationContext;ApplicationContext 的国际化支持;ApplicationContext 的事件机制;让Bean获取Spring容器;Spring容器中的Bean
7.4 使用 Spring 容器 Spring 有两个核心接口:BeanFactory 和 ApplicationContext,其中ApplicationContext 是 BeanFactory ...
- web项目中获取spring的bean对象
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,如何在程序中不通过注解的形式(@Resource.@Autowired)获取Spring配置的bean呢? Bean工厂(c ...
随机推荐
- std::string 字符串大小写转换(转)
该问题归结为std::transform函数的使用 函数原型 template < class InputIterator, class OutputIterator, class UnaryO ...
- centos6.5 的rpm 可以来这边找
http://copr-be.cloud.fedoraproject.org/results/mosquito/myrepo-el6/epel-6-i386/gcc-4.8.2-16.3.fc20/
- normalize.css v2.1.2 翻译
/*! normalize.css v2.1.2 | MIT License | git.io/normalize */ /* /*! 我就是自己看看,然后翻译下下,让大家看看 */ /* ===== ...
- (7)python 函数和lambda表达式
一.函数定义和调用 1.定义函数用def 2.函数注释 在函数体里的开头写上字符串,可以起到说明的作用 可以用函数名.__doc__的方式读取在函数开头加的字符串(双下划线) 内建的help()函数也 ...
- 集训day15 t1 poj3728
[问题描述] 有一颗n个节点的树 每个节点上都有许多奸商在卖东西,第i个奸商的理想价格为vi,即他会以vi的价格购买或卖出一件东西 有m个人希望从树上的某个点走到另一个点,问你在只进行一次买卖(每次仅 ...
- Codeforces Round #283 (Div. 2) D. Tennis Game(模拟)
D. Tennis Game time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...
- 利用Java的反射与代理机制实现AOP
在上一篇文章中,我们讲述了利用Java的反射机制中实现Spring中的IOC,在本文中,我们将更进一步,讲述用Java的反射和动态代理机制来实现Spring的AOP. 一.AOP概述 AOP(Aspe ...
- [P2396] yyy loves Maths VII
Link: P2396 传送门 Solution: 一眼能看出$O(n*2^n)$的状压$dp$ 但此题是个卡常题,$n=23/24$的时候就别想过了 这题算是提供了一种对状压$dp$的优化思路吧 原 ...
- [SRM570]TheTiles
题意:给一个$n\times m$的网格,对这个网格黑白染色,左上角为黑色.现在要用一些大小为$3$的L型图形覆盖这个网格,要求不能重复覆盖同一个格子,不能覆盖到障碍,L型可以进行旋转,但转角处格子必 ...
- 【强联通分量缩点】【搜索】bzoj2208 [Jsoi2010]连通数
两次dfs缩点,然后n次dfs暴搜. #include<cstdio> #include<vector> #include<cstring> using names ...