Kaynağa Gözat

支持在 Bean 方法(必须保证入参和返回值符合 ReturnT<String> 方法名任意(String param) throws Exception)上使用 @JobHandler 注解,在方法上使用注解时如果没有指定 value,就会使用方法名作为 JobHandler 的名字,注解额外增加 init 和 destroy 可以指定当前 bean 中的其他方法作为 JobHandler 中的 init 和 destroy 方法。

abel533 5 yıl önce
ebeveyn
işleme
039346b730

+ 34 - 5
xxl-job-core/src/main/java/com/xxl/job/core/executor/impl/XxlJobSpringExecutor.java Dosyayı Görüntüle

@@ -4,12 +4,15 @@ import com.xxl.job.core.executor.XxlJobExecutor;
4 4
 import com.xxl.job.core.glue.GlueFactory;
5 5
 import com.xxl.job.core.handler.IJobHandler;
6 6
 import com.xxl.job.core.handler.annotation.JobHandler;
7
+import com.xxl.job.core.handler.impl.MethodJobHandler;
7 8
 import org.springframework.beans.BeansException;
8 9
 import org.springframework.beans.factory.DisposableBean;
9 10
 import org.springframework.beans.factory.InitializingBean;
10 11
 import org.springframework.context.ApplicationContext;
11 12
 import org.springframework.context.ApplicationContextAware;
13
+import org.springframework.core.annotation.AnnotationUtils;
12 14
 
15
+import java.lang.reflect.Method;
13 16
 import java.util.Map;
14 17
 
15 18
 /**
@@ -26,7 +29,7 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
26 29
 
27 30
         // init JobHandler Repository
28 31
         initJobHandlerRepository(applicationContext);
29
-
32
+        initJobHandlerMethodRepository(applicationContext);
30 33
         // refresh GlueFactory
31 34
         GlueFactory.refreshInstance(1);
32 35
 
@@ -42,7 +45,7 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
42 45
     }
43 46
 
44 47
 
45
-    private void initJobHandlerRepository(ApplicationContext applicationContext){
48
+    private void initJobHandlerRepository(ApplicationContext applicationContext) {
46 49
         if (applicationContext == null) {
47 50
             return;
48 51
         }
@@ -50,13 +53,13 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
50 53
         // init job handler action
51 54
         Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(JobHandler.class);
52 55
 
53
-        if (serviceBeanMap!=null && serviceBeanMap.size()>0) {
56
+        if (serviceBeanMap != null && serviceBeanMap.size() > 0) {
54 57
             for (Object serviceBean : serviceBeanMap.values()) {
55
-                if (serviceBean instanceof IJobHandler){
58
+                if (serviceBean instanceof IJobHandler) {
56 59
                     String name = serviceBean.getClass().getAnnotation(JobHandler.class).value();
57 60
                     IJobHandler handler = (IJobHandler) serviceBean;
58 61
                     if (loadJobHandler(name) != null) {
59
-                        throw new RuntimeException("xxl-job jobhandler["+ name +"] naming conflicts.");
62
+                        throw new RuntimeException("xxl-job jobhandler[" + name + "] naming conflicts.");
60 63
                     }
61 64
                     registJobHandler(name, handler);
62 65
                 }
@@ -64,12 +67,38 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
64 67
         }
65 68
     }
66 69
 
70
+    private void initJobHandlerMethodRepository(ApplicationContext applicationContext) {
71
+        if (applicationContext == null) {
72
+            return;
73
+        }
74
+        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
75
+        for (String beanDefinitionName : beanDefinitionNames) {
76
+            Object bean = applicationContext.getBean(beanDefinitionName);
77
+            Method[] methods = bean.getClass().getDeclaredMethods();
78
+            for (int i = 0; i < methods.length; i++) {
79
+                JobHandler jobHandler = AnnotationUtils.findAnnotation(methods[i], JobHandler.class);
80
+                if (jobHandler != null) {
81
+                    String name = jobHandler.value();
82
+                    if (name.isEmpty()) {
83
+                        name = methods[i].getName();
84
+                    }
85
+                    if (loadJobHandler(name) != null) {
86
+                        throw new RuntimeException("xxl-job jobhandler[" + name + "] naming conflicts.");
87
+                    }
88
+                    registJobHandler(name, new MethodJobHandler(bean, methods[i], jobHandler));
89
+                }
90
+            }
91
+        }
92
+    }
93
+
67 94
     // ---------------------- applicationContext ----------------------
68 95
     private static ApplicationContext applicationContext;
96
+
69 97
     @Override
70 98
     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
71 99
         this.applicationContext = applicationContext;
72 100
     }
101
+
73 102
     public static ApplicationContext getApplicationContext() {
74 103
         return applicationContext;
75 104
     }

+ 12 - 2
xxl-job-core/src/main/java/com/xxl/job/core/handler/annotation/JobHandler.java Dosyayı Görüntüle

@@ -9,12 +9,22 @@ import java.lang.annotation.Target;
9 9
 /**
10 10
  * annotation for job handler
11 11
  * @author 2016-5-17 21:06:49
12
+ * @author liuzh 2019-12-07
12 13
  */
13
-@Target({ElementType.TYPE})
14
+@Target({ElementType.TYPE, ElementType.METHOD})
14 15
 @Retention(RetentionPolicy.RUNTIME)
15 16
 @Inherited
16 17
 public @interface JobHandler {
17 18
 
18 19
     String value() default "";
19
-    
20
+
21
+    /**
22
+     * init handler, invoked when JobThread init
23
+     */
24
+    String init() default "";
25
+
26
+    /**
27
+     * destroy handler, invoked when JobThread destroy
28
+     */
29
+    String destroy() default "";
20 30
 }

+ 97 - 0
xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/MethodJobHandler.java Dosyayı Görüntüle

@@ -0,0 +1,97 @@
1
+package com.xxl.job.core.handler.impl;
2
+
3
+import com.xxl.job.core.biz.model.ReturnT;
4
+import com.xxl.job.core.handler.IJobHandler;
5
+import com.xxl.job.core.handler.annotation.JobHandler;
6
+import org.slf4j.Logger;
7
+import org.slf4j.LoggerFactory;
8
+
9
+import java.lang.reflect.InvocationTargetException;
10
+import java.lang.reflect.Method;
11
+
12
+/**
13
+ * @author liuzh 2019-12-07
14
+ */
15
+public class MethodJobHandler extends IJobHandler {
16
+    private static Logger logger = LoggerFactory.getLogger(MethodJobHandler.class);
17
+
18
+    private final Object target;
19
+    private final Method method;
20
+    private final JobHandler jobHandler;
21
+    private Method initMethod;
22
+    private Method destroyMethod;
23
+
24
+    public MethodJobHandler(Object target, Method method, JobHandler jobHandler) {
25
+        this.target = target;
26
+        this.method = method;
27
+        this.jobHandler = jobHandler;
28
+        this.method.setAccessible(true);
29
+        this.prepareMethod();
30
+    }
31
+
32
+    protected void prepareMethod() {
33
+        String init = jobHandler.init();
34
+        if(!init.isEmpty()) {
35
+            try {
36
+                initMethod = target.getClass().getDeclaredMethod(init);
37
+                initMethod.setAccessible(true);
38
+            } catch (NoSuchMethodException e) {
39
+                logger.warn(e.getMessage(), e);
40
+            }
41
+        }
42
+        String destroy = jobHandler.destroy();
43
+        if(!destroy.isEmpty()) {
44
+            try {
45
+                destroyMethod = target.getClass().getDeclaredMethod(destroy);
46
+                destroyMethod.setAccessible(true);
47
+            } catch (NoSuchMethodException e) {
48
+                logger.warn(e.getMessage(), e);
49
+            }
50
+        }
51
+    }
52
+
53
+    @Override
54
+    public ReturnT<String> execute(String param) throws Exception {
55
+        return (ReturnT<String>) method.invoke(target, new Object[]{param});
56
+    }
57
+
58
+    @Override
59
+    public void init() {
60
+        super.init();
61
+        if(initMethod != null) {
62
+            try {
63
+                initMethod.invoke(target);
64
+            } catch (IllegalAccessException e) {
65
+                logger.warn(e.getMessage(), e);
66
+            } catch (InvocationTargetException e) {
67
+                logger.warn(e.getMessage(), e);
68
+            }
69
+        }
70
+    }
71
+
72
+    @Override
73
+    public void destroy() {
74
+        super.destroy();
75
+        if(destroyMethod != null) {
76
+            try {
77
+                destroyMethod.invoke(target);
78
+            } catch (IllegalAccessException e) {
79
+                logger.warn(e.getMessage(), e);
80
+            } catch (InvocationTargetException e) {
81
+                logger.warn(e.getMessage(), e);
82
+            }
83
+        }
84
+    }
85
+
86
+    public Object getTarget() {
87
+        return target;
88
+    }
89
+
90
+    public Method getMethod() {
91
+        return method;
92
+    }
93
+
94
+    public JobHandler getJobHandler() {
95
+        return jobHandler;
96
+    }
97
+}