问题描述:
需求是要求在项目启动自动触发一个service中的线程的操作,使用监听器来实现,但是自定义监听器中spring注解service失败,通过WebApplicationContextUtils去spring容器中获取仍然获取不到,通过断点查看spring容器中没有被注入的service对象
 
代码如下:
1、web.xml文件中配置监听器
<listener>
<listener-class>com.cairh.xpe.aips.web.Test.TestLinstener</listener-class>
</listener>

2、写监听器实现ServletContextListener并重写相应的方法

public class TestLinstener implements ServletContextListener{

    @Autowired
MessMediaService messMediaService; @Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("*************执行相关方法************");
//spring容器中获取service对象
MessMediaService service = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()).getBean(MessMediaService.class);
service.test();
} @Override
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generated method stub
} }

3、service类

@Lazy(false)
@Service
public class MessMediaService { @Autowired
private ITaskService taskService; private RedisLock redisLock = new RedisLock(); private Map taskMap = (Map)JSON.parse(RedisClientUtil.get("config.cache./aips/tasksettings.properties")); private Thread thread = new Thread(new Runnable() { @Override
public void run() { }
}); public int test(){
    taskService.test();
     ...
return 1;
} public MessMediaService() {
super();
System.out.println("*******************测试构造方法********************");
} @PostConstruct
private void init() throws Exception {
System.out.println("*******************init******************");
thread.start();
} }

 解决历程:

后来尝试在构造方法中触发事件也失败,因为断点并没有进入到构造方法中;
再后来尝试使用@PostConstruct注解让service在实例化过程中自动执行方法来实现,@PostConstruct执行顺序大致如下:
服务器加载servlet-->servlet构造函数-->@PostConstruct方法-->init-->service方法-->destroy方法-->@PreDestory方法-->服务器卸载servlet完毕
 
通过此方法正常来说也可实现项目启动自动触发一定的操作,但是启动时并没有按照预想进入到注解的方法中执行任何操作
注:@PostConstruct详细解释见:@PostConstruct与@PreDestroy讲解及实例
 
分析:
构造方法没有执行并且spring容器中没有messMediaService实例,说明要么没有实例化要么是实例化失败
首先验证是否实例化失败,在普通的controller中注入此service,在调用controller时成功,说明service本身没有错误,不会导致实例化失败,剩下的可能就是在项目启动加载的时候没有实例化service
 
在查看spring配置文件的时候发现了beans属性default-lazy-init="true",发现问题所在,此属性表示延时加载,为了提高平时开发中项目启动时间设置的,就是在IoC容器启动时不会实例化bean,只有当容器需要用到时才实例化它,故在监听器中并没有实例化service
 
解决:
如果是手动配置则可在bean属性中添加lazy-init="false"属性来对需要提前加载的bean在spring容器启动时实例化,或者使用注解标签@Lazy(false)
 
再次尝试:
1、监听器中注入messMediaService依然失败;
2、spring容器中获取messMediaService对象成功,可通过从spring容器中获取messMediaService对象来调用,可满足需求;
3、在messMediaService构造方法中断点发现执行到service构造方法时service中注入的taskService依然为null;
4、在@PostConstruct注解方法中发现messMediaService中注入的taskService也有了实例,此方法可成功解决问题;
 
总结:
项目启动最先加载context-parame标签中配置的spring文件,此文件中配置了spring需要实例化的bean目录,但是spring注入和bean的实例化不是同时的,先实例化再注入,两步操作是紧接着的,但是在实例化调用构造方法完成后才有依赖注入行为。
注:spring实例化详细解释见:spring容器初始化过程 和 Spring BeanFactory实例化Bean的详细过程
 
项目启动执行顺序:调用构造方法实例化-->调用@PostConstruct方法-->执行listener的contextInitialized方法
 
listener中messMediaService没有注入成功而messMediaService中能注入taskService是因为messMediaService实例化时其属性service属于一种依赖关系也会被实例化并注入进来,而listener不会被spring实例化并查找依赖关系,故监听器中不能使用spring注解,只能手动获取spring容器中对象
 
 
 
 
 

监听器中spring注入相关的问题的更多相关文章

  1. 项目中Spring注入报错小结

    之前在做单元测试时采用注解方式进行service对象的注入,但运行测试用例时对象要注入的service对象总是空的,检查下spring配置文件,我要配置的bean类xml文件已经包含到spring要加 ...

  2. xfire发布的Webservice中Spring注入为空的解决方案

    Spring框架使用中注入为空是一个比较头疼的问题,遇到Webservice和Spring框架配合时,这个问题更容易出现并很难发现问题的原因. 在做SSO系统中就遇到这样的问题,在Service的实现 ...

  3. spring注入相关注解

    本次主要整理四个注解 @ComponentScan.@Scope.@Conditional.@Import 1. @ComponentScan(value = "com.xiaoguo&qu ...

  4. java 从spring容器中获取注入的bean对象

      java 从spring容器中获取注入的bean对象 CreateTime--2018年6月1日10点22分 Author:Marydon 1.使用场景 控制层调用业务层时,控制层需要拿到业务层在 ...

  5. JSP中使用Spring注入的Bean时需要注意的地方

    遇到问题 遇到一个问题:在JSP中,使用Spring注入的Bean对象时,未能正确地获取到想要的对象. 郁闷的是,它也没报错. 研究问题 使用DEBUG功能(好久不在JSP里写Java代码了,都忘了J ...

  6. Spring中的注入方式 和使用的注解 详解

    注解:http://www.cnblogs.com/liangxiaofeng/p/6390868.html 注入方式:http://www.cnblogs.com/java-class/p/4727 ...

  7. Spring注入中byType和byName的总结

    1.首先,区分清楚什么是byType,什么是byName. <bean id="userServiceImpl" class="cn.com.bochy.servi ...

  8. 线程中无法实例化spring注入的服务的解决办法

    问题描述 在Java Web应用中采用多线程处理数据,发现Spring注入的服务一直报NullPointerException.使用注解式的声明@Resource和XML配置的bean声明,都报空指针 ...

  9. boot中 Quartz注入spring管理类失败

    在项目中用到了Quartz,想在里面实现业务操作发现sping类注入总是失败.后来网上查询了一下解决办法.下面把我成功解决问题的这个版本发出来,大家一起学习一下. 在quartz 会发现 job中无法 ...

随机推荐

  1. Java 并发:Executor

    异常捕获 以前使用executor的时候,为了记录任务线程的异常退出会使用ThreadFactory来设置线程的UncaughtExceptionHandler,但是按照书上的验证发现,采用execu ...

  2. BZOJ5372: PKUSC2018神仙的游戏

    传送门 Sol 自己还是太 \(naive\) 了,上来就构造多项式和通配符直接匹配,然后遇到 \(border\) 相交的时候就 \(gg\) 了 神仙的游戏蒟蒻还是玩不来 一个小小的性质: 存在长 ...

  3. 普通平衡树Tyvj1728、luogu P3369 (treap)

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除x数(若有多个相同的数,因只删除一个) 查询x数的排名(若有多个相同的数,因输出最小的排名) 查询排名为x的 ...

  4. Bookmarklet编写指南

    作者: 阮一峰 日期: 2011年6月11日 前一段日子,我写了两个Bookmarklet----"短网址生成"和"短网址还原". 它们用起来很方便,除了我本人 ...

  5. JS 写入到文件

    //js写文件 function doSave(value, type, name) { var blob; if (typeof window.Blob == "function" ...

  6. 关于Bootstrap的悬浮窗口(popover)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  7. drupal 通过hook_menu实现添加菜单

    $items['mypayment/onlinepay']=array( 'title' => '在线充值', 'description' => '在线充值', 'page callbac ...

  8. SQL server查找指定表的所有索引

    WITH tmp AS ( SELECT indexname = a.name , tablename = c.name , indexcolumns = d.name , a.indid FROM ...

  9. 基础架构之spring cloud基础架构

    这篇文章是给公司设计的微服务基础架构,包括架构设计.部署流程.部署架构.开发Tip等等.这里分享出来,如果对看官们有点用,我就非常的高兴了. 首页 2. 架构设计 3. 部署流程 4. 部署架构 5. ...

  10. How To Manage StartUp Applications In Ubuntu

    Ever felt the need to control startup applications in Ubuntu? You should, if you feel that your Ubun ...