最近在工作使用boot+quartz整合,开发定时调度平台,遇到需要对Quartz的Job进行异常后将异常记录到日志表的操作,第一反应就想到了使用Spring的AOP,利用AfterThrowing来完成这个操作。
话不多说,直接上代码:
1 <!--整合Quartz--> 2 <dependency> 3 <groupId>org.springframework.boot</groupId> 4 <artifactId>spring-boot-starter-quartz</artifactId> 5 </dependency>
1.正常的一个job类:
2. 创建JobBeanFactory类,重写 SpringBeanJobFactory 的方法。
1 import org.quartz.SchedulerContext; 2 import org.quartz.spi.TriggerFiredBundle; 3 import org.springframework.beans.BeanWrapper; 4 import org.springframework.beans.MutablePropertyValues; 5 import org.springframework.beans.PropertyAccessorFactory; 6 import org.springframework.beans.factory.BeanFactory; 7 import org.springframework.lang.Nullable; 8 import org.springframework.scheduling.quartz.SpringBeanJobFactory; 9 10 /** 11 * @Author: Hujh 12 * @Date: 2019/7/5 9:38 13 * @Description: 配置job工厂 14 */ 15 public class JobBeanFactory extends SpringBeanJobFactory{ 16 17 @Nullable 18 private String[] ignoredUnknownProperties; 19 20 @Nullable 21 private SchedulerContext schedulerContext; 22 23 24 private final BeanFactory beanFactory; 25 26 27 JobBeanFactory(BeanFactory beanFactory){ 28 this.beanFactory = beanFactory; 29 } 30 31 32 public void setIgnoredUnknownProperties(String... ignoredUnknownProperties) { 33 this.ignoredUnknownProperties = ignoredUnknownProperties; 34 } 35 36 @Override 37 public void setSchedulerContext(SchedulerContext schedulerContext) { 38 this.schedulerContext = schedulerContext; 39 } 40 41 42 /** 43 * @Title: createJobInstance 44 * @Author : Hujh 45 * @Date: 2019/7/5 10:19 46 * @Description : 创建调度工作接口 47 * @param : bundle 48 * @Return : java.lang.Object 49 */ 50 @Override 51 protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { 52 Class<?> jobClass = bundle.getJobDetail().getJobClass(); 53 Object job = beanFactory.getBean(jobClass); 54 if (isEligibleForPropertyPopulation(job)) { 55 BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(job); 56 MutablePropertyValues pvs = new MutablePropertyValues(); 57 if (this.schedulerContext != null) { 58 pvs.addPropertyValues(this.schedulerContext); 59 } 60 pvs.addPropertyValues(bundle.getJobDetail().getJobDataMap()); 61 pvs.addPropertyValues(bundle.getTrigger().getJobDataMap()); 62 if (this.ignoredUnknownProperties != null) { 63 for (String propName : this.ignoredUnknownProperties) { 64 if (pvs.contains(propName) && !bw.isWritableProperty(propName)) { 65 pvs.removePropertyValue(propName); 66 } 67 } 68 bw.setPropertyValues(pvs); 69 } 70 else { 71 bw.setPropertyValues(pvs, true); 72 } 73 } 74 return job; 75 } 76 }
3.创建 QuartzConfig类,交给spring容器进行管理
1 import org.springframework.beans.BeansException; 2 import org.springframework.boot.autoconfigure.quartz.SchedulerFactoryBeanCustomizer; 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.ApplicationContextAware; 5 import org.springframework.context.annotation.Bean; 6 import org.springframework.context.annotation.Configuration; 7 8 /** 9 * @Author: Hujh 10 * @Date: 2019/7/5 9:39 11 * @Description: Quartz相关配置类 12 */ 13 @Configuration 14 public class QuartzConfig implements ApplicationContextAware { 15 16 private ApplicationContext applicationContext; 17 18 @Bean 19 public SchedulerFactoryBeanCustomizer schedulerFactoryBeanCustomizer() { 20 // Spring 项目整合 Quartz 主要依靠添加 SchedulerFactoryBean 这个 FactoryBean 21 return schedulerFactoryBean -> schedulerFactoryBean.setJobFactory(new JobBeanFactory(applicationContext)); 22 } 23 24 /** 25 * 初始化加载applicationContext 26 */ 27 @Override 28 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 29 this.applicationContext = applicationContext; 30 } 31 }
4. 创建AOP拦截:JobLogAop
1 <!-- aop依赖 --> 2 <dependency> 3 <groupId>org.springframework.boot</groupId> 4 <artifactId>spring-boot-starter-aop</artifactId> 5 </dependency>
1 2 3 import org.aspectj.lang.annotation.*; 4 import org.slf4j.Logger; 5 import org.slf4j.LoggerFactory; 6 import org.springframework.stereotype.Component; 7 8 /** 9 * @Author: Hujh 10 * @Date: 2019/7/4 17:12 11 * @Description: 工作调度任务拦截 (日志记录) 12 */ 13 @Component 14 @Aspect 15 public class JobLogAop { 16 17 private Logger logger = LoggerFactory.getLogger(JobLogAop.class); 18 19 /** 20 * 只对于execute切入 21 */ 22 @Pointcut("execution(public void com.ylsp.jobs..*.execute(..))") 23 public void pointJobLog(){} 24 25 /** 26 * 切点通知(方法执行后) 27 */ 28 @AfterReturning("pointJobLog()") 29 public void handlerControllerMethod() { 30 logger.info("execute方法执行后..---->> 开始写入日志"); 31 } 32 33 34 }
注:直接创建一个Job,可以看到Aop已经生效。