问题描述:
需求是要求在项目启动自动触发一个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. SpringJunit4 进行单元测试(实例篇--紧接上一章)

    前言: 在做WEB项目时,我们写好了一个Dao和Service后,接下来就是要进行单元测试,测试的时候还要等到Spring容器全部加载完毕后才能进行,然后通过拿到ApplicationContext对 ...

  2. idea搭建Spring Boot+Mybatis及使用教程

    环境准备 idea 15 jDK tomcat maven 搭建方式 官网下载源码包解压缩 使用idea中的Spring initializr创建 这两种方法创建的项目完全相同,只是操作方式不一样 这 ...

  3. Effective C++ .47 traits与模板特化

    #include <iostream> #include <cstdlib> #include <string> using namespace std; temp ...

  4. java 自定义 LRU(最近最少使用)策略 实现 缓存机制

    1. java提供了一个简单的方式实现LRU:  LinkedHashMap   2. 自定义实现 LRU至少需要两个主要操作: 添加(add)和搜索(search) public class LRU ...

  5. JavaScript的进阶之路(六)理解函数

    函数:定义一次,多次调用:用于对象的属性则称为对象的方法:在JavaScript中,函数即对象:嵌套的函数形成闭包: 定义函数和简单调用函数: //函数定义 function f1(){ //没有参数 ...

  6. 四元数(Quaternion)和旋转 +欧拉角

    四元数介绍 旋转,应该是三种坐标变换--缩放.旋转和平移,中最复杂的一种了.大家应该都听过,有一种旋转的表示方法叫四元数.按照我们的习惯,我们更加熟悉的是另外两种旋转的表示方法--矩阵旋转和欧拉旋转. ...

  7. Benefits of encapsulation

    ①:通过方法来控制成员变量的操作,提高了代码的安全性. ②:把代码用方法进行封装,提高了代码的复用性.

  8. 微信小程序-02-项目文件之间配合和调用关系

    微信小程序-02-项目文件之间配合和调用关系 我就不说那么多了,我是从官方文档拷贝的,然后加上一些自己的笔记,不喜勿喷 官方文档:https://developers.weixin.qq.com/mi ...

  9. MVC框架以及实例(补充)

    此文是MVC框架以及实例(http://www.cnblogs.com/justmaomao/p/6739065.html)的补充部分 以下简单介绍简单登录的相关内容 1)在login.jsp中待提交 ...

  10. Linux常用命令(随时补充)

    1.系统 1.1.系统关闭.重启 1)关闭:shutdown -h now 2)重启:reboot.init 6 1.2.修改默认网卡 1)vi /etc/udev/rules.d/70-persis ...