1. 程式人生 > >獲取SpringMVC上下文bean例項-SpringContextUtil

獲取SpringMVC上下文bean例項-SpringContextUtil

專案中,用到了SpringMVC框架。在一個監聽中,需要呼叫server層,並且通過注入的方式,例項化server層。

網上找了很多,提到利用ApplicationContextAware來獲取SpringMVC上下文生成的server層。

例如下:

package com.xsp.onlineshop.web.comm;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * SpringContextUtil
 *
 * @author 
 */
@Component
public class SpringContextUtil implements ApplicationContextAware {

	private static ApplicationContext applicationContext; // Spring應用上下文環境

	/*
	 *
	 * 實現了ApplicationContextAware 介面,必須實現該方法;
	 *
	 * 通過傳遞applicationContext引數初始化成員變數applicationContext
	 */

	public void setApplicationContext(ApplicationContext applicationContext)
	        throws BeansException {
		SpringContextUtil.applicationContext = applicationContext;
	}

	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}

	@SuppressWarnings("unchecked")
	public static <T> T getBean(String name) throws BeansException {
		return (T) applicationContext.getBean(name);
	}

}

但是,在執行的時候,遇到了各種各樣的問題。

現記錄如下:

1,呼叫時,取得的ApplicationContext 為null

ApplicationContext beanFactory= SpringContextUtil.getApplicationContext();
CheckPayTask checkPayTask = beanFactory.getBean(CheckPayTask.class);

執行時,beanFactory為null。原因是SpringContextUtil自身沒有被註冊。

明明<context:component-scan>的路徑裡面包含了SpringContextUtil,怎麼還是取得為null。

在解決這個問題之前,先要弄清楚,Spring上下文和SpringMVC上下文。

先看配置,Spring上下文配置,在Web.xml裡

    <context-param>  
        <param-name>contextConfigLocation</param-name>  
        <param-value>classpath:resources/spring.xml</param-value>  
    </context-param>
    <!-- Spring監聽器 -->  
    <listener>  
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
    </listener>

spring.xml裡面配置的bean屬於Spring上下文。

SpringMVC上下文配置,在Web.xml裡

<!-- Spring MVC servlet -->  
    <servlet>  
        <servlet-name>SpringMVC</servlet-name>  
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
        <init-param>  
            <param-name>contextConfigLocation</param-name>  
            <param-value>classpath:resources/spring-mvc.xml</param-value>  
        </init-param>  
        <load-on-startup>1</load-on-startup>  
        <async-supported>true</async-supported>  
    </servlet>  

spring-mvc.xml裡面配置的bean屬於SpringMVC上下文。

注意:SpringMVC上下文和Spring上下文是分開獨立,兩者是父子關係。Spring 父<->SpringMVC 子。但是SpringMVC上下文是可以取得Spring上下文。反之則不行。

在tomcat服務啟動日誌中可以看到,root WebApplicationContext就是Spring的。

再回頭來看,我們的SpringContextUtil,它應該放在Spring裡面來設定,才有效。放在SpringMVC裡面是沒法完成自動例項化的。

問題1,就是由於我把SpringContextUtil的配置放在了spring-mvc.xml了。

問題2,beanFactory不為null,checkPayTask為null。

其實同問題1一樣,既然SpringContextUtil是Spring裡面例項化的bean,從中取得的bean,自然也都是Spring的bean。所以checkPayTask這個bean的設定要放在spring.xml裡面才對。

PS:其實最開始說的“利用ApplicationContextAware來獲取SpringMVC上下文生成的server層”是不對的,應該是利用ApplicationContextAware來獲取Spring上下文生成的server層。