Browse Source

Merge branch 'master' of https://github.com/xuxueli/xxl-job

xuxueli 5 years ago
parent
commit
49f7e16954

+ 34 - 5
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<String, Object> 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;
     }

+ 12 - 2
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 "";
 }

+ 97 - 0
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<String> execute(String param) throws Exception {
+        return (ReturnT<String>) 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;
+    }
+}