在Spring容器外調用bean

這個東西源於這種需求:一個應用丟到服務其後,無論用戶有沒有訪問項目,這個後臺線程都必須給我跑,並且這個線程還調用了Spring注入的bean,這樣天然就會想到去監聽Servlet的狀態,當Servlet初始化完畢後會調用ServletContextListener中的contextInitialized方法,因此能夠建立一個監聽器繼承ServletContextListener類來監聽Servlet的狀態,在contextInitialized方法中來啓動後臺的線程,可是如何使用Spring注入的bean呢?因此必須確保在啓動線程前Spring容器必須初始化完畢,Spring的初始化也是有Listener完成的,因此這裏特別注意的是自定的監聽器必須放在Spring的監聽器以後(很重要),不然沒法獲取bean屬性,會報空指針異常!java

1.建立監聽器

package com.hhu.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import com.hhu.threads.DiagnosisThread;

/**
 * 這個監聽器在WEB容器初始化後就馬上啓用了
 * @author Weiguo Liu
 * @data 2017年11月30日
 */

public class ContextListener implements ServletContextListener  {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("加載應用程序...");
//      StationService stationService = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()).getBean(StationService.class);
//      System.out.println("stationService=" + stationService);

        /*
         * 建立診斷線程並啓動
         */
        DiagnosisThread dt = new DiagnosisThread();
        dt.start();
        System.out.println("Listener繼續執行");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // TODO Auto-generated method stub

    }

}

 

 

2.web.xml配置啓動順序

  <!-- 這裏不能少,web啓動後會按這個位置尋找Spring的配置文件 -->
     <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:spring/spring-*.xml
        </param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

  <listener>
    <listener-class>
        com.hhu.listener.ContextListener
    </listener-class>
  </listener>

    <servlet>
    <servlet-name>springDispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring/spring-*.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

    <servlet-mapping>
    <servlet-name>springDispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

 

 

3.寫一個獲取Spring Bean的工具類

因爲ServletContextListener並不被Spring管理,因此咱們不能使用@Autowired註解來獲取相應的bean屬性,而是利用ApplicationContext來獲取Bean,代碼以下web

package com.hhu.util;

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

/**
 * 使用getBean能夠獲取對應的bean,本身的的手動進行類型強轉
 * 建立獲取SpringBean的工具類
 * @author Weiguo Liu
 *
 */
public class SpringBeanUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext = null;

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

    public static Object getBeanByName(String beanName) {
        if (applicationContext == null) {
            return null;
        }
        return applicationContext.getBean(beanName);
    }

    public static <T> T getBean(Class<T> type) {
        return applicationContext.getBean(type);
    }
}

 

 

這樣之後就能夠在後臺線程中愉快的獲取Spring bean了,這個工具類很強大,只要Spring初始化後,無論所在類是否被Spring管理,均可以使用以下的方式獲取spring

bean的類型 bean的名字 = (bean的類型)SpringBeanUtil.getBeanByName("bean的名字");

 

作的越多,也就發現本身不懂的越多,仍是要深刻理解其原理啊app

相關文章
相關標籤/搜索