工具類------讓普通類能夠獲取ApplicationContext和Spring容器中的bean和配置項

       在編寫Web代碼時,可能需要讓工具類或者是沒有加入到Spring bean工廠的類,能夠訪問到Spring中的ApplicationContext和、bean和配置項,這時,因爲該類沒有加入到Spring容器中,所以不能在這個類中使用@Autowired來注入Spring中的bean,這時就需要一個工具類,來完成這件事。

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletContext;
import java.util.Collections;
import java.util.Map;

@Configuration
public class ApplicationContextExt implements ApplicationContextAware {
    private static ApplicationContext context = null;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextExt.context = applicationContext;
    }

    /**
     * 取得存儲在靜態變量中的ApplicationContext.
     */
    public static ApplicationContext getContext() {
        if (context == null)
            throw new IllegalStateException("can not found application context.");
        return context;
    }

    /**
     * 從靜態變量ApplicationContext中取得Bean, 自動轉型爲所賦值對象的類型
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        if (context == null)
            throw new IllegalStateException("can not find application context.");
        try {
            return (T) context.getBean(name);
        } catch (BeansException e) {

        }
        return (T) null;
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name, ServletContext sc) {
        if (sc == null)
            throw new IllegalStateException("can not find servlet context.");
        try {
            return (T) WebApplicationContextUtils.getWebApplicationContext(sc).getBean(name);
        } catch (BeansException e) {

        }
        return (T) null;
    }


    public static <T> T getBean(Class<T> cls) {
        if (context == null)
            throw new IllegalStateException("can not find application context.");
        try {
            return (T) context.getBean(cls);
        } catch (BeansException e) {

        }
        return (T) null;
    }

    public static <T> T getBean(Class<T> cls, ServletContext sc) {
        if (sc == null)
            throw new IllegalStateException("can not find servlet context.");
        try {
            return (T) WebApplicationContextUtils.getWebApplicationContext(sc).getBean(cls);
        } catch (BeansException e) {

        }
        return (T) null;
    }

    public static <T> Map<String, T> getBeansOfType(Class<T> cls) {
        if (context == null)
            throw new IllegalStateException("can not found application context.");
        try {
            return context.getBeansOfType(cls);
        } catch (BeansException e) {

        }
        return Collections.emptyMap();
    }

    public static <T> Map<String, T> getBeansOfType(Class<T> cls, ServletContext sc) {
        if (sc == null) {
            throw new IllegalStateException("can not find servlet context.");
        }
        try {
            return WebApplicationContextUtils.getWebApplicationContext(sc).getBeansOfType(cls);
        } catch (BeansException e) {
            // TODO: handle exception
        }
        return Collections.emptyMap();
    }

    /**
     * 根據WebApp的虛擬路徑獲取文件的絕對路徑
     *
     * @param path
     * @return
     */
    public static String getAbsolutePathInWeb(String path) {
        return ((WebApplicationContext) context).getServletContext().getRealPath(path);
    }

    public static Resource getResource(String location) {
        return context.getResource(location);
    }

}

        ApplicationContextExt類添加了@Configuration註解,所以ApplicationContextExt會在Spring初始化bean的時候被創建,而且實現了ApplicationContextAware接口,spring會在創建bean時,調用bean的生命週期函數,其中ApplicationContextAware接口的setApplicationContext就是bean的生命週期函數的一個。關於Spring中bean的生命週期,可以查看:Spring中bean的生命週期(最詳細),注意:如果該類沒有標註@Configuration註解,Spring是不會將你加載成一個bean的,也就沒有調用這個bean的生命週期函數這個說法。

         ApplicationContextExt類的核心關鍵是獲取了Spring容器,所以Spring容器裏面有的,都可以獲取到,這裏只寫出了獲取bean和resource的方法,也可以自行添加其他方法。

        因爲該ApplicationContextExt不是bean後置處理器和bean 工廠的後置處理器,所以不能保證其他bean使用之前被創建完成,只有後置處理器在註冊時可以指定先後順序,而普通的bean我在源碼中沒有看到註冊bean有先後順序,普通bean只能保存它依賴的bean先被註冊,而此時我們使用的是工具類,在普通bean中,沒有使用@Autowired來指定依賴這個bean,所以這個工具類被使用的時機,應該是Spring容器完成初始化bean之後,再進行使用,這一點要註冊。

       Spring容器完成初始化bean之後,容器還能幹什麼用?編寫服務器端代碼,用戶發送的請求,都是在Spring容器完成初始化bean之後,才能進行請求,所以,用戶的接口都是可以使用這個工具類的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章