在Spring容器外呼叫bean
阿新 • • 發佈:2019-01-26
原文地址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
做的越多,也就發現自己不懂的越多,還是要深入理解其原理啊