問題背景:在我們的web程序中,用spring來管理各個實例(bean), 有時在程序中為了使用已被實例化的bean, 通常會用到這樣的代碼:
- ApplicationContext appContext =
- new ClassPathXmlApplicationContext("classpath:META-INF/spring/applicationContext-common.xml");
- ApplicationContext appContext=appContextUtil.getContext();
- ProjectServiceFacade projectServiceFacade=(ProjectServiceFacade)appContext.getBean("biz.projectServiceFacade");
上述的代碼會帶來一個問題:因為它會重新裝載applicationContext-common.xml並實例化上下文bean, 如果有些線程配置類也是在這個配置文件中,那么會造成做相同工作的的線程會被啟兩次。一次是web容器初始化時啟動,另一次是上述代碼顯示的實例化了一次。這在業務上是要避免的。
解決方法:不用類似new ClassPathXmlApplicationContext()的方式,從已有的spring上下文取得已實例化的bean。
具體步驟:1)增加一個ApplicationContextUtil類,用來取得上下文ApplicationContext
- public class ApplicationContextUtil implements ApplicationContextAware {
- private ApplicationContext context;//聲明一個靜態變量保存
- @Override
- public void setApplicationContext(ApplicationContext applicationContext)
- throws BeansException {
- this.context=applicationContext;
- }
- public ApplicationContext getContext(){
- return context;
- }
- }
2) 對ApplicationContextUtil類增加 Spring配置,讓Spring完成此工具類的裝載並且完成applicationcontext上下文的注入;applicationContext-common.xml配置如下:
- //初始化appliationUtil類,並完成ApplicationContext的注入
- <bean id="applicationContextUtil" class="com.service.utils.ApplicationContextUtil"></bean>
- //對業務類注入ApplicationContextUtil實例
- <bean id="workSignCheckJob" class="com.service.tools.quartz.WorkSignCheckJob" >
- <property name="appContextUtil" ref="applicationContextUtil" />
- </bean>
3)業務類調用代碼如下:
- ApplicationContext appContext=appContextUtil.getContext();
- ProjectServiceFacade projectServiceFacade=(ProjectServiceFacade)appContext.getBean("biz.projectServiceFacade");
- WorkSignService workSignService=(WorkSignService)appContext.getBean("biz.workSignService");