How to use @Autowired in a Quartz Job?

前端 未结 5 2009
余生分开走
余生分开走 2020-12-25 11:52

i am using quartz with spring and i want to inject/use another class in the job class and i don\'t know how to do it correctly

the xml:



        
相关标签:
5条回答
  • 2020-12-25 12:32

    this is my solution:

        public class MySpringBeanJobFactory extends
            org.springframework.scheduling.quartz.SpringBeanJobFactory implements
            ApplicationContextAware {
          private ApplicationContext ctx;
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext)
                throws BeansException {
            this.ctx = applicationContext;
        }
    
    
        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle)
                throws Exception {
    
            Object jobInstance = super.createJobInstance(bundle);
            ctx.getAutowireCapableBeanFactory().autowireBean(jobInstance);
            return jobInstance;
        }
    }
    

    then config the class of MySpringBeanJobFactory in the xml:

    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <property name="jobFactory">
                <bean class="com.xxxx.MySpringBeanJobFactory" />
        </property>
            <property name="configLocation" value="classpath:quartz.properties" />
            <property name="triggers">
                <list>
                    <ref bean="cronTrigger"/>
                </list>
            </property>
        </bean>
    

    Good luck ! :)

    0 讨论(0)
  • 2020-12-25 12:33

    In your solution you are using the spring @Autowired annotation in a class that is not instantiated by Spring. Your solution will still work if you remove the @Autowired annotation because Quartz is setting the property, not Spring.

    Quartz will try to set every key within the JobDataMap as a property. E.g. since you have a key "myDao" Quartz will look for a method called "setMyDao" and pass the key's value into that method.

    If you want Spring to inject spring beans into your jobs, create a SpringBeanJobFactory and set this into your SchedulerFactoryBean with the jobFactory property within your spring context.

    SpringBeanJobFactory javadoc:

    Applies scheduler context, job data map and trigger data map entries as bean property values

    0 讨论(0)
  • 2020-12-25 12:40

    As mentioned in inject bean reference into a Quartz job in Spring? you can use spring SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

    @Named
    public class SampleJob implements Job {
    
        @Inject
        private AService aService;
    
       @Override
        public void execute(JobExecutionContext context)
            throws JobExecutionException {
    
           //Do injection with spring
            SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
            aService.doIt();
           }
    }
    

    As mentioned it may not wotk on some spring version but I have tested it on 4.2.1.RELEASE which worked fine.

    0 讨论(0)
  • 2020-12-25 12:46
    ApplicationContext springContext = 
        WebApplicationContextUtils.getWebApplicationContext(
            ContextLoaderListener.getCurrentWebApplicationContext().getServletContext()
        );
    Bean bean = (Bean) springContext.getBean("beanName");
    bean.method();
    
    0 讨论(0)
  • 2020-12-25 12:52

    Not sure if this is what you want, but you can pass some configuration values to the Quartz job. I believe in your case you could take advantage of the jobDataAsMap property you already set up, e.g.:

     <property name="jobDataAsMap">
        <map>
          <entry key="schedulerTask" value-ref="schedulerTask" />
          <entry key="param1" value="com.custom.package.ClassName"/>
         </map>
      </property>
    

    Then you should be able to access it in your actual Java code in manual way:

    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        schedulerTask.printSchedulerMessage();
        System.out.println(context.getJobDetail().getJobDataMap().getString("param1"));
    }
    

    Or using the magic Spring approach - have the param1 property defined with getter/setter. You could try defining it with java.lang.Class type then and have the done automatically (Spring would do it for you):

     private Class<?> param1;
    
     // getter & setter
    
     protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        schedulerTask.printSchedulerMessage();
        System.out.println("Class injected" + getParam1().getName());
     }     
    

    I haven't tested it though.

    0 讨论(0)
提交回复
热议问题