@Inject注解读不到

项目里面要用到定时任务,cron4j满足不了以秒为单位的控制,所以用了quartz,发现个奇怪的问题。

自定义了JFinalJobFactory,用Aop.get()创建quartz的job实例,但发现job实例的@Inject注解在Aop执行doInject时找不到。

public class MyJobFactory implements JobFactory {

    private final Log log = Log.getLog(MyJobFactory.class);

    @Override
    public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException {
        JobDetail jobDetail = bundle.getJobDetail();
        Class jobClass = jobDetail.getJobClass();

        try {
            if (this.log.isDebugEnabled()) {
                this.log.debug("Producing instance of Job '" + jobDetail.getKey() + "', class=" + jobClass.getName());
            }

            return (Job) Aop.get(jobClass);
        } catch (Exception var7) {
            SchedulerException se = new SchedulerException("Problem instantiating class '" + jobDetail.getJobClass().getName() + "'", var7);
            throw se;
        }
    }
}

job类,期望是通过Inject注入service

public class xxxQuartz implements InterruptableJob {

    @Inject
    private xxxService xxxService;
    
    //....
}

debug到这里可以发现,当field是xxxService的时候,inject注解是null的

protected void doInject(Class<?> targetClass, Object targetObject) throws ReflectiveOperationException {
   targetClass = getUsefulClass(targetClass);
   Field[] fields = targetClass.getDeclaredFields();
   if (fields.length != 0) {
      for (Field field : fields) {
         Inject inject = field.getAnnotation(Inject.class);
         if (inject == null) {
            continue ;
         }

Quartz是以在BaseConfig中以Plugin的形式启动的(参考了社区分享里面的QuartzPlugin)

@Override
public boolean start() {
    try {
        SchedulerFactory sf = new StdSchedulerFactory(schedulerConfig);
        Scheduler scheduler = sf.getScheduler();
        loadJob(jobConfig);
        scheduler.start();
    } catch (SchedulerException | ClassNotFoundException e) {
        e.printStackTrace();
        return false;
    }
    return true;
}

在这种情况下,不知道为何job类的Inject注解读不到。

但是,在Test方法下启动quartz,却又可以读到Inject注解,并成功注入

@Test
public void test() throws ClassNotFoundException {
    try {
        String clazz = "xxx";
        String config = "xxx";
        SchedulerFactory sf = new StdSchedulerFactory(config);
        Scheduler scheduler = sf.getScheduler();
        scheduler.scheduleJob(getJobDetail() , getTrigger());
        scheduler.start();
        Thread.sleep(60 * 1000l);
        scheduler.shutdown();
    } catch (SchedulerException | InterruptedException e) {
        e.printStackTrace();
    }
}

请教一下各位大佬,两种quartz启动方式有何区别,为何一种Inject有效,一种Inject无效

评论区

lyh061619

2019-11-18 11:22

非JFinal接管类,用法是Aop.get(xxxService.class)。

newbie

2019-11-18 11:26

@lyh061619 MyJobFactory的jobClass 是Class类型啊,Aop.get(),参数是变量和常量有什么不一样吗

JFinal

2019-11-19 00:55

@newbie 显然是 import Inject 这个注解的时候,错误的引入了别的地方的 Inject,必须要引入下面的类:
import com.jfinal.aop.Inject;

由于很多第三方中也有 Inject 注解,所以容易出错,归根结底还是细心的问题

newbie

2019-11-19 10:46

@JFinal检查了一下,引入的是 import com.jfinal.aop.Inject;

newbie

2019-11-19 10:49

@JFinal 两种启动方式都是通过实现JobFactory ,在里面调用Aop.get()创建job实例的

JFinal

2019-11-19 11:53

@newbie 我估计你是忘了配置注入父类了:
me.setInjectSuperClass(true);

如果你不是 jfinal web 项目,可以这样配置:
AopManager.me().setInjectSuperClass(injectSuperClass);

热门反馈

扫码入社