From f2abb4b8e08c6224a2197af7ea7505c848dcb3b0 Mon Sep 17 00:00:00 2001 From: "L.Answer" Date: Wed, 19 May 2021 13:38:46 -0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E8=A7=A3=E6=9E=90=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 10 +- .../AbstractDingerDefinitionResolver.java | 269 +++--------------- .../AnnotationDingerDefinitionResolver.java | 99 +++++++ .../AnnotationParameterNameDiscoverer.java | 68 +++++ .../dinger/core/ClassPathDingerScanner.java | 141 +++++++++ .../core/DefaultDingerDefinitionResolver.java | 163 +++++++++++ .../dinger/core/DingerDefinitionResolver.java | 196 +------------ .../jaemon/dinger/core/DingerHandleProxy.java | 1 - .../dinger/core/DingerMessageHandler.java | 6 +- .../core/DingerParameterNameDiscoverer.java | 56 ++++ .../PrioritizedParameterNameDiscoverer.java | 73 +++++ .../core/XmlDingerDefinitionResolver.java | 153 ++++++++++ .../dinger/core/annatations/DingerScan.java | 51 +++- .../dinger/core/entity/DingerMethod.java | 45 +++ .../dinger/core/entity/DingerProperties.java | 8 +- .../dinger/core/spring/DingerFactoryBean.java | 14 +- .../core/spring/DingerScannerRegistrar.java | 132 ++++----- .../core/spring/DingerSessionSupport.java | 52 ++++ .../listeners/DingerListenersProperty.java | 17 +- .../listeners/DingerXmlPreparedEvent.java | 75 +---- .../MultiDingerAlgorithmInjectRegister.java | 1 - .../multi/MultiDingerScannerRegistrar.java | 16 +- src/main/resources/META-INF/spring.factories | 1 - 23 files changed, 1040 insertions(+), 607 deletions(-) create mode 100644 src/main/java/com/github/jaemon/dinger/core/AnnotationDingerDefinitionResolver.java create mode 100644 src/main/java/com/github/jaemon/dinger/core/AnnotationParameterNameDiscoverer.java create mode 100644 src/main/java/com/github/jaemon/dinger/core/ClassPathDingerScanner.java create mode 100644 src/main/java/com/github/jaemon/dinger/core/DefaultDingerDefinitionResolver.java create mode 100644 src/main/java/com/github/jaemon/dinger/core/DingerParameterNameDiscoverer.java create mode 100644 src/main/java/com/github/jaemon/dinger/core/PrioritizedParameterNameDiscoverer.java create mode 100644 src/main/java/com/github/jaemon/dinger/core/XmlDingerDefinitionResolver.java create mode 100644 src/main/java/com/github/jaemon/dinger/core/entity/DingerMethod.java create mode 100644 src/main/java/com/github/jaemon/dinger/core/spring/DingerSessionSupport.java diff --git a/pom.xml b/pom.xml index 2ef090c..6624686 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ com.github.answerail dinger-spring-boot-starter jar - 1.1.1 + 1.2.0-beta1 dinger-spring-boot-starter Dinger-SpringBoot集成钉钉/企业微信群机器人实现消息通知中间件 @@ -83,6 +83,10 @@ + + AnswerAIL + https://github.com/AnswerAIL/dingtalk-spring-boot-starter + @@ -91,6 +95,10 @@ https://github.com/AnswerAIL/dingtalk-spring-boot-starter/tree/master + + GitHub + https://github.com/AnswerAIL/dingtalk-spring-boot-starter/issues + diff --git a/src/main/java/com/github/jaemon/dinger/core/AbstractDingerDefinitionResolver.java b/src/main/java/com/github/jaemon/dinger/core/AbstractDingerDefinitionResolver.java index 77a1f41..a6593e2 100644 --- a/src/main/java/com/github/jaemon/dinger/core/AbstractDingerDefinitionResolver.java +++ b/src/main/java/com/github/jaemon/dinger/core/AbstractDingerDefinitionResolver.java @@ -16,49 +16,42 @@ package com.github.jaemon.dinger.core; import com.github.jaemon.dinger.constant.DingerConstant; -import com.github.jaemon.dinger.core.annatations.DingerImageText; -import com.github.jaemon.dinger.core.annatations.DingerLink; -import com.github.jaemon.dinger.core.annatations.DingerScan; -import com.github.jaemon.dinger.core.annatations.Parameter; +import com.github.jaemon.dinger.core.annatations.AsyncExecute; +import com.github.jaemon.dinger.core.annatations.DingerConfiguration; +import com.github.jaemon.dinger.core.entity.DingerMethod; import com.github.jaemon.dinger.core.entity.enums.DingerDefinitionType; import com.github.jaemon.dinger.core.entity.enums.DingerType; import com.github.jaemon.dinger.exception.DingerException; import com.github.jaemon.dinger.listeners.DingerListenersProperty; -import com.github.jaemon.dinger.utils.PackageUtils; +import com.github.jaemon.dinger.utils.DingerUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.core.ParameterNameDiscoverer; -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.*; -import java.util.List; +import java.util.HashMap; +import java.util.Map; -import static com.github.jaemon.dinger.core.AbstractDingerDefinitionResolver.Container.INSTANCE; -import static com.github.jaemon.dinger.core.ClassPathScanForResources.*; -import static com.github.jaemon.dinger.core.entity.enums.ExceptionEnum.*; -import static com.github.jaemon.dinger.utils.DingerUtils.methodParamsGenericType; -import static com.github.jaemon.dinger.utils.DingerUtils.methodParamsType; +import static com.github.jaemon.dinger.core.entity.enums.ExceptionEnum.DINGER_REPEATED_EXCEPTION; +import static com.github.jaemon.dinger.core.entity.enums.ExceptionEnum.METHOD_DEFINITION_EXCEPTION; /** - * AbstractDingerDefinitionResolver + * AbsDingerDefinitionResolver * * @author Jaemon - * @since 1.0 + * @version 1.0 */ -public abstract class AbstractDingerDefinitionResolver - extends DingerListenersProperty { +public abstract class AbstractDingerDefinitionResolver extends DingerListenersProperty implements DingerDefinitionResolver { private static final Logger log = LoggerFactory.getLogger(AbstractDingerDefinitionResolver.class); /** dinger消息类型和对应生成器映射关系 */ - protected Map> dingerDefinitionGeneratorMap; - /** Dinger默认的DingerConfig */ - protected Map defaultDingerConfigs; + private Map> dingerDefinitionGeneratorMap; + /** + * 方法参数名称解析 + */ + protected ParameterNameDiscoverer parameterNameDiscoverer; public AbstractDingerDefinitionResolver() { this.dingerDefinitionGeneratorMap = new HashMap<>(); - this.defaultDingerConfigs = new HashMap<>(); + this.parameterNameDiscoverer = new DingerParameterNameDiscoverer(); for (DingerDefinitionType dingerDefinitionType : DingerDefinitionType.dingerDefinitionTypes) { dingerDefinitionGeneratorMap.put( @@ -71,120 +64,26 @@ public AbstractDingerDefinitionResolver() { } - /** - * 解析XML文件Dinger - * - * @param resources - * Dinger.xml文件集 - * @throws Exception ex - */ - abstract void analysisDingerXml(Resource[] resources) throws Exception; - - /** - * 解析注解Dinger - * - * @param dingerClasses - * dingerClasses - * @throws Exception - * ex - */ - abstract void analysisDingerAnnotation(List> dingerClasses) throws Exception; - + protected DingerConfig dingerConfiguration(Class dingerClass) { + DingerConfig dingerConfig = new DingerConfig(); - /** - * Xml定义Dinger解析处理 - * - * @param dingerLocations - * Dinger Xml文件位置 - * @throws Exception - * ex - * */ - protected void dingerXmlResolver(String dingerLocations) throws Exception { - boolean debugEnabled = log.isDebugEnabled(); - if (dingerLocations == null) { - if (debugEnabled) { - log.debug("dinger xml is not configured."); + if (dingerClass.isAnnotationPresent(DingerConfiguration.class)) { + DingerConfiguration dingerConfiguration = dingerClass.getAnnotation(DingerConfiguration.class); + String tokenId = dingerConfiguration.tokenId(); + if (DingerUtils.isNotEmpty(tokenId)) { + dingerConfig.setTokenId(tokenId); + dingerConfig.setDecryptKey(dingerConfiguration.decryptKey()); + dingerConfig.setSecret(dingerConfiguration.secret()); } - return; } - // 处理xml配置转为dingerDefinition - ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); - Resource[] resources = resolver.getResources(dingerLocations); - if (resources.length == 0) { - log.warn("dinger xml is empty under {}.", dingerLocations); - return; + if (dingerClass.isAnnotationPresent(AsyncExecute.class)) { + dingerConfig.setAsyncExecute(true); } - - analysisDingerXml(resources); + return dingerConfig; } - /** - * 注释定义Dinger解析处理 - * - * @return - * Dinger类集合 - * @throws Exception - * ex - * */ - protected List> dingerAnnotationResolver() throws Exception { - boolean debugEnabled = log.isDebugEnabled(); - // deal with annotation - DingerScan dingerScan = null; - List> dingerClasses = new ArrayList<>(); - // 获取启动类下所有Dinger标注的类信息 - for (Class primarySource : DingerListenersProperty.primarySources()) { - if (debugEnabled) { - log.debug("ready to analysis primarySource[{}].", primarySource.getName()); - } - // 存在DingerScan并记录, 后续使用扫面 XXXDinger.java - if (primarySource.isAnnotationPresent(DingerScan.class)) { - // obtain dingerScan basePackages value - if (dingerScan == null) { - dingerScan = primarySource.getAnnotation(DingerScan.class); - } else { - throw new DingerException(MULTI_DINGER_SCAN_ERROR); - } - } - } - - // 获取dingerScan下所有类信息 - if (dingerScan != null) { - String[] basePackages = dingerScan.basePackages(); - for (String basePackage : basePackages) { - if (debugEnabled) { - log.debug("ready to scan package[{}] for Dinger.", basePackage); - } - List> classes = scanInterfaces(basePackage); - if (!classes.isEmpty()) { - dingerClasses.addAll(classes); - } - } - - if (dingerClasses.isEmpty()) { - log.warn("the first time to parse the packages[{}] is empty.", Arrays.asList(basePackages)); - for (String basePackage : basePackages) { - PackageUtils.classNames(basePackage, dingerClasses, true); - } - } - } else { - log.warn("annotation dingerScan is not configured and will execute Dinger scanner registrar."); - } - - if (dingerClasses.isEmpty()) { - if (debugEnabled) { - log.debug("annotation dinger class is empty."); - } - return dingerClasses; - } - - // 处理类信息转为dingerDefinition - analysisDingerAnnotation(dingerClasses); - - return dingerClasses; - } - /** * 注册Dinger Definition * @@ -240,114 +139,28 @@ void registerDingerDefinition( } continue; } - if (INSTANCE.contains(keyName)) { + if (Container.INSTANCE.contains(keyName)) { throw new DingerException(DINGER_REPEATED_EXCEPTION, keyName); } if (dingerMethod.check()) { - throw new DingerException(METHOD_DEFINITION_EXCEPTION, dingerMethod.methodName); + throw new DingerException(METHOD_DEFINITION_EXCEPTION, dingerMethod.getMethodName()); } - dingerDefinition.setMethodParams(dingerMethod.methodParams); - dingerDefinition.setGenericIndex(dingerMethod.paramTypes); + dingerDefinition.setMethodParams(dingerMethod.getMethodParams()); + dingerDefinition.setGenericIndex(dingerMethod.getParamTypes()); // DingerConfig Priority: `@DingerText | @DingerMarkdown | XML` > `@DingerConfiguration` > `***.yml | ***.properties` dingerDefinition.dingerConfig() .merge(dingerConfiguration) .merge(defaultDingerConfig); - INSTANCE.put(keyName, dingerDefinition); + Container.INSTANCE.put(keyName, dingerDefinition); if (debugEnabled) { log.debug("dinger definition={} has been registed.", keyName); } } } - /** - * 获取当前Dinger接口层方法的所有参数信息 - * - * @param dingerClass - * Dinger接口层类 - * @return - * 当前Dinger接口定义的方法的参数信息和泛型信息 - */ - protected Map dingerClassMethods(Class dingerClass) { - Method[] methods = dingerClass.getMethods(); - Map dingerMethodParams = new HashMap<>(); - for (Method method : methods) { - String methodName = method.getName(); - String methodAllName = dingerClass.getSimpleName() + DingerConstant.SPOT_SEPERATOR + methodName; - int[] paramTypes = null; - if (method.isAnnotationPresent(DingerImageText.class)) { - paramTypes = methodParamsGenericType(method, DingerImageText.clazz); - if (paramTypes.length != 1) { - throw new DingerException(IMAGETEXT_METHOD_PARAM_EXCEPTION, methodAllName); - } - } else if (method.isAnnotationPresent(DingerLink.class)) { - paramTypes = methodParamsType(method, DingerLink.clazz); - if (paramTypes.length != 1) { - throw new DingerException(LINK_METHOD_PARAM_EXCEPTION, methodAllName); - } - } - String[] methodParams = methodParams(method); - dingerMethodParams.put(methodName, new DingerMethod(methodAllName, methodParams, paramTypes)); - } - return dingerMethodParams; - } - - /** - * 获取当前方法的所有参数信息 - * - * @param method - * Dinger接口层方法 - * @return - * 当前方法的参数信息 - */ - protected String[] methodParams(Method method) { - Annotation[][] parameterAnnotations = method.getParameterAnnotations(); - java.lang.reflect.Parameter[] parameters = method.getParameters(); - String[] params = new String[parameterAnnotations.length]; - - for (int i = 0; i < parameterAnnotations.length; i++) { - Annotation[] parameterAnnotation = parameterAnnotations[i]; - params[i] = parameters[i].getName(); - for (Annotation annotation : parameterAnnotation) { - if (Parameter.class.isInstance(annotation)) { - Parameter dingerParam = (Parameter) annotation; - params[i] = dingerParam.value(); - break; - } - } - } - return params; - } - - static class DingerMethod { - String methodName; - String[] methodParams; - int[] paramTypes; - - public DingerMethod(String methodName, String[] methodParams, int[] paramTypes) { - this.methodName = methodName; - this.methodParams = methodParams; - this.paramTypes = paramTypes; - } - - boolean check() { - if (paramTypes == null) { - return false; - } - - int length = this.methodParams.length; - for (int index : paramTypes) { - if (index >= length) { - return true; - } - } - return false; - } - - } - /** * Container for DingerDefinition */ @@ -392,16 +205,4 @@ boolean contains(String key) { protected static void clear() { Container.INSTANCE.container.clear(); } - - /** - * transferXml - * - * solve -Djavax.xml.accessExternalSchema=all - * - * @param sourceXml sourceXml - * @return xml - */ - String transferXml(String sourceXml) { - return sourceXml.replaceAll("", ""); - } } \ No newline at end of file diff --git a/src/main/java/com/github/jaemon/dinger/core/AnnotationDingerDefinitionResolver.java b/src/main/java/com/github/jaemon/dinger/core/AnnotationDingerDefinitionResolver.java new file mode 100644 index 0000000..9d98c8a --- /dev/null +++ b/src/main/java/com/github/jaemon/dinger/core/AnnotationDingerDefinitionResolver.java @@ -0,0 +1,99 @@ +/* + * Copyright ©2015-2021 Jaemon. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.jaemon.dinger.core; + +import com.github.jaemon.dinger.core.annatations.DingerImageText; +import com.github.jaemon.dinger.core.annatations.DingerLink; +import com.github.jaemon.dinger.core.annatations.DingerMarkdown; +import com.github.jaemon.dinger.core.annatations.DingerText; +import com.github.jaemon.dinger.core.entity.DingerMethod; +import com.github.jaemon.dinger.core.entity.enums.MessageMainType; +import com.github.jaemon.dinger.core.entity.enums.MessageSubType; +import com.github.jaemon.dinger.exception.DingerException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Method; +import java.util.List; + +import static com.github.jaemon.dinger.constant.DingerConstant.SPOT_SEPERATOR; +import static com.github.jaemon.dinger.core.entity.enums.ExceptionEnum.IMAGETEXT_METHOD_PARAM_EXCEPTION; +import static com.github.jaemon.dinger.core.entity.enums.ExceptionEnum.LINK_METHOD_PARAM_EXCEPTION; +import static com.github.jaemon.dinger.utils.DingerUtils.methodParamsGenericType; +import static com.github.jaemon.dinger.utils.DingerUtils.methodParamsType; + +/** + * dinger定义-注解方式 + * + * @author Jaemon + * @since 1.2 + */ +public class AnnotationDingerDefinitionResolver extends AbstractDingerDefinitionResolver>> { + private static final Logger log = LoggerFactory.getLogger(AnnotationDingerDefinitionResolver.class); + + @Override + public void resolver(List> dingerClasses) { + for (Class dingerClass : dingerClasses) { + // dinger 层钉钉机器人配置 + DingerConfig dingerConfiguration = dingerConfiguration(dingerClass); + + String namespace = dingerClass.getName(); + Method[] methods = dingerClass.getMethods(); + for (Method method : methods) { + String dingerName = namespace + SPOT_SEPERATOR + method.getName(); + String dingerDefinitionKey = MessageMainType.ANNOTATION + SPOT_SEPERATOR; + + Object source; + MessageSubType messageSubType; + int[] paramTypes = null; + if (method.isAnnotationPresent(DingerText.class)) { + source = method.getAnnotation(DingerText.class); + messageSubType = MessageSubType.TEXT; + } else if (method.isAnnotationPresent(DingerMarkdown.class)) { + source = method.getAnnotation(DingerMarkdown.class); + messageSubType = MessageSubType.MARKDOWN; + } else if (method.isAnnotationPresent(DingerImageText.class)) { + paramTypes = methodParamsGenericType(method, DingerImageText.clazz); + if (paramTypes.length != 1) { + throw new DingerException(IMAGETEXT_METHOD_PARAM_EXCEPTION, dingerName); + } + source = method.getAnnotation(DingerImageText.class); + messageSubType = MessageSubType.IMAGETEXT; + } else if (method.isAnnotationPresent(DingerLink.class)) { + paramTypes = methodParamsType(method, DingerLink.clazz); + if (paramTypes.length != 1) { + throw new DingerException(LINK_METHOD_PARAM_EXCEPTION, dingerName); + } + source = method.getAnnotation(DingerLink.class); + messageSubType = MessageSubType.LINK; + } else { + if (log.isDebugEnabled()) { + log.debug("register annotation dingerDefinition and skip method={}(possible use xml definition).", dingerName); + } + continue; + } + + registerDingerDefinition( + dingerName, source, + dingerDefinitionKey + messageSubType, + dingerConfiguration, + new DingerMethod(dingerName, parameterNameDiscoverer.getParameterNames(method), paramTypes) + ); + } + + } + } +} \ No newline at end of file diff --git a/src/main/java/com/github/jaemon/dinger/core/AnnotationParameterNameDiscoverer.java b/src/main/java/com/github/jaemon/dinger/core/AnnotationParameterNameDiscoverer.java new file mode 100644 index 0000000..a7769b1 --- /dev/null +++ b/src/main/java/com/github/jaemon/dinger/core/AnnotationParameterNameDiscoverer.java @@ -0,0 +1,68 @@ +/* + * Copyright ©2015-2021 Jaemon. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.jaemon.dinger.core; + +import com.github.jaemon.dinger.core.annatations.Parameter; +import org.springframework.core.ParameterNameDiscoverer; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** + * 注解参数名称解析 + * + * @author Jaemon + * @since 1.2 + */ +public class AnnotationParameterNameDiscoverer implements ParameterNameDiscoverer { + @Override + public String[] getParameterNames(Method method) { + return getParameterNames(method.getParameters(), method.getParameterAnnotations()); + } + + @Override + public String[] getParameterNames(Constructor ctor) { + return getParameterNames(ctor.getParameters(), ctor.getParameterAnnotations()); + } + + /** + * 获取参数名称 + * + * @param parameters + * 参数对象{@link java.lang.reflect.Parameter}集 + * @param parameterAnnotations + * 参数注解 + * @return + * 参数名称 + */ + protected String[] getParameterNames(java.lang.reflect.Parameter[] parameters, Annotation[][] parameterAnnotations) { + String[] params = new String[parameterAnnotations.length]; + + for (int i = 0; i < parameterAnnotations.length; i++) { + Annotation[] parameterAnnotation = parameterAnnotations[i]; + params[i] = parameters[i].getName(); + for (Annotation annotation : parameterAnnotation) { + if (Parameter.class.isInstance(annotation)) { + Parameter dingerParam = (Parameter) annotation; + params[i] = dingerParam.value(); + break; + } + } + } + return params; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/jaemon/dinger/core/ClassPathDingerScanner.java b/src/main/java/com/github/jaemon/dinger/core/ClassPathDingerScanner.java new file mode 100644 index 0000000..5938d35 --- /dev/null +++ b/src/main/java/com/github/jaemon/dinger/core/ClassPathDingerScanner.java @@ -0,0 +1,141 @@ +/* + * Copyright ©2015-2021 Jaemon. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.jaemon.dinger.core; + +import com.github.jaemon.dinger.core.spring.DingerFactoryBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.core.type.filter.AssignableTypeFilter; +import org.springframework.util.ClassUtils; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +/** + * Dinger扫描器 + * + * @author Jaemon + * @since 1.2 + */ +public class ClassPathDingerScanner extends ClassPathBeanDefinitionScanner { + private static final Logger log = LoggerFactory.getLogger(ClassPathDingerScanner.class); + private List> dingerClasses; + private Class annotationClass; + private Class markerInterface; + + public ClassPathDingerScanner(BeanDefinitionRegistry registry) { + super(registry, false); + dingerClasses = new ArrayList<>(); + } + + public void setAnnotationClass(Class annotationClass) { + this.annotationClass = annotationClass; + } + + public void setMarkerInterface(Class markerInterface) { + this.markerInterface = markerInterface; + } + + public void registerFilters() { + boolean acceptAllInterfaces = true; + + // if specified, use the given annotation and / or marker interface + if (this.annotationClass != null) { + addIncludeFilter(new AnnotationTypeFilter(this.annotationClass)); + acceptAllInterfaces = false; + } + + // override AssignableTypeFilter to ignore matches on the actual marker interface + if (this.markerInterface != null) { + addIncludeFilter(new AssignableTypeFilter(this.markerInterface) { + @Override + protected boolean matchClassName(String className) { + return false; + } + }); + acceptAllInterfaces = false; + } + + if (acceptAllInterfaces) { + // default include filter that accepts all classes + addIncludeFilter((metadataReader, metadataReaderFactory) -> true); + } + + // exclude package-info.java + addExcludeFilter((metadataReader, metadataReaderFactory) -> { + String className = metadataReader.getClassMetadata().getClassName(); + return className.endsWith("package-info"); + }); + } + + @Override + public Set doScan(String... basePackages) { + Set beanDefinitions = super.doScan(basePackages); + + if (beanDefinitions.isEmpty()) { + log.warn("No Dinger was found in '{}' package. Please check your configuration.", + Arrays.toString(basePackages)); + } else { + processBeanDefinitions(beanDefinitions); + } + + return beanDefinitions; + } + + @Override + protected boolean isCandidateComponent(AnnotatedBeanDefinition annotatedBeanDefinition) { + return annotatedBeanDefinition.getMetadata().isInterface() && annotatedBeanDefinition.getMetadata().isIndependent(); + } + + private void processBeanDefinitions(Set beanDefinitions) { + boolean debugEnabled = log.isDebugEnabled(); + GenericBeanDefinition definition; + for (BeanDefinitionHolder beanDefinition : beanDefinitions) { + definition = (GenericBeanDefinition) beanDefinition.getBeanDefinition(); + String beanClassName = definition.getBeanClassName(); + + if (debugEnabled) { + log.debug("Creating DingerFactoryBean with name '{}' and '{}' dingerInterface", + beanDefinition.getBeanName(), beanClassName); + } + + try { + dingerClasses.add(ClassUtils.forName(beanClassName, this.getClass().getClassLoader())); + } catch (ClassNotFoundException e) { + log.warn("beanClassName=[{}] not found", beanClassName); + } + + definition.setBeanClass(DingerFactoryBean.class); + definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); + definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); + } + + } + + public List> getDingerClasses() { + return dingerClasses; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/jaemon/dinger/core/DefaultDingerDefinitionResolver.java b/src/main/java/com/github/jaemon/dinger/core/DefaultDingerDefinitionResolver.java new file mode 100644 index 0000000..9ac81e7 --- /dev/null +++ b/src/main/java/com/github/jaemon/dinger/core/DefaultDingerDefinitionResolver.java @@ -0,0 +1,163 @@ +/* + * Copyright ©2015-2021 Jaemon. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.jaemon.dinger.core; + +import com.github.jaemon.dinger.constant.DingerConstant; +import com.github.jaemon.dinger.core.entity.enums.DingerType; +import com.github.jaemon.dinger.exception.DingerException; +import com.github.jaemon.dinger.listeners.DingerListenersProperty; +import com.github.jaemon.dinger.utils.DingerUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.Environment; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; + +import java.io.IOException; +import java.util.*; + +import static com.github.jaemon.dinger.constant.DingerConstant.DINGER_PROPERTIES_PREFIX; +import static com.github.jaemon.dinger.constant.DingerConstant.SPOT_SEPERATOR; +import static com.github.jaemon.dinger.core.entity.enums.ExceptionEnum.RESOURCE_CONFIG_EXCEPTION; + +/** + * Default DingerDefinition Resolver + * + * @author Jaemon + * @since 1.2 + */ +public class DefaultDingerDefinitionResolver extends DingerListenersProperty implements EnvironmentAware { + private static final Logger log = LoggerFactory.getLogger(DefaultDingerDefinitionResolver.class); + private final DingerDefinitionResolver xmlDingerDefinitionResolver; + private final DingerDefinitionResolver annotaDingerDefinitionResolver; + private Environment environment; + + public DefaultDingerDefinitionResolver() { + xmlDingerDefinitionResolver = new XmlDingerDefinitionResolver(); + annotaDingerDefinitionResolver = new AnnotationDingerDefinitionResolver(); + } + + /** + * 解析处理 + * + * @param dingerClasses + * Dinger类集合 + * */ + protected void resolver(List> dingerClasses) { + registerDefaultDingerConfig(environment); + + // deal with xml + dingerXmlResolver(); + + // deal with annotation + annotaDingerDefinitionResolver.resolver(dingerClasses); + } + + /** + * Xml定义Dinger解析处理 + * */ + protected void dingerXmlResolver() { + boolean debugEnabled = log.isDebugEnabled(); + String dingerLocationsProp = DingerConstant.DINGER_PROPERTIES_PREFIX + "dinger-locations"; + String dingerLocations = environment.getProperty(dingerLocationsProp); + if (dingerLocations == null) { + if (debugEnabled) { + log.debug("dinger xml is not configured."); + } + return; + } + + // 处理xml配置转为dingerDefinition + ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + Resource[] resources; + try { + resources = resolver.getResources(dingerLocations); + } catch (IOException e) { + throw new DingerException(RESOURCE_CONFIG_EXCEPTION, dingerLocations); + } + if (resources.length == 0) { + log.warn("dinger xml is empty under {}.", dingerLocations); + return; + } + + xmlDingerDefinitionResolver.resolver(resources); + } + + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + /** + * 注册默认的Dinger机器人信息, 即配置文件内容 + * + * @param environment + * environment + */ + private void registerDefaultDingerConfig(Environment environment) { + if (environment == null) { + log.warn("environment is null."); + return; + } + for (DingerType dingerType : enabledDingerTypes) { + String dingers = DINGER_PROPERTIES_PREFIX + "dingers" + SPOT_SEPERATOR + dingerType.name().toLowerCase() + SPOT_SEPERATOR; + String tokenIdProp = dingers + "token-id"; + String secretProp = dingers + "secret"; + String decryptProp = dingers + "decrypt"; + String decryptKeyProp = dingers + "decryptKey"; + String asyncExecuteProp = dingers + "async"; + + if (DingerUtils.isEmpty(tokenIdProp)) { + if (log.isDebugEnabled()) { + log.debug("dinger={} is not open.", dingerType); + } + continue; + } + String tokenId = environment.getProperty(tokenIdProp); + String secret = environment.getProperty(secretProp); + boolean decrypt = getProperty(environment, decryptProp); + boolean async = getProperty(environment, asyncExecuteProp); + DingerConfig defaultDingerConfig = DingerConfig.instance(tokenId); + defaultDingerConfig.setDingerType(dingerType); + defaultDingerConfig.setSecret(secret); + if (decrypt) { + defaultDingerConfig.setDecryptKey( + environment.getProperty(decryptKeyProp) + ); + } + defaultDingerConfig.setAsyncExecute(async); + + defaultDingerConfig.check(); + defaultDingerConfigs.put(dingerType, defaultDingerConfig); + } + } + + /** + * getProperty + * + * @param environment environment + * @param prop prop + * @return prop value + */ + private boolean getProperty(Environment environment, String prop) { + if (environment.getProperty(prop) != null) { + return environment.getProperty(prop, boolean.class); + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/jaemon/dinger/core/DingerDefinitionResolver.java b/src/main/java/com/github/jaemon/dinger/core/DingerDefinitionResolver.java index 2046aeb..fa40d26 100644 --- a/src/main/java/com/github/jaemon/dinger/core/DingerDefinitionResolver.java +++ b/src/main/java/com/github/jaemon/dinger/core/DingerDefinitionResolver.java @@ -15,202 +15,18 @@ */ package com.github.jaemon.dinger.core; -import com.github.jaemon.dinger.constant.DingerConstant; -import com.github.jaemon.dinger.core.annatations.*; -import com.github.jaemon.dinger.core.entity.enums.MessageMainType; -import com.github.jaemon.dinger.core.entity.enums.MessageSubType; -import com.github.jaemon.dinger.core.entity.xml.BeanTag; -import com.github.jaemon.dinger.core.entity.xml.MessageTag; -import com.github.jaemon.dinger.exception.DingerException; -import com.github.jaemon.dinger.utils.DingerUtils; -import com.github.jaemon.dinger.utils.XmlUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.io.Resource; -import org.springframework.util.FileCopyUtils; - -import java.lang.reflect.Method; -import java.util.*; - -import static com.github.jaemon.dinger.constant.DingerConstant.SPOT_SEPERATOR; -import static com.github.jaemon.dinger.core.entity.enums.ExceptionEnum.*; -import static com.github.jaemon.dinger.utils.DingerUtils.methodParamsGenericType; -import static com.github.jaemon.dinger.utils.DingerUtils.methodParamsType; - /** - * DingerDefinitionResolver + * DingerDefinition Resolver * * @author Jaemon * @since 1.0 */ -public class DingerDefinitionResolver extends AbstractDingerDefinitionResolver { - private static final Logger log = LoggerFactory.getLogger(DingerDefinitionResolver.class); - protected static final String DINGER_PROPERTIES_PREFIX = DingerConstant.DINGER_PROPERTIES_PREFIX; - +public interface DingerDefinitionResolver { /** - * 解析处理 + * 解析器 * - * @param event - * the event to respond to - * @return - * Dinger类集合 - * @throws Exception - * ex - * */ - protected List> doAnalysis(ApplicationEnvironmentPreparedEvent event) throws Exception { - try { - ConfigurableEnvironment environment = event.getEnvironment(); - String DingerLocationsProp = DINGER_PROPERTIES_PREFIX + "dinger-locations"; - String dingerLocations = environment.getProperty(DingerLocationsProp); - - // deal with xml - dingerXmlResolver(dingerLocations); - - // deal with annotation - return dingerAnnotationResolver(); - } finally { - defaultDingerConfigs.clear(); - defaultDingerConfigs = null; - dingerDefinitionGeneratorMap.clear(); - dingerDefinitionGeneratorMap = null; - } - } - - @Override - synchronized - void analysisDingerXml(Resource[] resources) throws Exception { - boolean debugEnabled = log.isDebugEnabled(); - for (Resource resource : resources) { - if (!resource.isReadable()) { - if (debugEnabled) { - log.debug("Ignored because not readable: {} ", resource.getFilename()); - } - continue; - } - String xml = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()), "UTF-8"); - xml = transferXml(xml); - BeanTag dingerBean = XmlUtils.xmlToJavaBean(xml, BeanTag.class); - if (dingerBean == null) { - if (debugEnabled) { - log.debug("dinger xml file: {} content is empty.", resource.getFilename()); - } - continue; - } - String namespace = dingerBean.getNamespace(); - Class dingerClass = Class.forName(namespace); - if (dingerClass == null) { - throw new DingerException(DINER_XML_NAMESPACE_INVALID, namespace); - } - Map dingerClassMethods = dingerClassMethods(dingerClass); - - DingerConfig dingerConfiguration = dingerConfiguration(dingerClass); - - List messages = dingerBean.getMessages(); - for (MessageTag message : messages) { - String methodName = message.getIdentityId(); - if (!dingerClassMethods.containsKey(methodName)) { - log.warn("namespace={}, messageId={} undefined in dingerClass.", - namespace, methodName); - continue; - } - String dingerName = namespace + SPOT_SEPERATOR + methodName; - String messageSubType = message.getDingerType(); - if (!MessageSubType.contains(messageSubType)) { - throw new DingerException(DINER_XML_MSGTYPE_INVALID, dingerName, messageSubType); - } - String dingerDefinitionKey = MessageMainType.XML + SPOT_SEPERATOR + message.getDingerType(); - - registerDingerDefinition( - dingerName, message, - dingerDefinitionKey, - dingerConfiguration, - dingerClassMethods.get(methodName) - ); - } - } - } - - - @Override - synchronized - void analysisDingerAnnotation(List> dingerClasses) throws Exception { - for (Class dingerClass : dingerClasses) { - // dinger 层钉钉机器人配置 - DingerConfig dingerConfiguration = dingerConfiguration(dingerClass); - - String namespace = dingerClass.getName(); - Method[] methods = dingerClass.getMethods(); - for (Method method : methods) { - String dingerName = namespace + SPOT_SEPERATOR + method.getName(); - String dingerDefinitionKey = MessageMainType.ANNOTATION + SPOT_SEPERATOR; - - Object source; - MessageSubType messageSubType; - int[] paramTypes = null; - if (method.isAnnotationPresent(DingerText.class)) { - source = method.getAnnotation(DingerText.class); - messageSubType = MessageSubType.TEXT; - } else if (method.isAnnotationPresent(DingerMarkdown.class)) { - source = method.getAnnotation(DingerMarkdown.class); - messageSubType = MessageSubType.MARKDOWN; - } else if (method.isAnnotationPresent(DingerImageText.class)) { - paramTypes = methodParamsGenericType(method, DingerImageText.clazz); - if (paramTypes.length != 1) { - throw new DingerException(IMAGETEXT_METHOD_PARAM_EXCEPTION, dingerName); - } - source = method.getAnnotation(DingerImageText.class); - messageSubType = MessageSubType.IMAGETEXT; - } else if (method.isAnnotationPresent(DingerLink.class)) { - paramTypes = methodParamsType(method, DingerLink.clazz); - if (paramTypes.length != 1) { - throw new DingerException(LINK_METHOD_PARAM_EXCEPTION, dingerName); - } - source = method.getAnnotation(DingerLink.class); - messageSubType = MessageSubType.LINK; - } else { - if (log.isDebugEnabled()) { - log.debug("register annotation dingerDefinition and skip method={}(possible use xml definition).", dingerName); - } - continue; - } - - registerDingerDefinition( - dingerName, source, - dingerDefinitionKey + messageSubType, - dingerConfiguration, - new DingerMethod(dingerName, methodParams(method), paramTypes) - ); - } - - } - } - - /** - * Dinger层级别机器人配置 - * - * @param dingerClass dingerClass - * @return dingerConfig + * @param context + * 上下文路径 */ - private DingerConfig dingerConfiguration(Class dingerClass) { - DingerConfig dingerConfig = new DingerConfig(); - - if (dingerClass.isAnnotationPresent(DingerConfiguration.class)) { - DingerConfiguration dingerConfiguration = dingerClass.getAnnotation(DingerConfiguration.class); - String tokenId = dingerConfiguration.tokenId(); - if (DingerUtils.isNotEmpty(tokenId)) { - dingerConfig.setTokenId(tokenId); - dingerConfig.setDecryptKey(dingerConfiguration.decryptKey()); - dingerConfig.setSecret(dingerConfiguration.secret()); - } - } - - if (dingerClass.isAnnotationPresent(AsyncExecute.class)) { - dingerConfig.setAsyncExecute(true); - } - return dingerConfig; - } - - + void resolver(T context); } \ No newline at end of file diff --git a/src/main/java/com/github/jaemon/dinger/core/DingerHandleProxy.java b/src/main/java/com/github/jaemon/dinger/core/DingerHandleProxy.java index 376cae3..41b3a4d 100644 --- a/src/main/java/com/github/jaemon/dinger/core/DingerHandleProxy.java +++ b/src/main/java/com/github/jaemon/dinger/core/DingerHandleProxy.java @@ -74,7 +74,6 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl DingerResponse dingerResponse; if (dingerDefinition == null) { -// log.warn("method {} does not support dinger {}。", keyName, useDinger); dingerResponse = DingerResponse.failed( DingerResponseCodeEnum.MESSAGE_TYPE_UNSUPPORTED, String.format("method %s does not support dinger %s.", keyName, useDinger)); diff --git a/src/main/java/com/github/jaemon/dinger/core/DingerMessageHandler.java b/src/main/java/com/github/jaemon/dinger/core/DingerMessageHandler.java index 8974069..0826290 100644 --- a/src/main/java/com/github/jaemon/dinger/core/DingerMessageHandler.java +++ b/src/main/java/com/github/jaemon/dinger/core/DingerMessageHandler.java @@ -20,7 +20,6 @@ import com.github.jaemon.dinger.core.entity.MsgType; import com.github.jaemon.dinger.core.entity.enums.DingerType; import com.github.jaemon.dinger.core.entity.DingerResponse; -import com.github.jaemon.dinger.listeners.DingerXmlPreparedEvent; import com.github.jaemon.dinger.multi.MultiDingerConfigContainer; import com.github.jaemon.dinger.multi.MultiDingerProperty; import com.github.jaemon.dinger.multi.entity.MultiDingerConfig; @@ -85,7 +84,6 @@ public Map paramsHandler(Method method, DingerDefinition dingerD String paramName = parameter.getName(); com.github.jaemon.dinger.core.annatations.Parameter[] panno = parameter.getDeclaredAnnotationsByType(com.github.jaemon.dinger.core.annatations.Parameter.class); -// Keyword[] kanno = parameter.getDeclaredAnnotationsByType(Keyword.class); if (panno != null && panno.length > 0) { paramName = panno[0].value(); } @@ -182,7 +180,7 @@ DingerDefinition dingerDefinition(DingerType useDinger, String dingerClassName, // 优先使用用户设定 dingerConfig if (localDinger == null) { String dingerName = useDinger + SPOT_SEPERATOR + keyName; - dingerDefinition = DingerXmlPreparedEvent + dingerDefinition = AbstractDingerDefinitionResolver .Container.INSTANCE.get(dingerName); if (dingerDefinition == null) { @@ -221,7 +219,7 @@ DingerDefinition dingerDefinition(DingerType useDinger, String dingerClassName, dingerType = useDinger; } keyName = dingerType + SPOT_SEPERATOR + keyName; - dingerDefinition = DingerXmlPreparedEvent + dingerDefinition = AbstractDingerDefinitionResolver .Container.INSTANCE.get(keyName); if (dingerDefinition == null) { diff --git a/src/main/java/com/github/jaemon/dinger/core/DingerParameterNameDiscoverer.java b/src/main/java/com/github/jaemon/dinger/core/DingerParameterNameDiscoverer.java new file mode 100644 index 0000000..6a3c3e8 --- /dev/null +++ b/src/main/java/com/github/jaemon/dinger/core/DingerParameterNameDiscoverer.java @@ -0,0 +1,56 @@ +/* + * Copyright ©2015-2021 Jaemon. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.jaemon.dinger.core; + +import org.springframework.core.*; + +/** + * {@link ParameterNameDiscoverer} implementation that tries several discoverer + * delegates in succession. Those added first in the {@code addDiscoverer} method + * have highest priority. If one returns {@code null}, the next will be tried. + * + *

The default behavior is to return {@code null} if no discoverer matches. + * + * @author Jaemon + * @since 1.2 + * @see org.springframework.core.PrioritizedParameterNameDiscoverer + */ +/** + * Default implementation of the {@link ParameterNameDiscoverer} strategy interface, + * using the Java 8 standard reflection mechanism (if available), and falling back + * to the ASM-based {@link LocalVariableTableParameterNameDiscoverer} for checking + * debug information in the class file. + * + *

If a Kotlin reflection implementation is present, + * {@link KotlinReflectionParameterNameDiscoverer} is added first in the list and + * used for Kotlin classes and interfaces. When compiling or running as a GraalVM + * native image, the {@code KotlinReflectionParameterNameDiscoverer} is not used. + * + *

Further discoverers may be added through {@link #addDiscoverer(ParameterNameDiscoverer)}. + * + * @author Jaemon + * @since 1.0 + * @see StandardReflectionParameterNameDiscoverer + * @see LocalVariableTableParameterNameDiscoverer + * @see KotlinReflectionParameterNameDiscoverer + */ +public class DingerParameterNameDiscoverer extends PrioritizedParameterNameDiscoverer { + + public DingerParameterNameDiscoverer() { +// addDiscoverer(new StandardReflectionParameterNameDiscoverer()); + addDiscoverer(new AnnotationParameterNameDiscoverer()); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/jaemon/dinger/core/PrioritizedParameterNameDiscoverer.java b/src/main/java/com/github/jaemon/dinger/core/PrioritizedParameterNameDiscoverer.java new file mode 100644 index 0000000..6ade5fa --- /dev/null +++ b/src/main/java/com/github/jaemon/dinger/core/PrioritizedParameterNameDiscoverer.java @@ -0,0 +1,73 @@ +/* + * Copyright ©2015-2021 Jaemon. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.jaemon.dinger.core; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.core.ParameterNameDiscoverer; + +/** + * {@link ParameterNameDiscoverer} implementation that tries several discoverer + * delegates in succession. Those added first in the {@code addDiscoverer} method + * have highest priority. If one returns {@code null}, the next will be tried. + * + *

The default behavior is to return {@code null} if no discoverer matches. + * + * @author Jaemon + * @since 1.2 + * @see org.springframework.core.PrioritizedParameterNameDiscoverer + */ +public class PrioritizedParameterNameDiscoverer implements ParameterNameDiscoverer { + + private final List parameterNameDiscoverers = new LinkedList<>(); + + + /** + * Add a further {@link ParameterNameDiscoverer} delegate to the list of + * discoverers that this {@code PrioritizedParameterNameDiscoverer} checks. + * @param pnd pnd + */ + public void addDiscoverer(ParameterNameDiscoverer pnd) { + this.parameterNameDiscoverers.add(pnd); + } + + + @Override + public String[] getParameterNames(Method method) { + for (ParameterNameDiscoverer pnd : this.parameterNameDiscoverers) { + String[] result = pnd.getParameterNames(method); + if (result != null) { + return result; + } + } + return null; + } + + @Override + public String[] getParameterNames(Constructor ctor) { + for (ParameterNameDiscoverer pnd : this.parameterNameDiscoverers) { + String[] result = pnd.getParameterNames(ctor); + if (result != null) { + return result; + } + } + return null; + } + +} \ No newline at end of file diff --git a/src/main/java/com/github/jaemon/dinger/core/XmlDingerDefinitionResolver.java b/src/main/java/com/github/jaemon/dinger/core/XmlDingerDefinitionResolver.java new file mode 100644 index 0000000..a7447f5 --- /dev/null +++ b/src/main/java/com/github/jaemon/dinger/core/XmlDingerDefinitionResolver.java @@ -0,0 +1,153 @@ +/* + * Copyright ©2015-2021 Jaemon. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.jaemon.dinger.core; + +import com.github.jaemon.dinger.constant.DingerConstant; +import com.github.jaemon.dinger.core.annatations.DingerImageText; +import com.github.jaemon.dinger.core.annatations.DingerLink; +import com.github.jaemon.dinger.core.entity.DingerMethod; +import com.github.jaemon.dinger.core.entity.enums.MessageMainType; +import com.github.jaemon.dinger.core.entity.enums.MessageSubType; +import com.github.jaemon.dinger.core.entity.xml.BeanTag; +import com.github.jaemon.dinger.core.entity.xml.MessageTag; +import com.github.jaemon.dinger.exception.DingerException; +import com.github.jaemon.dinger.utils.XmlUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.io.Resource; +import org.springframework.util.FileCopyUtils; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.github.jaemon.dinger.constant.DingerConstant.SPOT_SEPERATOR; +import static com.github.jaemon.dinger.core.entity.enums.ExceptionEnum.*; +import static com.github.jaemon.dinger.core.entity.enums.ExceptionEnum.LINK_METHOD_PARAM_EXCEPTION; +import static com.github.jaemon.dinger.utils.DingerUtils.methodParamsGenericType; +import static com.github.jaemon.dinger.utils.DingerUtils.methodParamsType; + +/** + * dinger定义-xml方式 + * + * @author Jaemon + * @since 1.2 + */ +public class XmlDingerDefinitionResolver extends AbstractDingerDefinitionResolver { + private static final Logger log = LoggerFactory.getLogger(XmlDingerDefinitionResolver.class); + + @Override + public void resolver(Resource[] resources) { + boolean debugEnabled = log.isDebugEnabled(); + for (Resource resource : resources) { + if (!resource.isReadable()) { + if (debugEnabled) { + log.debug("Ignored because not readable: {} ", resource.getFilename()); + } + continue; + } + String xml; + try { + xml = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()), "UTF-8"); + } catch (IOException e) { + throw new DingerException(RESOURCE_CONFIG_EXCEPTION, resource.getFilename()); + } + xml = transferXml(xml); + BeanTag dingerBean = XmlUtils.xmlToJavaBean(xml, BeanTag.class); + if (dingerBean == null) { + if (debugEnabled) { + log.debug("dinger xml file: {} content is empty.", resource.getFilename()); + } + continue; + } + String namespace = dingerBean.getNamespace(); + Class dingerClass; + try { + dingerClass = Class.forName(namespace); + } catch (ClassNotFoundException e) { + throw new DingerException(DINER_XML_NAMESPACE_INVALID, namespace); + } + + Map dingerClassMethods = dingerClassMethods(dingerClass); + + DingerConfig dingerConfiguration = dingerConfiguration(dingerClass); + + List messages = dingerBean.getMessages(); + for (MessageTag message : messages) { + String methodName = message.getIdentityId(); + if (!dingerClassMethods.containsKey(methodName)) { + if (debugEnabled) { + log.debug("namespace={}, messageId={} undefined in dingerClass.", + namespace, methodName); + } + continue; + } + String dingerName = namespace + SPOT_SEPERATOR + methodName; + String messageSubType = message.getDingerType(); + if (!MessageSubType.contains(messageSubType)) { + throw new DingerException(DINER_XML_MSGTYPE_INVALID, dingerName, messageSubType); + } + String dingerDefinitionKey = MessageMainType.XML + SPOT_SEPERATOR + message.getDingerType(); + + registerDingerDefinition( + dingerName, message, + dingerDefinitionKey, + dingerConfiguration, + dingerClassMethods.get(methodName) + ); + } + } + } + + + /** + * 获取当前Dinger接口层方法的所有参数信息 + * + * @param dingerClass + * Dinger接口层类 + * @return + * 当前Dinger接口定义的方法的参数信息和泛型信息 + */ + protected Map dingerClassMethods(Class dingerClass) { + Method[] methods = dingerClass.getMethods(); + Map dingerMethodParams = new HashMap<>(); + for (Method method : methods) { + String methodName = method.getName(); + String methodAllName = dingerClass.getSimpleName() + DingerConstant.SPOT_SEPERATOR + methodName; + int[] paramTypes = null; + if (method.isAnnotationPresent(DingerImageText.class)) { + paramTypes = methodParamsGenericType(method, DingerImageText.clazz); + if (paramTypes.length != 1) { + throw new DingerException(IMAGETEXT_METHOD_PARAM_EXCEPTION, methodAllName); + } + } else if (method.isAnnotationPresent(DingerLink.class)) { + paramTypes = methodParamsType(method, DingerLink.clazz); + if (paramTypes.length != 1) { + throw new DingerException(LINK_METHOD_PARAM_EXCEPTION, methodAllName); + } + } + String[] methodParams = parameterNameDiscoverer.getParameterNames(method); + dingerMethodParams.put(methodName, new DingerMethod(methodAllName, methodParams, paramTypes)); + } + return dingerMethodParams; + } + + String transferXml(String sourceXml) { + return sourceXml.replaceAll("", ""); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/jaemon/dinger/core/annatations/DingerScan.java b/src/main/java/com/github/jaemon/dinger/core/annatations/DingerScan.java index 0e35e1f..fa595b2 100644 --- a/src/main/java/com/github/jaemon/dinger/core/annatations/DingerScan.java +++ b/src/main/java/com/github/jaemon/dinger/core/annatations/DingerScan.java @@ -16,6 +16,7 @@ package com.github.jaemon.dinger.core.annatations; import com.github.jaemon.dinger.core.spring.DingerScannerRegistrar; +import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.annotation.Import; import java.lang.annotation.*; @@ -31,5 +32,53 @@ @Documented @Import(DingerScannerRegistrar.class) public @interface DingerScan { - String[] basePackages(); + /** + * Alias for the {@link #basePackages()} attribute. Allows for more concise + * annotation declarations e.g.: + * {@code @DingerScan("org.my.pkg")} instead of {@code @DingerScan(basePackages = "org.my.pkg"})}. + * + * @return base package names + */ + String[] value() default {}; + + /** + * Base packages to scan for Dinger interfaces. Note that only interfaces + * with at least one method will be registered; concrete classes will be + * ignored. + * + * @return base package names for scanning dinger interface + */ + String[] basePackages() default {}; + + /** + * The {@link BeanNameGenerator} class to be used for naming detected components + * within the Spring container. + * + * @return the class of {@link BeanNameGenerator} + */ + Class nameGenerator() default BeanNameGenerator.class; + + /** + * This property specifies the annotation that the scanner will search for. + *

+ * The scanner will register all interfaces in the base package that also have + * the specified annotation. + *

+ * Note this can be combined with markerInterface. + * + * @return the annotation that the scanner will search for + */ + Class annotationClass() default Annotation.class; + + /** + * This property specifies the parent that the scanner will search for. + *

+ * The scanner will register all interfaces in the base package that also have + * the specified interface class as a parent. + *

+ * Note this can be combined with annotationClass. + * + * @return the parent that the scanner will search for + */ + Class markerInterface() default Class.class; } diff --git a/src/main/java/com/github/jaemon/dinger/core/entity/DingerMethod.java b/src/main/java/com/github/jaemon/dinger/core/entity/DingerMethod.java new file mode 100644 index 0000000..5c1d185 --- /dev/null +++ b/src/main/java/com/github/jaemon/dinger/core/entity/DingerMethod.java @@ -0,0 +1,45 @@ +package com.github.jaemon.dinger.core.entity; + +/** + * DingerMethod + * + * @author Jaemon + * @version 1.0 + */ +public class DingerMethod { + String methodName; + String[] methodParams; + int[] paramTypes; + + public DingerMethod(String methodName, String[] methodParams, int[] paramTypes) { + this.methodName = methodName; + this.methodParams = methodParams; + this.paramTypes = paramTypes; + } + + public boolean check() { + if (paramTypes == null) { + return false; + } + + int length = this.methodParams.length; + for (int index : paramTypes) { + if (index >= length) { + return true; + } + } + return false; + } + + public String getMethodName() { + return methodName; + } + + public String[] getMethodParams() { + return methodParams; + } + + public int[] getParamTypes() { + return paramTypes; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/jaemon/dinger/core/entity/DingerProperties.java b/src/main/java/com/github/jaemon/dinger/core/entity/DingerProperties.java index 9ef5c2a..65528af 100644 --- a/src/main/java/com/github/jaemon/dinger/core/entity/DingerProperties.java +++ b/src/main/java/com/github/jaemon/dinger/core/entity/DingerProperties.java @@ -24,7 +24,7 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.boot.context.properties.ConfigurationProperties; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import static com.github.jaemon.dinger.constant.DingerConstant.DINGER_PROP_PREFIX; @@ -48,7 +48,7 @@ public class DingerProperties implements InitializingBean { /** * dinger类型 key={@link DingerType}, value={@link Dinger}, 必填 */ - private Map dingers = new HashMap<>(); + private Map dingers = new LinkedHashMap<>(); /** * 项目名称, 必填 eg: ${spring.application.name} @@ -250,7 +250,9 @@ public void afterPropertiesSet() throws Exception { if (defaultDinger == null) { defaultDinger = dingerType; - log.warn("defaultDinger undeclared and use fisrt dingers dingerType, defaultDinger={}", defaultDinger); + if (log.isDebugEnabled()) { + log.debug("defaultDinger undeclared and use first dingers dingerType, defaultDinger={}.", defaultDinger); + } } } diff --git a/src/main/java/com/github/jaemon/dinger/core/spring/DingerFactoryBean.java b/src/main/java/com/github/jaemon/dinger/core/spring/DingerFactoryBean.java index c165fee..7e11ce9 100644 --- a/src/main/java/com/github/jaemon/dinger/core/spring/DingerFactoryBean.java +++ b/src/main/java/com/github/jaemon/dinger/core/spring/DingerFactoryBean.java @@ -15,11 +15,7 @@ */ package com.github.jaemon.dinger.core.spring; -import com.github.jaemon.dinger.core.DingerRobot; -import com.github.jaemon.dinger.core.DingerSession; -import com.github.jaemon.dinger.core.entity.DingerProperties; import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.annotation.Autowired; /** * DingerFactoryBean @@ -27,13 +23,11 @@ * @author Jaemon * @since 1.0 */ -public class DingerFactoryBean implements FactoryBean { +public class DingerFactoryBean extends DingerSessionSupport implements FactoryBean { private Class dingerInterface; - @Autowired - private DingerRobot dingerRobot; - @Autowired - private DingerProperties dingerProperties; + public DingerFactoryBean() { + } public DingerFactoryBean(Class dingerInterface) { this.dingerInterface = dingerInterface; @@ -41,7 +35,7 @@ public DingerFactoryBean(Class dingerInterface) { @Override public T getObject() throws Exception { - return new DingerSession(dingerRobot, dingerProperties).getDinger(this.dingerInterface); + return getDingerSession().getDinger(this.dingerInterface); } @Override diff --git a/src/main/java/com/github/jaemon/dinger/core/spring/DingerScannerRegistrar.java b/src/main/java/com/github/jaemon/dinger/core/spring/DingerScannerRegistrar.java index 2b01822..2881c20 100644 --- a/src/main/java/com/github/jaemon/dinger/core/spring/DingerScannerRegistrar.java +++ b/src/main/java/com/github/jaemon/dinger/core/spring/DingerScannerRegistrar.java @@ -15,24 +15,27 @@ */ package com.github.jaemon.dinger.core.spring; +import com.github.jaemon.dinger.core.ClassPathDingerScanner; +import com.github.jaemon.dinger.core.DefaultDingerDefinitionResolver; import com.github.jaemon.dinger.core.annatations.DingerScan; import com.github.jaemon.dinger.core.entity.enums.ExceptionEnum; +import com.github.jaemon.dinger.exception.DingerAnalysisException; import com.github.jaemon.dinger.exception.DingerException; -import com.github.jaemon.dinger.listeners.DingerListenersProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; -import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.type.AnnotationMetadata; +import org.springframework.util.StringUtils; +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; - -import static com.github.jaemon.dinger.utils.PackageUtils.classNames; +import java.util.stream.Collectors; /** * DingerScannerRegistrar @@ -41,77 +44,68 @@ * @since 1.0 */ public class DingerScannerRegistrar - extends DingerListenersProperty - implements ImportBeanDefinitionRegistrar, Ordered + extends DefaultDingerDefinitionResolver + implements ImportBeanDefinitionRegistrar { private static final Logger log = LoggerFactory.getLogger(DingerScannerRegistrar.class); @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { - boolean isDebugEnabled = log.isDebugEnabled(); - log.info("ready to execute dingerScanner..."); - try { - List> dingerClasses = DingerListenersProperty.dingerClasses(); - - if (!dingerClasses.isEmpty()) { - registerBeanDefinition(registry, dingerClasses); - } else { - if (isDebugEnabled) { - log.debug("dinger class is empty in primarySources, ready to reanalysis from DingerScan."); - } - - if (!importingClassMetadata.hasAnnotation(DingerScan.class.getName())) { - log.warn("import class can't find DingerScan annotation."); - return; - } - AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap( - importingClassMetadata.getAnnotationAttributes(DingerScan.class.getName()) - ); - - String[] basePackages = annoAttrs.getStringArray("basePackages"); - // traversing all classes under the package: basePackage - for (String basePackage : basePackages) { - classNames(basePackage, dingerClasses, true); - } - - // just to obtain interface that defined by Dinger annotation, Deprecated -// classNames(DingerUtils.classPackageName(importingClassMetadata.getClassName()), dingerClasses, true, Dinger.class); - - if (!dingerClasses.isEmpty()) { - registerBeanDefinition(registry, dingerClasses); - } else { - throw new DingerException("dinger class is empty.", ExceptionEnum.CONFIG_ERROR); - } - } - } finally { -// ApplicationEventTimeTable.emptyDingerClasses(); - } + AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap( + importingClassMetadata.getAnnotationAttributes(DingerScan.class.getName()) + ); + if (annoAttrs != null) { + registerBeanDefinitions(annoAttrs, registry); + } } - /** - * registerBeanDefinition - * - * @param registry registry - * @param dingerClasses dingerClasses - */ - private void registerBeanDefinition(BeanDefinitionRegistry registry, List> dingerClasses) { - for (Class dingerClass : dingerClasses) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(DingerFactoryBean.class); - AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); - beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(dingerClass); - beanDefinition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE); - // 注册到 BeanDefinitionRegistry - registry.registerBeanDefinition(dingerClass.getSimpleName(), beanDefinition); - - if (log.isDebugEnabled()) { - log.debug("the beanDefinition[{}] is already registered.", dingerClass.getSimpleName()); - } + void registerBeanDefinitions(AnnotationAttributes annoAttrs, BeanDefinitionRegistry registry) { + ClassPathDingerScanner scanner = new ClassPathDingerScanner(registry); + + Class annotationClass = annoAttrs.getClass("annotationClass"); + if (!Annotation.class.equals(annotationClass)) { + scanner.setAnnotationClass(annotationClass); } - } - @Override - public int getOrder() { - return LOWEST_PRECEDENCE - 2; + Class markerInterface = annoAttrs.getClass("markerInterface"); + if (!Class.class.equals(markerInterface)) { + scanner.setMarkerInterface(markerInterface); + } + + Class generatorClass = annoAttrs.getClass("nameGenerator"); + if (!BeanNameGenerator.class.equals(generatorClass)) { + scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass)); + } + + List basePackages = new ArrayList<>(); + + basePackages.addAll( + Arrays.stream(annoAttrs.getStringArray("value")) + .filter(StringUtils::hasText) + .collect(Collectors.toList()) + ); + + basePackages.addAll( + Arrays.stream(annoAttrs.getStringArray("basePackages")) + .filter(StringUtils::hasText) + .collect(Collectors.toList()) + ); + + + scanner.registerFilters(); + scanner.doScan( + StringUtils.toStringArray(basePackages) + ); + + try { + resolver(scanner.getDingerClasses()); + dingerClasses = scanner.getDingerClasses(); + } catch (DingerException ex) { + throw new DingerAnalysisException(ex.getPairs(), ex.getMessage()); + } catch (Exception ex) { + throw new DingerException(ex, ExceptionEnum.UNKNOWN); + } } + } \ No newline at end of file diff --git a/src/main/java/com/github/jaemon/dinger/core/spring/DingerSessionSupport.java b/src/main/java/com/github/jaemon/dinger/core/spring/DingerSessionSupport.java new file mode 100644 index 0000000..a9f1505 --- /dev/null +++ b/src/main/java/com/github/jaemon/dinger/core/spring/DingerSessionSupport.java @@ -0,0 +1,52 @@ +/* + * Copyright ©2015-2021 Jaemon. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.jaemon.dinger.core.spring; + +import com.github.jaemon.dinger.core.DingerRobot; +import com.github.jaemon.dinger.core.DingerSession; +import com.github.jaemon.dinger.core.entity.DingerProperties; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * DingerSessionSupport + * + * @author Jaemon + * @version 1.2 + */ +public abstract class DingerSessionSupport implements InitializingBean { + protected DingerSession dingerSession; + + @Autowired + private DingerRobot dingerRobot; + @Autowired + private DingerProperties dingerProperties; + + public void setDingerSession() { + if (dingerSession == null) { + this.dingerSession = new DingerSession(dingerRobot, dingerProperties); + } + } + + public DingerSession getDingerSession() { + return this.dingerSession; + } + + @Override + public void afterPropertiesSet() throws Exception { + setDingerSession(); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/jaemon/dinger/listeners/DingerListenersProperty.java b/src/main/java/com/github/jaemon/dinger/listeners/DingerListenersProperty.java index 1192d58..5b5fd0b 100644 --- a/src/main/java/com/github/jaemon/dinger/listeners/DingerListenersProperty.java +++ b/src/main/java/com/github/jaemon/dinger/listeners/DingerListenersProperty.java @@ -15,6 +15,7 @@ */ package com.github.jaemon.dinger.listeners; +import com.github.jaemon.dinger.core.DingerConfig; import com.github.jaemon.dinger.core.entity.enums.DingerType; import java.util.*; @@ -28,17 +29,13 @@ */ public class DingerListenersProperty { /** - * primarySources + * dingerClasses */ - static Set> primarySources = new HashSet<>(); + protected static List> dingerClasses = new ArrayList<>(); /** - * dingerClasses + * Dinger默认的DingerConfig */ - static List> dingerClasses = new ArrayList<>(); - - protected static Set> primarySources() { - return primarySources; - } + protected static Map defaultDingerConfigs = new HashMap<>(); protected static List> dingerClasses() { return dingerClasses; @@ -56,8 +53,8 @@ protected static void emptyDingerClasses() { } protected static void clear() { - DingerListenersProperty.primarySources().clear(); - DingerListenersProperty.dingerClasses().clear(); + dingerClasses.clear(); + defaultDingerConfigs.clear(); } } \ No newline at end of file diff --git a/src/main/java/com/github/jaemon/dinger/listeners/DingerXmlPreparedEvent.java b/src/main/java/com/github/jaemon/dinger/listeners/DingerXmlPreparedEvent.java index a3fb06c..76c7aef 100644 --- a/src/main/java/com/github/jaemon/dinger/listeners/DingerXmlPreparedEvent.java +++ b/src/main/java/com/github/jaemon/dinger/listeners/DingerXmlPreparedEvent.java @@ -15,25 +15,16 @@ */ package com.github.jaemon.dinger.listeners; -import com.github.jaemon.dinger.core.DingerDefinitionResolver; import com.github.jaemon.dinger.core.annatations.DingerScan; -import com.github.jaemon.dinger.core.entity.enums.DingerType; -import com.github.jaemon.dinger.core.entity.enums.ExceptionEnum; -import com.github.jaemon.dinger.exception.DingerAnalysisException; -import com.github.jaemon.dinger.exception.DingerException; -import com.github.jaemon.dinger.utils.DingerUtils; -import com.github.jaemon.dinger.core.DingerConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringBootVersion; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.context.ApplicationListener; -import org.springframework.core.env.Environment; import java.util.HashSet; import java.util.Set; -import static com.github.jaemon.dinger.constant.DingerConstant.SPOT_SEPERATOR; /** * DingerXmlPreparedEvent @@ -41,8 +32,8 @@ * @author Jaemon * @since 1.0 */ +@Deprecated public class DingerXmlPreparedEvent - extends DingerDefinitionResolver implements ApplicationListener { private static final Logger log = LoggerFactory.getLogger(DingerXmlPreparedEvent.class); @@ -50,15 +41,6 @@ public class DingerXmlPreparedEvent public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { log.info("ready to execute dinger analysis."); loadPrimarySources(event); - registerDefaultDingerConfig(event.getEnvironment()); - - try { - DingerListenersProperty.dingerClasses = doAnalysis(event); - } catch (DingerException ex) { - throw new DingerAnalysisException(ex.getPairs(), ex.getMessage()); - } catch (Exception ex) { - throw new DingerException(ex, ExceptionEnum.UNKNOWN); - } } /** @@ -83,60 +65,5 @@ private void loadPrimarySources(ApplicationEnvironmentPreparedEvent event) { } } } - DingerListenersProperty.primarySources = primarySources; - } - - /** - * 注册默认的Dinger机器人信息, 即配置文件内容 - * - * @param environment - * environment - */ - private void registerDefaultDingerConfig(Environment environment) { - for (DingerType dingerType : enabledDingerTypes) { - String dingers = DINGER_PROPERTIES_PREFIX + "dingers" + SPOT_SEPERATOR + dingerType.name().toLowerCase() + SPOT_SEPERATOR; - String tokenIdProp = dingers + "token-id"; - String secretProp = dingers + "secret"; - String decryptProp = dingers + "decrypt"; - String decryptKeyProp = dingers + "decryptKey"; - String asyncExecuteProp = dingers + "async"; - - if (DingerUtils.isEmpty(tokenIdProp)) { - if (log.isDebugEnabled()) { - log.debug("dinger={} is not open.", dingerType); - } - continue; - } - String tokenId = environment.getProperty(tokenIdProp); - String secret = environment.getProperty(secretProp); - boolean decrypt = getProperty(environment, decryptProp); - boolean async = getProperty(environment, asyncExecuteProp); - DingerConfig defaultDingerConfig = DingerConfig.instance(tokenId); - defaultDingerConfig.setDingerType(dingerType); - defaultDingerConfig.setSecret(secret); - if (decrypt) { - defaultDingerConfig.setDecryptKey( - environment.getProperty(decryptKeyProp) - ); - } - defaultDingerConfig.setAsyncExecute(async); - - defaultDingerConfig.check(); - defaultDingerConfigs.put(dingerType, defaultDingerConfig); - } - } - - /** - * getProperty - * - * @param environment environment - * @param prop prop - * @return prop value - */ - private boolean getProperty(Environment environment, String prop) { - if (environment.getProperty(prop) != null) { - return environment.getProperty(prop, boolean.class); - } - return false; } } \ No newline at end of file diff --git a/src/main/java/com/github/jaemon/dinger/multi/MultiDingerAlgorithmInjectRegister.java b/src/main/java/com/github/jaemon/dinger/multi/MultiDingerAlgorithmInjectRegister.java index e63de0f..47891c3 100644 --- a/src/main/java/com/github/jaemon/dinger/multi/MultiDingerAlgorithmInjectRegister.java +++ b/src/main/java/com/github/jaemon/dinger/multi/MultiDingerAlgorithmInjectRegister.java @@ -35,7 +35,6 @@ import java.lang.reflect.Field; import java.util.*; -import static com.github.jaemon.dinger.constant.DingerConstant.SPOT_SEPERATOR; import static com.github.jaemon.dinger.core.entity.enums.ExceptionEnum.ALGORITHM_FIELD_INJECT_FAILED; /** diff --git a/src/main/java/com/github/jaemon/dinger/multi/MultiDingerScannerRegistrar.java b/src/main/java/com/github/jaemon/dinger/multi/MultiDingerScannerRegistrar.java index 539bdb9..0a949b9 100644 --- a/src/main/java/com/github/jaemon/dinger/multi/MultiDingerScannerRegistrar.java +++ b/src/main/java/com/github/jaemon/dinger/multi/MultiDingerScannerRegistrar.java @@ -43,10 +43,7 @@ import org.springframework.core.type.AnnotationMetadata; import org.springframework.objenesis.instantiator.util.ClassUtils; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import static com.github.jaemon.dinger.constant.DingerConstant.SPOT_SEPERATOR; import static com.github.jaemon.dinger.core.entity.enums.ExceptionEnum.MULTIDINGER_ALGORITHM_EXCEPTION; @@ -78,8 +75,6 @@ public class MultiDingerScannerRegistrar @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { - log.info("ready to execute multiDingerScanner..."); - try { doScanAndRegister(importingClassMetadata, registry); } catch (DingerException ex) { @@ -150,6 +145,7 @@ private void doScanAndRegister(AnnotationMetadata importingClassMetadata, BeanDe private void multiDingerHandler(BeanDefinitionRegistry registry, List> dingerClasses) { boolean debugEnabled = log.isDebugEnabled(); + int valid = 0; for (Class dingerClass : dingerClasses) { if (dingerClass.isAnnotationPresent(MultiHandler.class)) { MultiHandler multiDinger = dingerClass.getAnnotation(MultiHandler.class); @@ -172,8 +168,13 @@ private void multiDingerHandler(BeanDefinitionRegistry registry, List> log.debug("regiseter multi dinger for dingerClass={} and dingerConfigHandler={}.", dingerClass.getSimpleName(), beanName); } + valid++; } } + + if (valid == 0) { + log.warn("enable global multi dinger but none dinger interface be decorated with @MultiHandler."); + } } @@ -200,6 +201,7 @@ private void registerHandler(BeanDefinitionRegistry registry, DingerType dinger, Class algorithm = dingerConfigHandler.algorithmHandler(); // if empty? use default dinger config List dingerConfigs = dingerConfigHandler.dingerConfigs(); + dingerConfigs = dingerConfigs == null ? new ArrayList<>() : dingerConfigs; if (algorithm == null) { throw new DingerException(MULTIDINGER_ALGORITHM_EXCEPTION, dingerConfigHandlerClassName); @@ -226,8 +228,6 @@ key, new MultiDingerConfig(algorithmHandler, dingerConfigs) ); } else { BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(algorithm); -// beanDefinitionBuilder.addPropertyReference("dingerService", "dingerService"); -// beanDefinitionBuilder.addPropertyValue("dingerName", "Jaemon"); AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition(); beanDefinition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE); // 将当前算法注册到Spring容器中 diff --git a/src/main/resources/META-INF/spring.factories b/src/main/resources/META-INF/spring.factories index 0d21228..8302e3c 100644 --- a/src/main/resources/META-INF/spring.factories +++ b/src/main/resources/META-INF/spring.factories @@ -7,5 +7,4 @@ com.github.jaemon.dinger.config.DingerThreadPoolConfig # Application Listeners org.springframework.context.ApplicationListener=\ -com.github.jaemon.dinger.listeners.DingerXmlPreparedEvent,\ com.github.jaemon.dinger.listeners.ExitEventListener