原文地址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 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
}
}
- 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 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);
}
}
- 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
做的越多,也就发现自己不懂的越多,还是要深入理解其原理啊
<link rel="stylesheet" href="http://csdnimg.cn/release/phoenix/production/markdown_views-d4dade9c33.css">
</div>
- 1
- 2
- 3