问题描述:
需求是要求在项目启动自动触发一个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. 十四、ReentrantLock重入锁

    一.简介 JDK提供了Lock接口来实现更丰富的锁控制,ReentrantLock即Lock接口的实现 JDK文档:http://tool.oschina.net/uploads/apidocs/jd ...

  2. 撩课-Java每天10道面试题第1天

    1.简述JDK.JRE.JVM? 一.JDK JDK(Java Development Kit) 是整个JAVA的核心, 包括了Java运行环境(Java Runtime Envirnment), 一 ...

  3. [LeetCode]Delete and Earn题解(动态规划)

    Delete and Earn Given an array nums of integers, you can perform operations on the array. In each op ...

  4. CentOS配置multipath

    可以通过2种方式查看HBA的WWN信息: 1. 查看sys文件系统 查看HBA卡型号:[root@localhost ~]# lspci  | grep -i fibre13:00.0 Fibre C ...

  5. 转:Linux中tomcat服务成功发布但局域网浏览器无法访问

    转自:http://blog.csdn.net/mooncom/article/details/53168143 昨天,我在搭建Linux中服务器环境时,碰见一个问题,这里和大家分享一下. 问题描述: ...

  6. ARCGIS 10.0破解版安装过程error 1606 和error 1316问题 及安装流程

    来自:http://blog.csdn.net/don_lvsml/article/details/8681100 楼主今天安装ESRI.ArcGIS.10.CS时,由于第一次接触该软件,将其按照一般 ...

  7. Kali 防火墙配置

    Kali操作系统安装时默认已经安装了"iptables",配置前先检查有没有安装,命令如下:iptables -L显示如下(图1),则表示已经安装了,如果没有安装,使用命令:apt ...

  8. jpa No Dialect mapping for JDBC type:-9

    1.自定义个一个继承SQLServerDialect的dialect类 public class MySQLServer2008Dialect extends SQLServer2008Dialect ...

  9. 使用拦截器拦截html参数

    公司最新需求:根据传递的参数进行业务判断,如果符合条件则继续后面的业务逻辑,否则跳转到指定的错误页面.有些是请求的controller 使用了spring  aop的方式进行验证:但是有些是html页 ...

  10. Linux运维体系