From eee7628986c3eedd92d6673c61710a103607e2ae Mon Sep 17 00:00:00 2001 From: "chen.ma" Date: Wed, 5 Jan 2022 22:55:33 +0800 Subject: [PATCH] =?UTF-8?q?ListableBeanFactory#findAnnotationOnBean=20Spri?= =?UTF-8?q?ngBoot=20=E4=BD=8E=E7=89=88=E6=9C=AC=E9=80=82=E9=85=8D.=20(#64)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/DynamicThreadPoolPostProcessor.java | 22 +++++++-- .../DynamicThreadPoolAnnotationUtil.java | 47 +++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/starter/toolkit/DynamicThreadPoolAnnotationUtil.java diff --git a/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/starter/core/DynamicThreadPoolPostProcessor.java b/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/starter/core/DynamicThreadPoolPostProcessor.java index 2303dc5a..3315cd47 100644 --- a/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/starter/core/DynamicThreadPoolPostProcessor.java +++ b/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/starter/core/DynamicThreadPoolPostProcessor.java @@ -9,6 +9,7 @@ import cn.hippo4j.common.web.base.Result; import cn.hippo4j.starter.common.CommonDynamicThreadPool; import cn.hippo4j.starter.config.BootstrapProperties; import cn.hippo4j.starter.remote.HttpAgent; +import cn.hippo4j.starter.toolkit.DynamicThreadPoolAnnotationUtil; import cn.hippo4j.starter.toolkit.thread.QueueTypeEnum; import cn.hippo4j.starter.toolkit.thread.RejectedTypeEnum; import cn.hippo4j.starter.toolkit.thread.ThreadPoolBuilder; @@ -60,16 +61,29 @@ public final class DynamicThreadPoolPostProcessor implements BeanPostProcessor { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof DynamicThreadPoolExecutor) { - DynamicThreadPool dynamicThreadPool = ApplicationContextHolder.findAnnotationOnBean(beanName, DynamicThreadPool.class); - if (Objects.isNull(dynamicThreadPool)) { - return bean; + DynamicThreadPool dynamicThreadPool; + try { + dynamicThreadPool = ApplicationContextHolder.findAnnotationOnBean(beanName, DynamicThreadPool.class); + if (Objects.isNull(dynamicThreadPool)) { + // 适配低版本 SpringBoot + dynamicThreadPool = DynamicThreadPoolAnnotationUtil.findAnnotationOnBean(beanName, DynamicThreadPool.class); + if (Objects.isNull(dynamicThreadPool)) { + return bean; + } + } + } catch (Exception ex) { + log.error("Failed to create dynamic thread pool in annotation mode.", ex); } + DynamicThreadPoolExecutor dynamicExecutor = (DynamicThreadPoolExecutor) bean; DynamicThreadPoolWrapper wrap = new DynamicThreadPoolWrapper(dynamicExecutor.getThreadPoolId(), dynamicExecutor); ThreadPoolExecutor remoteExecutor = fillPoolAndRegister(wrap); subscribeConfig(wrap); + return remoteExecutor; - } else if (bean instanceof DynamicThreadPoolWrapper) { + } + + if (bean instanceof DynamicThreadPoolWrapper) { DynamicThreadPoolWrapper wrap = (DynamicThreadPoolWrapper) bean; registerAndSubscribe(wrap); } diff --git a/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/starter/toolkit/DynamicThreadPoolAnnotationUtil.java b/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/starter/toolkit/DynamicThreadPoolAnnotationUtil.java new file mode 100644 index 00000000..126e2783 --- /dev/null +++ b/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/starter/toolkit/DynamicThreadPoolAnnotationUtil.java @@ -0,0 +1,47 @@ +package cn.hippo4j.starter.toolkit; + +import cn.hippo4j.common.config.ApplicationContextHolder; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.core.annotation.AnnotationUtils; + +import java.lang.annotation.Annotation; +import java.util.Optional; + +/** + * {@link DynamicThreadPoolAnnotationUtil} 是为了适配低版本 SpringBoot. + * + *

Spring version >= 5.2.0 下述方法才是有效的, 等同于 SpringBoot version 2.2.0.RELEASE + * {@link ListableBeanFactory#findAnnotationOnBean(java.lang.String, java.lang.Class)} + * + *

但这不是一个优雅的实现方式, 因为其中用到了很多强类型转换, 不确定后续 Spring 升级是否会受影响. + * 不过, 可以确定的是 Spring version < 5.3.14 是没问题的, 等同于 SpringBoot version < 2.6.2 + * + * @author chen.ma + * @date 2022/1/5 21:15 + */ +public class DynamicThreadPoolAnnotationUtil { + + /** + * 根据 {@param beanName} 查询注解 {@param annotationType} 是否存在. + * + * @param beanName + * @param annotationType + * @param + * @return + */ + public static A findAnnotationOnBean(String beanName, Class annotationType) { + AbstractApplicationContext context = (AbstractApplicationContext) ApplicationContextHolder.getInstance(); + ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); + A annotation = Optional.ofNullable(beanFactory) + .map(each -> (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName)) + .map(definition -> definition.getResolvedFactoryMethod()) + .map(factoryMethod -> AnnotationUtils.getAnnotation(factoryMethod, annotationType)) + .orElse(null); + + return annotation; + } + +}