Code Bye

spring quartz一个问题,job无法得到spring注入的属性bean

 

事情是这样的,动态启动多个任务去发送消息,这个任务我是从数据库里获取,各个任务的启动是同一个JOB,只是每个任务JOB传入的参数不同,但这个JOB,需要一个spring 的dao,得不到spring注入的dao属性,不知道怎么回事

1.spring配置dao

–application*.xml–
<bean id=”sendMsg” class=”com.test.SendMsg”>
     <property name=”msgDao”><ref bean=”msgDao”/></property>
</bean>

….msgDao已经配好数据源 spring
2.启任务
1)public calss TestInit(){
    //get tasklist
    public void initJobTrigger() throws Exception
    {
     List list=getTasklist();
     if(null!=list&&list.size()>0){
          Iterator ite=list.iterator();//这个可以得到dao 
          while(ite.hasNext()){
                 Tmsg msg=(Tmsg)ite.next();
                 JobDetail jobdetail=new JobDetail(“msgJob_”+msg.getId(),Scheduler.DEFAULT_GROUP,SendMsg.class);
                 SimpleTrigger sm=new SimpleTrigger(“trigger_”+msg.getId(),Scheduler.DEFAULT_GROUP,new Date(),null,SimpleTrigger.REPEAT_INDEFINITELY,60L*10000L);
               try{
                scheduler.schedulerJob(jobDetail,sm);
                }catch(Exception ex){

                }
                scheduler.unscheduleJob(“InitTrigger”,Scheduler.DEFAULT_GROUP);//初始化任务只执行一行,执行一次之后移除初始化触发器
                scheduler.start();
          }
     }
}

public class SendMsg implements Job
{
            private MsgDao msgDao;
            //msgDao get,set方法,略
            …
            public void execute(JobExecutionContext je) throws JobExecutionException{

                ……略
                  List   list=msgDao.getNeedMsg()  ;//问题出在这里没法获得 msgDao

               …..do sth.          
            }
}

现在主要出现两个问题:

1.实现的job没法得到spring已经注入的dao,出现空指针,先前第一次初始化任务可以得到dao,但是动态生成任务,实现job,无法得到spring注入的属性dao,这是什么原因,请各位XDJM看有什么办法,困扰好久了…万分感谢…
2..多任务创建存在job和group id已经存在的错误,因为这些id是从数据库获取

没人回答,XDJM们,用的技术就是spring2.5.5+quartz-1.6.5

10分
你读取spring配置文件啦吗?ApplicationContext……

10分
<property name=”schedulerContextAsMap”>
<map>
<!– spring 管理的service需要放到这里,才能够注入成功 –>
<description>schedulerContextAsMap</description>
<entry key=”xxService或xxRepo” value-ref=”xxService或xxRepo” />
</map>
</property>

40分
 <!--  定时执行任务的类,要继承TimerTask  --> 
   
  <!--  <bean  id ="SmsSendTask"  class ="com.aisino.platform.sms.core.SmsSendTask" /> -->  
     <!--  用Spring管理这个TimerTask,设定触发间隔  --> 
      <!-- 
      <bean  id ="ScheduledUserTimerTask"  class ="org.springframework.scheduling.timer.ScheduledTimerTask" > 
        <property  name ="delay" > 
          <value > 10000 </value > 
        </property > 
        <property  name ="period" > 
          <value > 60000 </value > 
        </property > 
        <property  name ="timerTask" > 
          <ref  local ="SmsSendTask" /> 
        </property > 
      </bean > 
 	-->
    
    
    <!-- 
     <bean  id ="SmsQuickQueueSendTask"  class ="com.aisino.platform.sms.queue.SmsQuickQueueSendTask" />  
       <bean  id ="ScheduledQuickTimerTask"  class ="org.springframework.scheduling.timer.ScheduledTimerTask" > 
        <property  name ="delay" > 
          <value >30000</value> 
        </property > 
       
        <property  name ="period" > 
          <value >60000</value > 
        </property > 
        <property  name ="timerTask" > 
          <ref  local ="SmsQuickQueueSendTask" /> 
        </property > 
      </bean > 
    
      <bean  id ="timerFactory"  class ="org.springframework.scheduling.timer.TimerFactoryBean" > 
       <property  name ="scheduledTimerTasks" > 
        <list > 
     
          <ref  local ="ScheduledQuickTimerTask" /> 
        </list > 
       </property > 
     </bean > 

参考下


20分
<bean id="sendMsgJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
        <property name="jobClass">
            <value>com.youcom.job.SendMsg</value>
        </property>
        <property name="jobDataAsMap">
            <map>
                <entry key="msgDao"><ref bean="msgDao"/></entry>
            </map>
        </property>
    </bean>

将SendMsg改为继承SPIRNG的QuartzJobBean

在TestInit中注入上面定义的JobDetail,加入如下内容:
@Resource
private JobDetail sendMsgJobDetail;


10分
楼主所指的动态生成任务没有得到msgDao,但这个动态生成的任务是如何创建SendMsg 实例的呢?反射吗?反射的话就得不到msgDao了。只有取spring容器中的SendMsg 实例才能取到msgDao,通过反射创建的SendMsg实例,spring并没有将msgDao注入其中。

第2个问题没看懂,不知道是不是由于第1个问题引起的。

第二个问题,错误提示如下:org.quartz.ObjectAlreadyExistsException:Unable to store Job withe name:””smsJob_222″” and group:””DEFAULT””,because one already exists with this identification
是通过反射创建的:

  JobDetail jobDetail=new JobDetail(“msgJob_”+msgGetId(),Scheduler.DEFAULT_GROUP,SendMsgJob.class);//可以看这是一个CLASS类,SendMsgJob.class
  


10分
引用 7 楼  的回复:

第二个问题,错误提示如下:org.quartz.ObjectAlreadyExistsException:Unable to store Job withe name:””smsJob_222″” and group:””DEFAULT””,because one already exists with this identification

JobDetail jobdetail=new JobDetail(“msgJob_”+msg.getId(),Scheduler.DEFAULT_GROUP,SendMsg.class);

循环的时候,msg.getId有重复的吧?

通过反射创建的SendMsg实例,spring并没有将msgDao注入其中。如果必须要用的dao的话,还是通过ApplicationContext获取吧。
同样的困扰,是否已解决?
引用 11 楼 amber_tear 的回复:

同样的困扰,是否已解决?

问题已解决。
首先:
      job的实现中无法实现dao或者service的spring初始化注入;
其次:
      job的实现每次都会创建一个任务实例,如果在job中去做new ClassPathXmlApplicationContext(“classpath*:xxx”);的话可以解决上面的情况,但是job每次都会创建一个实例,这样在高并发或者长时间使用下,很容易就会内存溢出;

我的处理办法是:
      在spring配置文件中加入ApplicationContextAware 的实现类SpringContextUtil ,让spring在初始化的时候做一次需要使用的service或dao的bean初始化,这样在job中就可以通过这个util去拿到已经初始化的实例,而不用每次都创建一次context。
util的实现只需要加入:
@Override
       @SuppressWarnings(“static-access” )
       public void setApplicationContext(ApplicationContext contex)
                   throws BeansException {
             this.context = contex;
      }

       public static Object getBean(String beanName){
        return context .getBean(beanName);
    }
      
       public static String getMessage(String key){
        return context .getMessage(key, null, Locale. getDefault());
    }

然后在spring配置文件中加入这个util的<bean class …即可

同样的困扰,是否已解决? 

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明spring quartz一个问题,job无法得到spring注入的属性bean