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

This commit is contained in:
abel533 2019-12-07 16:45:47 +08:00
parent 82bb3dfcc8
commit 039346b730
3 changed files with 143 additions and 7 deletions

View File

@ -4,12 +4,15 @@ import com.xxl.job.core.executor.XxlJobExecutor;
import com.xxl.job.core.glue.GlueFactory; import com.xxl.job.core.glue.GlueFactory;
import com.xxl.job.core.handler.IJobHandler; import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHandler; 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.BeansException;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationUtils;
import java.lang.reflect.Method;
import java.util.Map; import java.util.Map;
/** /**
@ -26,7 +29,7 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
// init JobHandler Repository // init JobHandler Repository
initJobHandlerRepository(applicationContext); initJobHandlerRepository(applicationContext);
initJobHandlerMethodRepository(applicationContext);
// refresh GlueFactory // refresh GlueFactory
GlueFactory.refreshInstance(1); GlueFactory.refreshInstance(1);
@ -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 ---------------------- // ---------------------- applicationContext ----------------------
private static ApplicationContext applicationContext; private static ApplicationContext applicationContext;
@Override @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext; this.applicationContext = applicationContext;
} }
public static ApplicationContext getApplicationContext() { public static ApplicationContext getApplicationContext() {
return applicationContext; return applicationContext;
} }

View File

@ -9,12 +9,22 @@ import java.lang.annotation.Target;
/** /**
* annotation for job handler * annotation for job handler
* @author 2016-5-17 21:06:49 * @author 2016-5-17 21:06:49
* @author liuzh 2019-12-07
*/ */
@Target({ElementType.TYPE}) @Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Inherited @Inherited
public @interface JobHandler { public @interface JobHandler {
String value() default ""; String value() default "";
/**
* init handler, invoked when JobThread init
*/
String init() default "";
/**
* destroy handler, invoked when JobThread destroy
*/
String destroy() default "";
} }

View File

@ -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;
}
}