diff --git a/xxl-job-core/src/main/java/com/xxl/job/core/executor/impl/XxlJobSpringExecutor.java b/xxl-job-core/src/main/java/com/xxl/job/core/executor/impl/XxlJobSpringExecutor.java index d0a14824db28e024e7ae71b54ba656b97539e67d..6f128a6a94523b5bd7c6c23075ae52e6de699584 100644 --- a/xxl-job-core/src/main/java/com/xxl/job/core/executor/impl/XxlJobSpringExecutor.java +++ b/xxl-job-core/src/main/java/com/xxl/job/core/executor/impl/XxlJobSpringExecutor.java @@ -4,12 +4,15 @@ import com.xxl.job.core.executor.XxlJobExecutor; import com.xxl.job.core.glue.GlueFactory; import com.xxl.job.core.handler.IJobHandler; import com.xxl.job.core.handler.annotation.JobHandler; +import com.xxl.job.core.handler.impl.MethodJobHandler; import org.springframework.beans.BeansException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import org.springframework.core.annotation.AnnotationUtils; +import java.lang.reflect.Method; import java.util.Map; /** @@ -26,7 +29,7 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC // init JobHandler Repository initJobHandlerRepository(applicationContext); - + initJobHandlerMethodRepository(applicationContext); // refresh GlueFactory GlueFactory.refreshInstance(1); @@ -42,7 +45,7 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC } - private void initJobHandlerRepository(ApplicationContext applicationContext){ + private void initJobHandlerRepository(ApplicationContext applicationContext) { if (applicationContext == null) { return; } @@ -50,13 +53,13 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC // init job handler action Map serviceBeanMap = applicationContext.getBeansWithAnnotation(JobHandler.class); - if (serviceBeanMap!=null && serviceBeanMap.size()>0) { + if (serviceBeanMap != null && serviceBeanMap.size() > 0) { for (Object serviceBean : serviceBeanMap.values()) { - if (serviceBean instanceof IJobHandler){ + if (serviceBean instanceof IJobHandler) { String name = serviceBean.getClass().getAnnotation(JobHandler.class).value(); IJobHandler handler = (IJobHandler) serviceBean; if (loadJobHandler(name) != null) { - throw new RuntimeException("xxl-job jobhandler["+ name +"] naming conflicts."); + throw new RuntimeException("xxl-job jobhandler[" + name + "] naming conflicts."); } registJobHandler(name, handler); } @@ -64,12 +67,38 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC } } + private void initJobHandlerMethodRepository(ApplicationContext applicationContext) { + if (applicationContext == null) { + return; + } + String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); + for (String beanDefinitionName : beanDefinitionNames) { + Object bean = applicationContext.getBean(beanDefinitionName); + Method[] methods = bean.getClass().getDeclaredMethods(); + for (int i = 0; i < methods.length; i++) { + JobHandler jobHandler = AnnotationUtils.findAnnotation(methods[i], JobHandler.class); + if (jobHandler != null) { + String name = jobHandler.value(); + if (name.isEmpty()) { + name = methods[i].getName(); + } + if (loadJobHandler(name) != null) { + throw new RuntimeException("xxl-job jobhandler[" + name + "] naming conflicts."); + } + registJobHandler(name, new MethodJobHandler(bean, methods[i], jobHandler)); + } + } + } + } + // ---------------------- applicationContext ---------------------- private static ApplicationContext applicationContext; + @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } + public static ApplicationContext getApplicationContext() { return applicationContext; } diff --git a/xxl-job-core/src/main/java/com/xxl/job/core/handler/annotation/JobHandler.java b/xxl-job-core/src/main/java/com/xxl/job/core/handler/annotation/JobHandler.java index 253026a49decf2111080fb5673bfde41c88f706a..d6ba1e3e3e7f63771421dd1bcaba7054d7632083 100644 --- a/xxl-job-core/src/main/java/com/xxl/job/core/handler/annotation/JobHandler.java +++ b/xxl-job-core/src/main/java/com/xxl/job/core/handler/annotation/JobHandler.java @@ -9,12 +9,22 @@ import java.lang.annotation.Target; /** * annotation for job handler * @author 2016-5-17 21:06:49 + * @author liuzh 2019-12-07 */ -@Target({ElementType.TYPE}) +@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface JobHandler { String value() default ""; - + + /** + * init handler, invoked when JobThread init + */ + String init() default ""; + + /** + * destroy handler, invoked when JobThread destroy + */ + String destroy() default ""; } diff --git a/xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/MethodJobHandler.java b/xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/MethodJobHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..b9753a79fb48b577b9bc62254620aee0d3f1a7ad --- /dev/null +++ b/xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/MethodJobHandler.java @@ -0,0 +1,97 @@ +package com.xxl.job.core.handler.impl; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.handler.annotation.JobHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * @author liuzh 2019-12-07 + */ +public class MethodJobHandler extends IJobHandler { + private static Logger logger = LoggerFactory.getLogger(MethodJobHandler.class); + + private final Object target; + private final Method method; + private final JobHandler jobHandler; + private Method initMethod; + private Method destroyMethod; + + public MethodJobHandler(Object target, Method method, JobHandler jobHandler) { + this.target = target; + this.method = method; + this.jobHandler = jobHandler; + this.method.setAccessible(true); + this.prepareMethod(); + } + + protected void prepareMethod() { + String init = jobHandler.init(); + if(!init.isEmpty()) { + try { + initMethod = target.getClass().getDeclaredMethod(init); + initMethod.setAccessible(true); + } catch (NoSuchMethodException e) { + logger.warn(e.getMessage(), e); + } + } + String destroy = jobHandler.destroy(); + if(!destroy.isEmpty()) { + try { + destroyMethod = target.getClass().getDeclaredMethod(destroy); + destroyMethod.setAccessible(true); + } catch (NoSuchMethodException e) { + logger.warn(e.getMessage(), e); + } + } + } + + @Override + public ReturnT execute(String param) throws Exception { + return (ReturnT) method.invoke(target, new Object[]{param}); + } + + @Override + public void init() { + super.init(); + if(initMethod != null) { + try { + initMethod.invoke(target); + } catch (IllegalAccessException e) { + logger.warn(e.getMessage(), e); + } catch (InvocationTargetException e) { + logger.warn(e.getMessage(), e); + } + } + } + + @Override + public void destroy() { + super.destroy(); + if(destroyMethod != null) { + try { + destroyMethod.invoke(target); + } catch (IllegalAccessException e) { + logger.warn(e.getMessage(), e); + } catch (InvocationTargetException e) { + logger.warn(e.getMessage(), e); + } + } + } + + public Object getTarget() { + return target; + } + + public Method getMethod() { + return method; + } + + public JobHandler getJobHandler() { + return jobHandler; + } +}