Merge pull request #1338 from abel533/method

支持在 Bean 方法使用 @JobHandler 注解
This commit is contained in:
许雪里 2019-12-11 20:26:29 +08:00 committed by GitHub
commit 23f3199672
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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);
@ -42,7 +45,7 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
} }
private void initJobHandlerRepository(ApplicationContext applicationContext){ private void initJobHandlerRepository(ApplicationContext applicationContext) {
if (applicationContext == null) { if (applicationContext == null) {
return; return;
} }
@ -50,13 +53,13 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
// init job handler action // init job handler action
Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(JobHandler.class); 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()) { for (Object serviceBean : serviceBeanMap.values()) {
if (serviceBean instanceof IJobHandler){ if (serviceBean instanceof IJobHandler) {
String name = serviceBean.getClass().getAnnotation(JobHandler.class).value(); String name = serviceBean.getClass().getAnnotation(JobHandler.class).value();
IJobHandler handler = (IJobHandler) serviceBean; IJobHandler handler = (IJobHandler) serviceBean;
if (loadJobHandler(name) != null) { 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); 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 ---------------------- // ---------------------- 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;
}
}