1. 程式人生 > >在Spring容器外呼叫bean

在Spring容器外呼叫bean

原文地址http://blog.csdn.net/jacksonary/article/details/78680686 這個東西源於這種需求:一個應用丟到服務其後,不管使用者有沒有訪問專案,這個後臺執行緒都必須給我跑,而且這個執行緒還呼叫了Spring注入的bean,這樣自然就會想到去監聽Servlet的狀態,當Servlet初始化完畢後會呼叫ServletContextListener中的contextInitialized方法,所以可以建立一個監聽器繼承ServletContextListener類來監聽Servlet的狀態,在contextInitialized方法中來啟動後臺的執行緒,但是如何使用Spring注入的bean呢?所以必須確保在啟動執行緒前Spring容器必須初始化完畢,Spring的初始化也是有Listener完成的,所以這裡特別注意的是自定的監聽器必須放在Spring的監聽器之後(很重要),否則無法獲取bean屬性,會報空指標異常!

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 classContextListenerimplementsServletContextListener  {
@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 } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

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

由於ServletContextListener並不被Spring管理,所以我們不能使用@Autowired註解來獲取相應的bean屬性,而是利用ApplicationContext來獲取Bean,程式碼如下

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 classSpringBeanUtilimplementsApplicationContextAware {
    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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

這樣以後就可以在後臺執行緒中愉快的獲取Spring bean了,第三個工具類很強大,只要Spring初始化後,不管所在類是否被Spring管理,都可以使用如下的方式獲取

bean的型別 bean的名字 = (bean的型別)SpringBeanUtil.getBeanByName("bean的名字");
  • 1
  • 1

做的越多,也就發現自己不懂的越多,還是要深入理解其原理啊