SpringMVC自动注入空指针

来源:互联网 发布:网络什么客 编辑:程序博客网 时间:2024/06/11 01:04

最近做一个定时任务的需求时出现了springmvc自动注入报空指针的问题,在网上各种查找资料终于解决了。下面分享下这两天的经验。


package com.csot.ecp.web.listener;import javax.inject.Inject;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import com.csot.ecp.web.timer.JudgeEmailSendLogTimer;public class JudgeEmailAutoSendListener implements ServletContextListener {    @Inject  private JudgeEmailSendLogTimer rt;
//一开始是采用new JudgeEmailSendLogTimer()的方式去调用其start的方法     @Override  public void contextInitialized(ServletContextEvent event) {    String status ="Judge Email Send Listener start";    event.getServletContext().log(status);    System.out.println(status);           rt.start();  }  @Override  public void contextDestroyed(ServletContextEvent event) {        String status ="Judge Email Send Listener stop";    event.getServletContext().log(status);    System.out.println(status);        if(rt !=null){      rt.stop();    }  }

package com.csot.ecp.web.timer;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import javax.inject.Inject;import javax.inject.Named;@Namedpublic class JudgeEmailSendLogTimer {      @Inject  private JudgeEmailSendLogTask task;    private final Timer timer =new Timer();        public void start(){    final String time = "08:30:00";    long datespan =24*60*60*1000;    Date startTime;    final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd " + time);    try {            startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(sdf.format(new Date()));      timer.schedule(task, startTime, datespan);
//task这里开始也是用new JudgeEmailSendLogTask ()的方式去执行timer定时任务,结果发现其run()方法里面@Inject注入的变量
为空    } catch (Exception e) {            e.printStackTrace();    }      }    public void stop(){    timer.cancel();  }}

然后又是各种找“度娘”,最后发现是new出来的对象并没有交给spring去管理,那你这个类又去注入其它的变量肯定是会报空指针的。

就比如:

public class A{
  new B().update();
}

public class B{
 @Resource
 private C c;

 public update(){
   c.update();//这里会报空指针
 }

}

你c交给spring管理了,那么b也要交给spring管理才行,这样c才能注入到b中,a中new才可以用,A 、 B 、 C 都要给Spring管理, 并且不能new才可以。 


这时候候debug发现即使改为全部spring注入也会报空指针。

。。。

又是折腾了半天,最后实在不行只能找高手来帮忙了。

“听君一席话胜读十年书啊!” 突然恍然大悟。

因为spring本身也是一个listener,并不鞥保证spring比web.xml的listener更早加载,这就导致了系统在启动后有可能spring的bean还未初始化。

找到原因问题就好解决了^^

一:在不改动源程序的情况下在listener里面手动再加载一遍spring配置文件,但这对系统性能会有一定的影响。

二:采用Quartz或者spring-Task来实现

最后采用了Spring-Task的方式来实现,虽然没有Quartz那么功能强大,但Spring-Task配置简单,而且我原有的代码也不用做太多改动!其实一开始如果不用Timer直接用Quartz或者Spring-Task就没有多问题了!^_^

下面是最终实现代码:


@Component("judgeEmailSendLogTask")public class JudgeEmailSendLogTask {  @Inject  private JudgeAccessFacade judgeAccessFacade;    @Inject  private ArrangeAccessFacade arrangeAccessFacade;    @Inject  private EmployeeAccessFacade employeeAccessFacade;    @Inject  private SysMailAccessFacade sysMailAccessFacade;    @Inject  private JudgeConfigFacade judgeConfigFacade;    @Inject  private SubActivityAccessFacade subActivityAccessFacade;    //系统地址  @Value("${SystemUrl}")  private String systemUrl;    //评委不可排时间设置页面菜单ID  @Value("${JudgeNoArrangeTimeSetId}")  private String judgeNoArrangeTimeSetId;    private static final Logger LOGGER = LoggerFactory.getLogger(JudgeEmailSendLogTask.class);   @Scheduled(cron = "0 30 8 * * ?")  public void run() {    String subject = "ECP认证安排不可排时间设置";        long nh = 1000 * 60 * 60;    try {      List<String> sendEmailjudgeCodeList = judgeAccessFacade.queryAllJudgeEmailSendLog();      //去掉重复元素      HashSet<String> set = new HashSet<String>(sendEmailjudgeCodeList);      sendEmailjudgeCodeList.clear();      sendEmailjudgeCodeList.addAll(set);            SubActivityDTO subActivityDTO = new SubActivityDTO();      List<SubActivityDTO> queryList = subActivityAccessFacade.queryAllSubActivity(subActivityDTO);            JudgeArrangeDTO judgeArrangeDTO = new JudgeArrangeDTO();          List<JudgeArrangeDTO> judgeList = arrangeAccessFacade.queryJudgeArranges(judgeArrangeDTO);      List<String> AlljudgeCodeList = new ArrayList<String>();      for(JudgeArrangeDTO judgeDTO :judgeList ){        AlljudgeCodeList.add(judgeDTO.getJudgeCode());      }      HashSet<String> hset = new HashSet<String>(AlljudgeCodeList);      AlljudgeCodeList.clear();      AlljudgeCodeList.addAll(hset);            if(AlljudgeCodeList.size()>sendEmailjudgeCodeList.size()){        AlljudgeCodeList.removeAll(sendEmailjudgeCodeList);      }      for(String alljudgeCodeList:AlljudgeCodeList){        EmployeeDTO employeeDTO = employeeAccessFacade.getEmployeeById(alljudgeCodeList);        if (employeeDTO == null) {          continue;        }        String email = employeeDTO.getEmail();        if (StringUtils.isEmpty(email)) {          continue;        } else {          for(SubActivityDTO subActivityDTOList : queryList){            Date applystartdate = subActivityDTOList.getApplyStartDate();            Date currentdate =new Date();            String totalActivityId = subActivityDTOList.getTotalActivityId();            long diff = currentdate.getTime() - applystartdate.getTime();            long hour = diff / nh;            if(hour>8.5 && hour<24){              // 发送邮件              //String projectUrl=request.getScheme()+"://"+ request.getServerName()+":"+request.getServerPort()+request.getContextPath();              String mailContent = "Dear " + employeeDTO.getName()                  + ":<br><br>  请点击以下链接设置不可排时间:"                  + "<br><br>"+systemUrl+"/?extRoute="+judgeNoArrangeTimeSetId+"a  ";              boolean result = sysMailAccessFacade.sendMailCommon(subject, mailContent, email, "", "");              if(result == true){                //邮件发送成功将该评委记录到表中                CreateJudgeEmailSendLogCommand command = new CreateJudgeEmailSendLogCommand();                command.setJudgeCode(alljudgeCodeList);                command.setJudgeName(employeeDTO.getName());                command.setTotalActivityId(totalActivityId);                judgeConfigFacade.createJudgeEmailSendLog(command);               }            }          }              }  }    } catch (Exception e) {                 LOGGER.error("定时发送邮件失败", e);    }  }}

有理解错误的地方欢迎指正哈!---


原创粉丝点击