本来这是一个比较简单的问题。
然而在前一段事件项目中出现了一个问题。
问题描述:数据库连接数只增不减,直到数据库链接数爆满,报了一个 too many connection异常。整个服务就挂了,需要重写启动一次才能使用。
一开始的时候,一直以为是dao层那个链接没有释放。把dao层的代码都查了一遍,也从网上搜索了很多关于数据库连接池的东西,但是也没有发现问题。于是就纠结了~~
后台通过mysql的一个命令,status,发现在求职者简历编辑模块,每编辑一次简历,数据库连接数就会只增不减,增加三个(这个数与数据库连接池的一个参数有关,用的是dbcp链接池),于是就又把简历编辑模块的内容检查了一遍,终于找到了罪魁祸首。
在简历编辑的时候,为了重新生成个人简历的静态页面,使用了freemarker。但是freemarker模块的业务层没有使用@Resource,将它交给spring容器来管理。在里面有一行代码为了获取到某个dao层的bean,使用了
ApplicationContext ac = new ClassPathXmlApplicationContext(File file);
ac.getBean(Class clazz);
这句代码,相信很多人,看到这句代码就已经大致猜到了问题的所在了。
ApplicationContext ac = new ClassPathXmlApplicationContext(File file),这句代码相当于又重新初始化了一遍Spring容器。So......‘
问题算是解决了,那么总结一下经验教训。到底该如何正确的获取到bean呢?
1、一般情况下,我们使用spring容器来管理bean,可以直接使用注入的方式来获取到bean
例如:使用@Resource,@Autowire.
2、如果没有将某个bean交给spring容器来管理,我们又该在web项目中如果获取到这个bean呢?
方式一:也是错误的方式,就是使用
ApplicationContext ac = new ClassPathXmlApplicationContext(File file);
ac.getBean(Class clazz);
这种方式的弊端就如上所述,一般用于单元测试,不能在web项目中直接使用。
方式二:使用
ApplicationContext ac1 = WebApplicationContextUtils.
getRequiredWebApplicationContext(ServletContext sc)
ApplicationContext ac2 = WebApplicationContextUtils.
getWebApplicationContext(ServletContext sc)
ac1.getBean(beanId);
ac2.getBean(beanId);说明:
这种方式适合于采用Spring框架的B/S系统,通过ServletContext对象获取ApplicationContext对象,然后在通过它获取需要的类实例。
说明:上面两个工具方式的区别是,前者在获取失败时抛出异常,后者返回null。
这几种方式可能使我们比较常用到的。至于其他的方式,请参考
http://blog.sina.com.cn/s/blog_9c7ba64d0101evar.html 星星索深邃的博客。