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 466deba4..ad6064a3 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 @@ -5,21 +5,29 @@ import com.xxl.job.core.executor.XxlJobExecutor; import com.xxl.job.core.glue.GlueFactory; import com.xxl.job.core.handler.annotation.XxlJob; import com.xxl.job.core.handler.impl.MethodJobHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; 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 org.springframework.core.MethodIntrospector; +import org.springframework.core.annotation.AnnotatedElementUtils; import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + + /** * xxl-job executor (for spring) * * @author xuxueli 2018-11-01 09:24:52 */ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationContextAware, InitializingBean, DisposableBean { + private static final Logger logger = LoggerFactory.getLogger(XxlJobSpringExecutor.class); // start @@ -72,62 +80,75 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC if (applicationContext == null) { return; } - // init job handler from method - String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); - if (beanDefinitionNames!=null && beanDefinitionNames.length>0) { - for (String beanDefinitionName : beanDefinitionNames) { - Object bean = applicationContext.getBean(beanDefinitionName); - Method[] methods = bean.getClass().getDeclaredMethods(); - for (Method method: methods) { - XxlJob xxlJob = AnnotationUtils.findAnnotation(method, XxlJob.class); - if (xxlJob != null) { - - // name - String name = xxlJob.value(); - if (name.trim().length() == 0) { - throw new RuntimeException("xxl-job method-jobhandler name invalid, for[" + bean.getClass() + "#"+ method.getName() +"] ."); - } - if (loadJobHandler(name) != null) { - throw new RuntimeException("xxl-job jobhandler[" + name + "] naming conflicts."); - } - - // execute method - if (!(method.getParameterTypes()!=null && method.getParameterTypes().length==1 && method.getParameterTypes()[0].isAssignableFrom(String.class))) { - throw new RuntimeException("xxl-job method-jobhandler param-classtype invalid, for[" + bean.getClass() + "#"+ method.getName() +"] , " + - "The correct method format like \" public ReturnT execute(String param) \" ."); - } - if (!method.getReturnType().isAssignableFrom(ReturnT.class)) { - throw new RuntimeException("xxl-job method-jobhandler return-classtype invalid, for[" + bean.getClass() + "#"+ method.getName() +"] , " + - "The correct method format like \" public ReturnT execute(String param) \" ."); - } - method.setAccessible(true); - - // init and destory - Method initMethod = null; - Method destroyMethod = null; - - if(xxlJob.init().trim().length() > 0) { - try { - initMethod = bean.getClass().getDeclaredMethod(xxlJob.init()); - initMethod.setAccessible(true); - } catch (NoSuchMethodException e) { - throw new RuntimeException("xxl-job method-jobhandler initMethod invalid, for[" + bean.getClass() + "#"+ method.getName() +"] ."); - } - } - if(xxlJob.destroy().trim().length() > 0) { - try { - destroyMethod = bean.getClass().getDeclaredMethod(xxlJob.destroy()); - destroyMethod.setAccessible(true); - } catch (NoSuchMethodException e) { - throw new RuntimeException("xxl-job method-jobhandler destroyMethod invalid, for[" + bean.getClass() + "#"+ method.getName() +"] ."); + + String[] beanDefinitionNames = applicationContext.getBeanNamesForType(Object.class, false, true); + for (String beanDefinitionName : beanDefinitionNames) { + Object bean = applicationContext.getBean(beanDefinitionName); + + Map annotatedMethods = new HashMap<>(); + try { + annotatedMethods = MethodIntrospector.selectMethods(bean.getClass(), + new MethodIntrospector.MetadataLookup() { + @Override + public XxlJob inspect(Method method) { + return AnnotatedElementUtils.findMergedAnnotation(method, XxlJob.class); } - } + }); + } catch (Throwable ex) { + if (logger.isDebugEnabled()) { + logger.debug("Could not resolve methods for bean with name '" + beanDefinitionName + "'", ex); + } + } + + for (Map.Entry methodXxlJobEntry : annotatedMethods.entrySet()) { + Method method = methodXxlJobEntry.getKey(); + XxlJob xxlJob = methodXxlJobEntry.getValue(); + if (xxlJob == null) { + continue; + } + String name = xxlJob.value(); + if (name.trim().length() == 0) { + throw new RuntimeException("xxl-job method-jobhandler name invalid, for[" + bean.getClass() + "#" + method.getName() + "] ."); + } + if (loadJobHandler(name) != null) { + throw new RuntimeException("xxl-job jobhandler[" + name + "] naming conflicts."); + } - // registry jobhandler - registJobHandler(name, new MethodJobHandler(bean, method, initMethod, destroyMethod)); + // execute method + if (!(method.getParameterTypes().length == 1 && method.getParameterTypes()[0].isAssignableFrom(String.class))) { + throw new RuntimeException("xxl-job method-jobhandler param-classtype invalid, for[" + bean.getClass() + "#" + method.getName() + "] , " + + "The correct method format like \" public ReturnT execute(String param) \" ."); + } + if (!method.getReturnType().isAssignableFrom(ReturnT.class)) { + throw new RuntimeException("xxl-job method-jobhandler return-classtype invalid, for[" + bean.getClass() + "#" + method.getName() + "] , " + + "The correct method format like \" public ReturnT execute(String param) \" ."); + } + method.setAccessible(true); + + // init and destory + Method initMethod = null; + Method destroyMethod = null; + + if (xxlJob.init().trim().length() > 0) { + try { + initMethod = bean.getClass().getDeclaredMethod(xxlJob.init()); + initMethod.setAccessible(true); + } catch (NoSuchMethodException e) { + throw new RuntimeException("xxl-job method-jobhandler initMethod invalid, for[" + bean.getClass() + "#" + method.getName() + "] ."); + } + } + if (xxlJob.destroy().trim().length() > 0) { + try { + destroyMethod = bean.getClass().getDeclaredMethod(xxlJob.destroy()); + destroyMethod.setAccessible(true); + } catch (NoSuchMethodException e) { + throw new RuntimeException("xxl-job method-jobhandler destroyMethod invalid, for[" + bean.getClass() + "#" + method.getName() + "] ."); } } + + // registry jobhandler + registJobHandler(name, new MethodJobHandler(bean, method, initMethod, destroyMethod)); } }