问题描述:
需求是要求在项目启动自动触发一个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. [Telegram X]旧版分享 突破被锁群组

    Telegram X的锁群是由于 App Store 审核时发现Telegram官方并不限制18+.社会舆论等的讨论:在 版本 5.0.2 (版本号825487096)时就已经封禁该类群组 注:可能由 ...

  2. LinkedList实现队列存储结构

    package com.tercher.demo; import java.util.LinkedList; public class Queue { //用LinkedList 实现队列的数据存储结 ...

  3. JSON和JSONP 实例

    来源:http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html 前言: 说到AJAX就会不可避免的面临两个问 ...

  4. [HAOI2009]逆序对数列(加强)

    ZJL 的妹子序列 暴力就是 \(\Theta(n\times m)\) 如果 \(n,m \le 10^5\) ? 考虑问题的转换,设 \(a_i\) 表示 \(i\) 小的在它后面的数的个数 \( ...

  5. [转]web使用Quartz.NET实现作业调度

    转自 https://www.cnblogs.com/best/p/7658573.html 一.Quartz.NET介绍 Quartz.NET是一个强大.开源.轻量的作业调度框架,是 OpenSym ...

  6. 代码积累-Common

    新建Common类库 /// <summary> /// string的扩展 /// </summary> public static class StringExt { // ...

  7. LintCode2016年8月8日算法比赛----中序遍历和后序遍历构造二叉树

    中序遍历和后序遍历构造二叉树 题目描述 根据中序遍历和后序遍历构造二叉树 注意事项 你可以假设树中不存在相同数值的节点 样例 给出树的中序遍历: [1,2,3] 和后序遍历: [1,3,2] 返回如下 ...

  8. The String class's judging function

    字符串的判断功能: package com.itheima_03; /* * Object:是类层次结构中的根类,所有的类都直接或者间接的继承自该类. * 如果一个方法的形式参数是Object,那么这 ...

  9. VUE知识day3_vue-cli脚手架安装和webpack模板项目生成

    ue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目. GitHub地址是:https://github.com/vuejs/vue-cli 一.安 ...

  10. C#字节流通信格式

    类似通信格式的实现关键点: byte数组转float的实现,BitConvetor.toSingle() float类型转by,BitConverter.GetBytes #客户端发送public b ...