Spring AOP与Quartz任务

huangapple go评论93阅读模式
英文:

Spring AOP with Quartz jobs

问题

I am trying to use Spring AOP with Quartz job spring beans. The jobs are autowired into spring container using the following approach:
a. Create AutowiringSpringBeanJobFactory extending SpringBeanJobFactory implementing ApplicationContextAware
b. override createJobInstance and use the AutowiringCapableBeanFactory to autowire the job beans.

Spring boot Application Configuration:

@Configuration
public class MyApplicationConfig {
@Bean
@Primary
public SchedulerFactoryBean schedulerFactoryBean() throws Exception {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(ApplicationContextProvider.getContext());

SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
factoryBean.setDataSource(datasource());
factoryBean.setConfigLocation(new ClassPathResource("quartz.properties"));
factoryBean.setFactory(jobFactory);

}
}

Autowiring of Jobs done as:

public class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {

private AutowireCapableBeanFactory beanFactory;

@Override
public void setApplicationContext() {
  beanFactory = context.getAutowireCapableBeanFactory();
}

@Override
protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
  final Object job = super.createJobInstance(bundle);
  beanFactory.autowireBean(job);
  return job;

}

}

Using this setup, I have created an Aspect:

@Aspect
@Configuration
public class MyAspect {
@Around("execution(public void com.myapp.jobs.*.execute(..))")
public Object process(ProceedingJoinPoint pjp) throws Throwable {
// do something with pjp
}
}

This is my sample job:

@Service
public class Myjob implements Job {
@Autowired
IAuditService auditService;

public void execute(JobExecutionContext jctx) throws JobExecutionException {
//do something
}
}

However, when the above job executes, spring aop does not invoke MyAspect.process().
I am already autowiring my job beans and I am able to autowire other beans into my jobs but only the aspect does not get invoked. What's missing here?

英文:

I am trying to use Spring AOP with Quartz job spring beans. The jobs are autowired into spring container using the following approach:
a. Create AutowiringSpringBeanJobFactory extending SpriongBeanJobFactory implementing ApplicationContextAware
b. override createJobInstance and use the AutowiringCapableBeanFactory to autowire the job beans.

See solution

Spring boot Application Configuration:

@Configuration
public class MyApplicationConfig {
  @Bean
  @Primary
  public SchedulerFactoryBean schedulerFactoryBean() throws Exception {
    AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
    jobFactory.setApplicationContext(ApplicationContextProvider.getContext());

    SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
    factoryBean.setDataSource(datasource());
    factoryBean.setConfigLocation(new ClassPathResource("quartz.properties"));
    factoryBean.setFactory(jobFactory);
  }
}

Autowiring of Jobs done as:

public class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {

  private AutowireCapableBeanFactory beanFactory;

    @Override
    public void setApplicationContext() {
      beanFactory = context.getAutowireCapableBeanFactory();
    }
    
    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
      final Object job = super.createJobInstance(bundle);
      beanFactory.autowireBean(job);
      return job;

    }
}

Using this setup, I have created an Aspect:

@Aspect
@Configuration
public class MyAspect {
    @Around("execution(public void com.myapp.jobs.*.execute(..))")
    public Object process(ProceedingJoinPoint pjp) throws Throwable {
       // do something with pjp
    }
}

This is my sample job:

@Service
public class Myjob implements Job {
  @Autowired
  IAuditService auditService;

  public void execute(JobExecutionContext jctx) throws JobExecutionException {
    //do something
  }
}

However, when the above job executes, spring aop does not invoke MyAspect.process().

I am already autowring my job beans and I am able to autowire other beans into my jobs but only the aspect does not get invoked. Whats missing here?

答案1

得分: 0

Sure, here's the translated content:

首先,你可以使用 @Component 替代 @Configuration 作为你的切面的注解,这样它会像这样:

@Aspect
@Component
public class MyAspect {
    @Around("execution(public void com.myapp.jobs.*.execute(..))")
    public Object process(ProceedingJoinPoint pjp) throws Throwable {
       // 对 pjp 做一些操作
    }
}

其次,确保切点表达式是正确的,你是否引用了正确的包/类/方法。

最后,如果你没有使用 Spring Boot,你应该将 @EnableAspectJAutoProxy 添加到你的配置类中,否则在 Spring Boot 中不需要,因为它是自动配置的!

英文:

First of all you can use @Component instead of @Configuration as annotation of your aspect, thus it will look like this:

@Aspect
@Component
public class MyAspect {
    @Around("execution(public void com.myapp.jobs.*.execute(..))")
    public Object process(ProceedingJoinPoint pjp) throws Throwable {
       // do something with pjp
    }
}

Secondly make sure that the pointcut expression is correct, whether you are referring to the right package/classe/method.

Lastly, if you are not using spring boot you should add @EnableAspectJAutoProxy to your configuration class otherwise no need for that with spring boot as it's auto configured !

答案2

得分: 0

为了在我的作业中启用AOP,我不得不增强“AutowiringSpringBeanJobFactory”,以手动为作业编织方面的内容,如下所示:

public class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
    
  private AutowireCapableBeanFactory beanFactory;
    
  private Object jobAspect;
    
  public void setJobAspect(Object aspect) {
    this.jobAspect = aspect;
  }
    
  @Override
  public void setApplicationContext() {
    beanFactory = context.getAutowireCapableBeanFactory();
  }
        
  @Override
  protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
    final Object job = super.createJobInstance(bundle);
    beanFactory.autowireBean(job);

    AspectJProxyFactory pFactory = new AspectJProxyFactory(job);
    pFactory.addAspect(this.jobAspect);

    return pFactory.getProxy();
  }
}

然而,如果您的作业在其方法上使用了注解,还有其他问题。不过,这是另一个时间要讨论的事情。

英文:

To enable AOP for my jobs, i had to enhance "AutowiringSpringBeanJobFactory " to manually weave aspects in for the jobs as follows:

public class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {

  private AutowireCapableBeanFactory beanFactory;

    private Object jobAspect;

    public void setJobAspect(Object aspect) {
      this.jobAspect = aspect;
    }

    @Override
    public void setApplicationContext() {
      beanFactory = context.getAutowireCapableBeanFactory();
    }
    
    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
      final Object job = super.createJobInstance(bundle);
      beanFactory.autowireBean(job);

      AspectJProxyFactory pFactory = new AspectJProxyFactory(job);
      pFactory.addAspect(this.jobAspect);

      return pFactory.getProxy();
    }
}

However, there are additional issues with this if your job uses annotations on its method(s). That's for another time though.

huangapple
  • 本文由 发表于 2020年7月28日 04:48:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/63123359.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定