From c3e6c6537d3521e4f659b99eeda4e061b11b7647 Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Mon, 10 Apr 2023 12:54:35 +0800 Subject: [PATCH 01/17] Support native with springboot3 Signed-off-by: crazyhzm --- .licenserc.yaml | 4 +- .../dubbo/common/aot/NativeDetector.java | 34 + .../common/extension/ExtensionLoader.java | 36 +- .../common/json/{JSON.java => JsonUtil.java} | 5 +- ...SONImpl.java => AbstractJsonUtilImpl.java} | 4 +- .../dubbo/common/json/impl/FastJson2Impl.java | 2 +- .../dubbo/common/json/impl/FastJsonImpl.java | 2 +- .../dubbo/common/json/impl/GsonImpl.java | 2 +- .../dubbo/common/json/impl/JacksonImpl.java | 2 +- .../utils/ClassLoaderResourceLoader.java | 3 +- .../apache/dubbo/common/utils/JsonUtils.java | 32 +- .../dubbo/config/AbstractInterfaceConfig.java | 4 +- .../org.apache.dubbo.common.json.JsonUtil | 4 + .../dubbo/config/spring/ReferenceBean.java | 37 +- .../spring/aot/AotWithSpringDetector.java | 43 + .../AbstractAnnotationBeanPostProcessor.java | 15 +- .../ServiceAnnotationPostProcessor.java | 20 +- .../context/DubboConfigBeanInitializer.java | 3 +- .../context/DubboContextPostProcessor.java | 79 ++ .../DubboInfraBeanRegisterPostProcessor.java | 17 - .../context/DubboSpringInitializer.java | 9 +- .../DubboClassPathBeanDefinitionScanner.java | 5 +- .../DubboComponentScanRegistrar.java | 4 +- .../reference/ReferenceBeanSupport.java | 8 +- .../AnnotationBeanDefinitionParser.java | 3 +- .../spring/schema/DubboNamespaceHandler.java | 5 +- .../config/spring/util/DubboBeanUtils.java | 23 +- .../config/spring/util/SpringCompatUtils.java | 29 +- dubbo-config/dubbo-config-spring6/pom.xml | 84 ++ ...nceAnnotationWithAotBeanPostProcessor.java | 841 ++++++++++++++++++ ...ServiceAnnotationWithAotPostProcessor.java | 98 ++ .../factory/aot/AutowiredElementResolver.java | 77 ++ .../aot/ReferencedFieldValueResolver.java | 210 +++++ .../ReferencedMethodArgumentsResolver.java | 222 +++++ .../DubboInfraBeanRegisterPostProcessor.java | 43 + dubbo-config/pom.xml | 1 + dubbo-dependencies-bom/pom.xml | 2 +- dubbo-distribution/dubbo-all/pom.xml | 14 + dubbo-metadata/dubbo-metadata-api/pom.xml | 6 + .../aot/MetadataProxyDescriberRegistrar.java | 43 + ...adataReflectionTypeDescriberRegistrar.java | 52 ++ ...ache.dubbo.aot.api.ProxyDescriberRegistrar | 1 + ...o.aot.api.ReflectionTypeDescriberRegistrar | 1 + dubbo-metrics/dubbo-metrics-default/pom.xml | 7 + ...tricsReflectionTypeDescriberRegistrar.java | 43 + ...o.aot.api.ReflectionTypeDescriberRegistrar | 1 + ...e.dubbo.metrics.collector.MetricsCollector | 3 + .../ConditionalDescriber.java | 2 +- .../aot/{generate => api}/ExecutableMode.java | 2 +- .../aot/{generate => api}/FieldDescriber.java | 2 +- .../dubbo/aot/api/JdkProxyDescriber.java | 62 ++ .../aot/{generate => api}/MemberCategory.java | 2 +- .../{generate => api}/MemberDescriber.java | 2 +- .../aot/api/ProxyDescriberRegistrar.java | 26 + .../api/ReflectionTypeDescriberRegistrar.java | 26 + .../ResourceBundleDescriber.java | 2 +- .../aot/api/ResourceDescriberRegistrar.java | 28 + .../ResourcePatternDescriber.java | 2 +- .../aot/{generate => api}/TypeDescriber.java | 4 +- .../dubbo/aot/generate/AotProcessor.java | 29 +- .../aot/generate/ExecutableDescriber.java | 3 + .../apache/dubbo/aot/generate/JarScanner.java | 1 - .../generate/NativeConfigurationWriter.java | 11 +- .../ProxyConfigMetadataRepository.java | 50 ++ .../dubbo/aot/generate/ProxyConfigWriter.java | 51 ++ .../ReflectConfigMetadataRepository.java | 17 +- .../aot/generate/ReflectionConfigWriter.java | 5 + .../ResourceConfigMetadataRepository.java | 3 + .../aot/generate/ResourceConfigWriter.java | 4 + .../ResourcePatternDescriberTest.java | 1 + dubbo-plugin/dubbo-qos/pom.xml | 6 + .../QosReflectionTypeDescriberRegistrar.java | 44 + ...o.aot.api.ReflectionTypeDescriberRegistrar | 1 + dubbo-registry/dubbo-registry-api/pom.xml | 6 + .../RegistryScopeModelInitializer.java | 2 + ...istryReflectionTypeDescriberRegistrar.java | 46 + .../client/metadata/MetadataUtils.java | 5 + ...o.aot.api.ReflectionTypeDescriberRegistrar | 1 + ...eeperReflectionTypeDescriberRegistrar.java | 48 + ...o.aot.api.ReflectionTypeDescriberRegistrar | 1 + dubbo-remoting/dubbo-remoting-netty4/pom.xml | 6 + ...etty4ReflectionTypeDescriberRegistrar.java | 50 ++ ...o.aot.api.ReflectionTypeDescriberRegistrar | 1 + .../dubbo-remoting-zookeeper-curator5/pom.xml | 6 + ...eeperReflectionTypeDescriberRegistrar.java | 54 ++ ...o.aot.api.ReflectionTypeDescriberRegistrar | 1 + .../dubbo-remoting-zookeeper/pom.xml | 7 + ...eeperReflectionTypeDescriberRegistrar.java | 50 ++ ...o.aot.api.ReflectionTypeDescriberRegistrar | 1 + .../autoconfigure/DubboAutoConfiguration.java | 13 +- pom.xml | 4 +- 91 files changed, 2741 insertions(+), 130 deletions(-) create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/aot/NativeDetector.java rename dubbo-common/src/main/java/org/apache/dubbo/common/json/{JSON.java => JsonUtil.java} (95%) rename dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/{AbstractJSONImpl.java => AbstractJsonUtilImpl.java} (98%) create mode 100644 dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.json.JsonUtil create mode 100644 dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/aot/AotWithSpringDetector.java create mode 100644 dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboContextPostProcessor.java create mode 100644 dubbo-config/dubbo-config-spring6/pom.xml create mode 100644 dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java create mode 100644 dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java create mode 100644 dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/AutowiredElementResolver.java create mode 100644 dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedFieldValueResolver.java create mode 100644 dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedMethodArgumentsResolver.java create mode 100644 dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/context/DubboInfraBeanRegisterPostProcessor.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/aot/MetadataProxyDescriberRegistrar.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/aot/MetadataReflectionTypeDescriberRegistrar.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ProxyDescriberRegistrar create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar create mode 100644 dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/aot/DefaultMetricsReflectionTypeDescriberRegistrar.java create mode 100644 dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar create mode 100644 dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metrics.collector.MetricsCollector rename dubbo-native/src/main/java/org/apache/dubbo/aot/{generate => api}/ConditionalDescriber.java (96%) rename dubbo-native/src/main/java/org/apache/dubbo/aot/{generate => api}/ExecutableMode.java (97%) rename dubbo-native/src/main/java/org/apache/dubbo/aot/{generate => api}/FieldDescriber.java (96%) create mode 100644 dubbo-native/src/main/java/org/apache/dubbo/aot/api/JdkProxyDescriber.java rename dubbo-native/src/main/java/org/apache/dubbo/aot/{generate => api}/MemberCategory.java (98%) rename dubbo-native/src/main/java/org/apache/dubbo/aot/{generate => api}/MemberDescriber.java (96%) create mode 100644 dubbo-native/src/main/java/org/apache/dubbo/aot/api/ProxyDescriberRegistrar.java create mode 100644 dubbo-native/src/main/java/org/apache/dubbo/aot/api/ReflectionTypeDescriberRegistrar.java rename dubbo-native/src/main/java/org/apache/dubbo/aot/{generate => api}/ResourceBundleDescriber.java (98%) create mode 100644 dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceDescriberRegistrar.java rename dubbo-native/src/main/java/org/apache/dubbo/aot/{generate => api}/ResourcePatternDescriber.java (97%) rename dubbo-native/src/main/java/org/apache/dubbo/aot/{generate => api}/TypeDescriber.java (95%) create mode 100644 dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigMetadataRepository.java create mode 100644 dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigWriter.java create mode 100644 dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/aot/QosReflectionTypeDescriberRegistrar.java create mode 100644 dubbo-plugin/dubbo-qos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar create mode 100644 dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/aot/RegistryReflectionTypeDescriberRegistrar.java create mode 100644 dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar create mode 100644 dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/aot/ZookeeperReflectionTypeDescriberRegistrar.java create mode 100644 dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar create mode 100644 dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/aot/Netty4ReflectionTypeDescriberRegistrar.java create mode 100644 dubbo-remoting/dubbo-remoting-netty4/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar create mode 100644 dubbo-remoting/dubbo-remoting-zookeeper-curator5/src/main/java/org/apache/dubbo/remoting/zookeeper/curator5/aot/Curator5ZookeeperReflectionTypeDescriberRegistrar.java create mode 100644 dubbo-remoting/dubbo-remoting-zookeeper-curator5/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar create mode 100644 dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/aot/CuratorZookeeperReflectionTypeDescriberRegistrar.java create mode 100644 dubbo-remoting/dubbo-remoting-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar diff --git a/.licenserc.yaml b/.licenserc.yaml index 5b8980c95ef..f793f30a4d4 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -96,8 +96,8 @@ header: - 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/RunArguments.java' - 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/RunProcess.java' - 'dubbo-native/src/main/java/org/apache/dubbo/aot/generate/BasicJsonWriter.java' - - 'dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableMode.java' - - 'dubbo-native/src/main/java/org/apache/dubbo/aot/generate/MemberCategory.java' + - 'dubbo-native/src/main/java/org/apache/dubbo/aot/api/ExecutableMode.java' + - 'dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java' comment: on-failure diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/aot/NativeDetector.java b/dubbo-common/src/main/java/org/apache/dubbo/common/aot/NativeDetector.java new file mode 100644 index 00000000000..df8bec0fab3 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/aot/NativeDetector.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.common.aot; + + +public abstract class NativeDetector { + + /** + * See https://github.com/oracle/graal/blob/master/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/ImageInfo.java + */ + private static final boolean IMAGE_CODE = (System.getProperty("org.graalvm.nativeimage.imagecode") != null); + + /** + * Returns {@code true} if invoked in the context of image building or during image runtime, else {@code false}. + */ + public static boolean inNativeImage() { + return IMAGE_CODE; + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java index 5f000daa8a4..02af9b73db6 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java @@ -18,6 +18,7 @@ import org.apache.dubbo.common.Extension; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.aot.NativeDetector; import org.apache.dubbo.common.beans.support.InstantiationStrategy; import org.apache.dubbo.common.context.Lifecycle; import org.apache.dubbo.common.extension.support.ActivateComparator; @@ -33,7 +34,6 @@ import org.apache.dubbo.common.utils.ConcurrentHashSet; import org.apache.dubbo.common.utils.ConfigUtils; import org.apache.dubbo.common.utils.Holder; -import org.apache.dubbo.common.utils.NativeUtils; import org.apache.dubbo.common.utils.ReflectUtils; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.rpc.model.ApplicationModel; @@ -107,8 +107,8 @@ public class ExtensionLoader { private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger( ExtensionLoader.class); - private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*"); - private static final String SPECIAL_SPI_PROPERTIES = "special_spi.properties"; + private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*"); + private static final String SPECIAL_SPI_PROPERTIES = "special_spi.properties"; private final ConcurrentMap, Object> extensionInstances = new ConcurrentHashMap<>(64); @@ -120,17 +120,17 @@ public class ExtensionLoader { private final Holder>> cachedClasses = new Holder<>(); - private final Map cachedActivates = Collections.synchronizedMap( + private final Map cachedActivates = Collections.synchronizedMap( new LinkedHashMap<>()); - private final Map> cachedActivateGroups = Collections.synchronizedMap( + private final Map> cachedActivateGroups = Collections.synchronizedMap( new LinkedHashMap<>()); - private final Map cachedActivateValues = Collections.synchronizedMap( + private final Map cachedActivateValues = Collections.synchronizedMap( new LinkedHashMap<>()); - private final ConcurrentMap> cachedInstances = new ConcurrentHashMap<>(); - private final Holder cachedAdaptiveInstance = new Holder<>(); - private volatile Class cachedAdaptiveClass = null; - private String cachedDefaultName; - private volatile Throwable createAdaptiveInstanceError; + private final ConcurrentMap> cachedInstances = new ConcurrentHashMap<>(); + private final Holder cachedAdaptiveInstance = new Holder<>(); + private volatile Class cachedAdaptiveClass = null; + private String cachedDefaultName; + private volatile Throwable createAdaptiveInstanceError; private Set> cachedWrapperClasses; @@ -148,13 +148,13 @@ public class ExtensionLoader { /** * Record all unacceptable exceptions when using SPI */ - private final Set unacceptableExceptions = new ConcurrentHashSet<>(); - private final ExtensionDirector extensionDirector; + private final Set unacceptableExceptions = new ConcurrentHashSet<>(); + private final ExtensionDirector extensionDirector; private final List extensionPostProcessors; - private InstantiationStrategy instantiationStrategy; - private final ActivateComparator activateComparator; - private final ScopeModel scopeModel; - private final AtomicBoolean destroyed = new AtomicBoolean(); + private InstantiationStrategy instantiationStrategy; + private final ActivateComparator activateComparator; + private final ScopeModel scopeModel; + private final AtomicBoolean destroyed = new AtomicBoolean(); public static void setLoadingStrategies(LoadingStrategy... strategies) { if (ArrayUtils.isNotEmpty(strategies)) { @@ -1409,7 +1409,7 @@ private Class createAdaptiveExtensionClass() { // Adaptive Classes' ClassLoader should be the same with Real SPI interface classes' ClassLoader ClassLoader classLoader = type.getClassLoader(); try { - if (NativeUtils.isNative()) { + if (NativeDetector.inNativeImage()) { return classLoader.loadClass(type.getName() + "$Adaptive"); } } catch (Throwable ignore) { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSON.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JsonUtil.java similarity index 95% rename from dubbo-common/src/main/java/org/apache/dubbo/common/json/JSON.java rename to dubbo-common/src/main/java/org/apache/dubbo/common/json/JsonUtil.java index 7eddf3d988b..cc94b77ebab 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSON.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JsonUtil.java @@ -16,11 +16,14 @@ */ package org.apache.dubbo.common.json; +import org.apache.dubbo.common.extension.SPI; + import java.lang.reflect.Type; import java.util.List; import java.util.Map; -public interface JSON { +@SPI +public interface JsonUtil { boolean isSupport(); T toJavaObject(String json, Type type); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/AbstractJSONImpl.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/AbstractJsonUtilImpl.java similarity index 98% rename from dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/AbstractJSONImpl.java rename to dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/AbstractJsonUtilImpl.java index 2ebec0c9a42..7823353cf1a 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/AbstractJSONImpl.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/AbstractJsonUtilImpl.java @@ -16,7 +16,7 @@ */ package org.apache.dubbo.common.json.impl; -import org.apache.dubbo.common.json.JSON; +import org.apache.dubbo.common.json.JsonUtil; import org.apache.dubbo.common.utils.CollectionUtils; import java.util.HashMap; @@ -24,7 +24,7 @@ import java.util.List; import java.util.Map; -public abstract class AbstractJSONImpl implements JSON { +public abstract class AbstractJsonUtilImpl implements JsonUtil { @Override public boolean isSupport() { try { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJson2Impl.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJson2Impl.java index 88f8920e37c..f12e76a2920 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJson2Impl.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJson2Impl.java @@ -21,7 +21,7 @@ import java.lang.reflect.Type; import java.util.List; -public class FastJson2Impl extends AbstractJSONImpl { +public class FastJson2Impl extends AbstractJsonUtilImpl { @Override public T toJavaObject(String json, Type type) { return com.alibaba.fastjson2.JSON.parseObject(json, type); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJsonImpl.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJsonImpl.java index 9397183f61a..d9560ed206f 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJsonImpl.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJsonImpl.java @@ -21,7 +21,7 @@ import java.lang.reflect.Type; import java.util.List; -public class FastJsonImpl extends AbstractJSONImpl { +public class FastJsonImpl extends AbstractJsonUtilImpl { @Override public T toJavaObject(String json, Type type) { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/GsonImpl.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/GsonImpl.java index e779be06633..03bca670c93 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/GsonImpl.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/GsonImpl.java @@ -22,7 +22,7 @@ import java.lang.reflect.Type; import java.util.List; -public class GsonImpl extends AbstractJSONImpl { +public class GsonImpl extends AbstractJsonUtilImpl { // weak reference of com.google.gson.Gson, prevent throw exception when init private volatile Object gsonCache = null; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/JacksonImpl.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/JacksonImpl.java index dc6f6e380bd..29327feb47d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/JacksonImpl.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/JacksonImpl.java @@ -26,7 +26,7 @@ import java.lang.reflect.Type; import java.util.List; -public class JacksonImpl extends AbstractJSONImpl { +public class JacksonImpl extends AbstractJsonUtilImpl { private ObjectMapper objectMapper = new ObjectMapper(); private volatile Object jacksonCache = null; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassLoaderResourceLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassLoaderResourceLoader.java index 8328cd727c2..d8003d41c73 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassLoaderResourceLoader.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassLoaderResourceLoader.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.common.utils; +import org.apache.dubbo.common.aot.NativeDetector; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.resource.GlobalResourcesRepository; @@ -78,7 +79,7 @@ public static Set loadResources(String fileName, ClassLoader currentClassLo Enumeration urls; try { urls = currentClassLoader.getResources(fileName); - boolean isNative = NativeUtils.isNative(); + boolean isNative = NativeDetector.inNativeImage(); if (urls != null) { while (urls.hasMoreElements()) { URL url = urls.nextElement(); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/JsonUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/JsonUtils.java index 395bfe4677a..60cd13b72a4 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/JsonUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/JsonUtils.java @@ -17,7 +17,7 @@ package org.apache.dubbo.common.utils; import org.apache.dubbo.common.constants.CommonConstants; -import org.apache.dubbo.common.json.JSON; +import org.apache.dubbo.common.json.JsonUtil; import org.apache.dubbo.common.json.impl.FastJson2Impl; import org.apache.dubbo.common.json.impl.FastJsonImpl; import org.apache.dubbo.common.json.impl.GsonImpl; @@ -27,16 +27,16 @@ import java.util.List; public class JsonUtils { - private static volatile JSON json; + private static volatile JsonUtil jsonUtil; - public static JSON getJson() { - if (json == null) { + public static JsonUtil getJson() { + if (jsonUtil == null) { synchronized (JsonUtils.class) { - if (json == null) { + if (jsonUtil == null) { String preferJsonFrameworkName = System.getProperty(CommonConstants.PREFER_JSON_FRAMEWORK_NAME); if (StringUtils.isNotEmpty(preferJsonFrameworkName)) { try { - JSON instance = null; + JsonUtil instance = null; switch (preferJsonFrameworkName) { case "fastjson2": instance = new FastJson2Impl(); @@ -52,23 +52,23 @@ public static JSON getJson() { break; } if (instance != null && instance.isSupport()) { - json = instance; + jsonUtil = instance; } } catch (Throwable ignore) { } } - if (json == null) { - List> jsonClasses = Arrays.asList( + if (jsonUtil == null) { + List> jsonClasses = Arrays.asList( FastJson2Impl.class, FastJsonImpl.class, GsonImpl.class, JacksonImpl.class); - for (Class jsonClass : jsonClasses) { + for (Class jsonClass : jsonClasses) { try { - JSON instance = jsonClass.getConstructor().newInstance(); + JsonUtil instance = jsonClass.getConstructor().newInstance(); if (instance.isSupport()) { - json = instance; + jsonUtil = instance; break; } } catch (Throwable ignore) { @@ -76,21 +76,21 @@ public static JSON getJson() { } } } - if (json == null) { + if (jsonUtil == null) { throw new IllegalStateException("Dubbo unable to find out any json framework (e.g. fastjson2, fastjson, gson, jackson) from jvm env. " + "Please import at least one json framework."); } } } } - return json; + return jsonUtil; } /** * @deprecated for uts only */ @Deprecated - protected static void setJson(JSON json) { - JsonUtils.json = json; + protected static void setJson(JsonUtil json) { + JsonUtils.jsonUtil = json; } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java index 6fd828d998c..7a9e72fb8d9 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java @@ -18,6 +18,7 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.aot.NativeDetector; import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.config.Environment; import org.apache.dubbo.common.config.InmemoryConfiguration; @@ -292,8 +293,7 @@ protected void appendMetricsCompatible(Map map) { * @return */ protected String[] methods(Class interfaceClass) { - boolean isNative = getEnvironment().getConfiguration().getBoolean(NATIVE, false); - if (isNative) { + if (NativeDetector.inNativeImage()) { return Arrays.stream(interfaceClass.getMethods()).map(Method::getName).toArray(String[]::new); } else { return ClassUtils.getMethodNames(interfaceClass); diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.json.JsonUtil b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.json.JsonUtil new file mode 100644 index 00000000000..914e8c9171c --- /dev/null +++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.json.JsonUtil @@ -0,0 +1,4 @@ +fastjson2=org.apache.dubbo.common.json.impl.FastJson2Impl +fastjson=org.apache.dubbo.common.json.impl.FastJsonImpl +gson=org.apache.dubbo.common.json.impl.GsonImpl +jackson=org.apache.dubbo.common.json.impl.JacksonImpl diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java index c22a280f0b7..4f0f775803e 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java @@ -20,6 +20,7 @@ import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.config.ReferenceConfig; +import org.apache.dubbo.config.spring.aot.AotWithSpringDetector; import org.apache.dubbo.config.spring.context.DubboConfigBeanInitializer; import org.apache.dubbo.config.spring.reference.ReferenceAttributes; import org.apache.dubbo.config.spring.reference.ReferenceBeanManager; @@ -74,14 +75,14 @@ * } * } * - * + *

* Or register ReferenceBean in xml: *

  * <dubbo:reference id="helloService" interface="org.apache.dubbo.config.spring.api.HelloService"/>
  * <!-- As GenericService -->
  * <dubbo:reference id="genericHelloService" interface="org.apache.dubbo.config.spring.api.HelloService" generic="true"/>
  * 
- * + *

* Step 2: Inject ReferenceBean by @Autowired *

  * public class FooController {
@@ -93,12 +94,11 @@
  * }
  * 
* - * * @see org.apache.dubbo.config.annotation.DubboReference * @see org.apache.dubbo.config.spring.reference.ReferenceBeanBuilder */ public class ReferenceBean implements FactoryBean, - ApplicationContextAware, BeanClassLoaderAware, BeanNameAware, InitializingBean, DisposableBean { + ApplicationContextAware, BeanClassLoaderAware, BeanNameAware, InitializingBean, DisposableBean { private transient ApplicationContext applicationContext; @@ -134,7 +134,7 @@ public class ReferenceBean implements FactoryBean, private ReferenceConfig referenceConfig; // Registration sources of this reference, may be xml file or annotation location - private List> sources = new ArrayList<>(); + private List> sources = new ArrayList<>(); public ReferenceBean() { super(); @@ -164,24 +164,23 @@ public void setBeanName(String name) { * *

* Why we need a lazy proxy? - * + *

*

* When Spring searches beans by type, if Spring cannot determine the type of a factory bean, it may try to initialize it. * The ReferenceBean is also a FactoryBean. *
* (This has already been resolved by decorating the BeanDefinition: {@link DubboBeanDefinitionParser#configReferenceBean}) - * + *

*

* In addition, if some ReferenceBeans are dependent on beans that are initialized very early, * and dubbo config beans are not ready yet, there will be many unexpected problems if initializing the dubbo reference immediately. - * + *

*

* When it is initialized, only a lazy proxy object will be created, * and dubbo reference-related resources will not be initialized. *
* In this way, the influence of Spring is eliminated, and the dubbo configuration initialization is controllable. * - * * @see DubboConfigBeanInitializer * @see ReferenceBeanManager#initReferenceBean(ReferenceBean) * @see DubboBeanDefinitionParser#configReferenceBean @@ -212,8 +211,14 @@ public void afterPropertiesSet() throws Exception { // pre init xml reference bean or @DubboReference annotation Assert.notEmptyString(getId(), "The id of ReferenceBean cannot be empty"); BeanDefinition beanDefinition = beanFactory.getBeanDefinition(getId()); - this.interfaceClass = (Class) beanDefinition.getAttribute(ReferenceAttributes.INTERFACE_CLASS); - this.interfaceName = (String) beanDefinition.getAttribute(ReferenceAttributes.INTERFACE_NAME); + if (AotWithSpringDetector.useGeneratedArtifacts()) { + this.interfaceClass = (Class) beanDefinition.getPropertyValues().get(ReferenceAttributes.INTERFACE_CLASS); + this.interfaceName = (String) beanDefinition.getPropertyValues().get(ReferenceAttributes.INTERFACE_NAME); + + } else { + this.interfaceClass = (Class) beanDefinition.getAttribute(ReferenceAttributes.INTERFACE_CLASS); + this.interfaceName = (String) beanDefinition.getAttribute(ReferenceAttributes.INTERFACE_NAME); + } Assert.notNull(this.interfaceClass, "The interface class of ReferenceBean is not initialized"); if (beanDefinition.hasAttribute(Constants.REFERENCE_PROPS)) { @@ -261,6 +266,7 @@ public void setId(String id) { /** * The interface of this ReferenceBean, for injection purpose + * * @return */ public Class getInterfaceClass() { @@ -347,7 +353,7 @@ private Object getCallProxy() throws Exception { //Subclasses should synchronize on the given Object if they perform any sort of extended singleton creation phase. // In particular, subclasses should not have their own mutexes involved in singleton creation, to avoid the potential for deadlocks in lazy-init situations. //The redundant type cast is to be compatible with earlier than spring-4.2 - synchronized (((DefaultSingletonBeanRegistry)getBeanFactory()).getSingletonMutex()) { + synchronized (((DefaultSingletonBeanRegistry) getBeanFactory()).getSingletonMutex()) { return referenceConfig.get(); } } @@ -365,4 +371,11 @@ public synchronized Class getTargetClass() { } } + public void setInterfaceClass(Class interfaceClass) { + this.interfaceClass = interfaceClass; + } + + public void setInterfaceName(String interfaceName) { + this.interfaceName = interfaceName; + } } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/aot/AotWithSpringDetector.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/aot/AotWithSpringDetector.java new file mode 100644 index 00000000000..97111ed870b --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/aot/AotWithSpringDetector.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.config.spring.aot; + +import org.apache.dubbo.common.aot.NativeDetector; +import org.springframework.core.SpringProperties; + +public abstract class AotWithSpringDetector { + + /** + * System property that indicates the application should run with AOT + * generated artifacts. If such optimizations are not available, it is + * recommended to throw an exception rather than fall back to the regular + * runtime behavior. + */ + public static final String AOT_ENABLED = "spring.aot.enabled"; + + /** + * Determine whether AOT optimizations must be considered at runtime. This + * is mandatory in a native image but can be triggered on the JVM using + * the {@value #AOT_ENABLED} Spring property. + * + * @return whether AOT optimizations must be considered + */ + public static boolean useGeneratedArtifacts() { + return (NativeDetector.inNativeImage() || SpringProperties.getFlag(AOT_ENABLED)); + } + +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AbstractAnnotationBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AbstractAnnotationBeanPostProcessor.java index 801333217ed..fc52559d810 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AbstractAnnotationBeanPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AbstractAnnotationBeanPostProcessor.java @@ -368,6 +368,11 @@ protected boolean needsRefresh(Class clazz) { if (targetClass.isAssignableFrom(clazz) && clazz.getName().contains("$$EnhancerBySpringCGLIB$$")) { return false; } + + if (targetClass.isAssignableFrom(clazz) && clazz.getName().contains("$$SpringCGLIB$$")) { + return false; + } + return true; } } @@ -377,11 +382,11 @@ protected boolean needsRefresh(Class clazz) { */ protected class AnnotatedInjectElement extends InjectionMetadata.InjectedElement { - protected final AnnotationAttributes attributes; + public final AnnotationAttributes attributes; - protected volatile Object injectedObject; + public volatile Object injectedObject; - private Class injectedType; + public Class injectedType; protected AnnotatedInjectElement(Member member, PropertyDescriptor pd, AnnotationAttributes attributes) { super(member, pd); @@ -438,7 +443,7 @@ public String getPropertyName() { protected class AnnotatedMethodElement extends AnnotatedInjectElement { - protected final Method method; + public final Method method; protected AnnotatedMethodElement(Method method, PropertyDescriptor pd, AnnotationAttributes attributes) { super(method, pd, attributes); @@ -448,7 +453,7 @@ protected AnnotatedMethodElement(Method method, PropertyDescriptor pd, Annotatio public class AnnotatedFieldElement extends AnnotatedInjectElement { - protected final Field field; + public final Field field; protected AnnotatedFieldElement(Field field, AnnotationAttributes attributes) { super(field, null, attributes); diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java index b5b8ac20fb8..8d0c3cd1178 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.config.spring.beans.factory.annotation; +import com.alibaba.spring.util.AnnotationUtils; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.ClassUtils; @@ -27,12 +28,11 @@ import org.apache.dubbo.config.annotation.Method; import org.apache.dubbo.config.annotation.Service; import org.apache.dubbo.config.spring.ServiceBean; +import org.apache.dubbo.config.spring.aot.AotWithSpringDetector; import org.apache.dubbo.config.spring.context.annotation.DubboClassPathBeanDefinitionScanner; import org.apache.dubbo.config.spring.schema.AnnotationBeanDefinitionParser; import org.apache.dubbo.config.spring.util.DubboAnnotationUtils; import org.apache.dubbo.config.spring.util.SpringCompatUtils; - -import com.alibaba.spring.util.AnnotationUtils; import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.BeanClassLoaderAware; @@ -78,12 +78,13 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; import static com.alibaba.spring.util.ObjectUtils.of; import static java.util.Arrays.asList; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUPLICATED_BEAN_DEFINITION; import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_NO_ANNOTATIONS_FOUND; import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_NO_BEANS_SCANNED; -import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUPLICATED_BEAN_DEFINITION; import static org.apache.dubbo.common.utils.AnnotationUtils.filterDefaultValues; import static org.apache.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilder.create; import static org.apache.dubbo.config.spring.util.DubboAnnotationUtils.resolveInterfaceName; @@ -128,7 +129,7 @@ public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPos private BeanDefinitionRegistry registry; - private ServicePackagesHolder servicePackagesHolder; + protected ServicePackagesHolder servicePackagesHolder; private volatile boolean scanned = false; @@ -136,12 +137,8 @@ public ServiceAnnotationPostProcessor(String... packagesToScan) { this(asList(packagesToScan)); } - public ServiceAnnotationPostProcessor(Collection packagesToScan) { - this(new LinkedHashSet<>(packagesToScan)); - } - - public ServiceAnnotationPostProcessor(Set packagesToScan) { - this.packagesToScan = packagesToScan; + public ServiceAnnotationPostProcessor(Collection packagesToScan) { + this.packagesToScan = (Set) packagesToScan.stream().collect(Collectors.toSet()); } @Override @@ -217,6 +214,9 @@ private void scanServiceBeans(Set packagesToScan, BeanDefinitionRegistry continue; } + if(AotWithSpringDetector.useGeneratedArtifacts()){ + scanner.setIncludeAnnotationConfig(false); + } // Registers @Service Bean first scanner.scan(packageToScan); diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigBeanInitializer.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigBeanInitializer.java index bf696b69fe6..71e9ace4a62 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigBeanInitializer.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigBeanInitializer.java @@ -34,6 +34,7 @@ import org.apache.dubbo.config.context.ConfigManager; import org.apache.dubbo.config.spring.ConfigCenterBean; import org.apache.dubbo.config.spring.reference.ReferenceBeanManager; +import org.apache.dubbo.config.spring.util.DubboBeanUtils; import org.apache.dubbo.rpc.model.ModuleModel; import org.springframework.beans.BeansException; @@ -66,7 +67,6 @@ public class DubboConfigBeanInitializer implements BeanFactoryAware, Initializin private ConfigurableListableBeanFactory beanFactory; private ReferenceBeanManager referenceBeanManager; - @Autowired private ConfigManager configManager; @Autowired @@ -86,6 +86,7 @@ public void afterPropertiesSet() throws Exception { private void init() { if (initialized.compareAndSet(false, true)) { referenceBeanManager = beanFactory.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class); + configManager = DubboBeanUtils.getConfigManager(beanFactory); try { prepareDubboConfigBeans(); referenceBeanManager.prepareReferenceBeans(); diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboContextPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboContextPostProcessor.java new file mode 100644 index 00000000000..9c1372aa17b --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboContextPostProcessor.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.config.spring.context; + +import org.apache.dubbo.config.context.ConfigManager; +import org.apache.dubbo.config.spring.context.annotation.DubboConfigConfigurationRegistrar; +import org.apache.dubbo.config.spring.extension.SpringExtensionInjector; +import org.apache.dubbo.config.spring.util.DubboBeanUtils; +import org.apache.dubbo.config.spring.util.EnvironmentUtils; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ModuleModel; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.env.ConfigurableEnvironment; + +import java.util.SortedMap; + + +public class DubboContextPostProcessor implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware { + + /** + * The bean name of {@link DubboConfigConfigurationRegistrar} + */ + public final static String BEAN_NAME = "dubboContextPostProcessor"; + + private BeanDefinitionRegistry registry; + + private ApplicationContext applicationContext; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + ApplicationModel applicationModel = DubboBeanUtils.getApplicationModel(beanFactory); + ModuleModel moduleModel = DubboBeanUtils.getModuleModel(beanFactory); + + // Initialize SpringExtensionInjector + SpringExtensionInjector.get(applicationModel).init(applicationContext); + SpringExtensionInjector.get(moduleModel).init(applicationContext); + DubboBeanUtils.getInitializationContext(beanFactory).setApplicationContext(applicationContext); + + // Initialize dubbo Environment before ConfigManager + // Extract dubbo props from Spring env and put them to app config + ConfigurableEnvironment environment = (ConfigurableEnvironment) applicationContext.getEnvironment(); + SortedMap dubboProperties = EnvironmentUtils.filterDubboProperties(environment); + applicationModel.getModelEnvironment().setAppConfigMap(dubboProperties); + + // register ConfigManager singleton + beanFactory.registerSingleton(ConfigManager.BEAN_NAME, applicationModel.getApplicationConfigManager()); + + } + + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { + DubboSpringInitializer.initialize(beanDefinitionRegistry); + this.registry = beanDefinitionRegistry; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java index d9f4f2b2cec..68e76ba0b0a 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java @@ -73,23 +73,6 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) DubboBeanUtils.registerPlaceholderConfigurerBeanIfNotExists(beanFactory, registry); } - ApplicationModel applicationModel = DubboBeanUtils.getApplicationModel(beanFactory); - ModuleModel moduleModel = DubboBeanUtils.getModuleModel(beanFactory); - - // Initialize SpringExtensionInjector - SpringExtensionInjector.get(applicationModel).init(applicationContext); - SpringExtensionInjector.get(moduleModel).init(applicationContext); - DubboBeanUtils.getInitializationContext(beanFactory).setApplicationContext(applicationContext); - - // Initialize dubbo Environment before ConfigManager - // Extract dubbo props from Spring env and put them to app config - ConfigurableEnvironment environment = (ConfigurableEnvironment) applicationContext.getEnvironment(); - SortedMap dubboProperties = EnvironmentUtils.filterDubboProperties(environment); - applicationModel.getModelEnvironment().setAppConfigMap(dubboProperties); - - // register ConfigManager singleton - beanFactory.registerSingleton(ConfigManager.BEAN_NAME, applicationModel.getApplicationConfigManager()); - // fix https://github.com/apache/dubbo/issues/10278 if (registry != null){ registry.removeBeanDefinition(BEAN_NAME); diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java index 774cfc1e8ea..6f4f2fc63a7 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java @@ -18,6 +18,7 @@ import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.config.spring.aot.AotWithSpringDetector; import org.apache.dubbo.config.spring.util.DubboBeanUtils; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.FrameworkModel; @@ -43,7 +44,7 @@ public class DubboSpringInitializer { private static final Map contextMap = new ConcurrentHashMap<>(); - private DubboSpringInitializer() { + public DubboSpringInitializer() { } public static void initialize(BeanDefinitionRegistry registry) { @@ -140,8 +141,10 @@ private static void initContext(DubboSpringInitContext context, BeanDefinitionRe context.markAsBound(); moduleModel.setLifeCycleManagedExternally(true); - // register common beans - DubboBeanUtils.registerCommonBeans(registry); + if (!AotWithSpringDetector.useGeneratedArtifacts()){ + // register common beans + DubboBeanUtils.registerCommonBeans(registry); + } } private static String safeGetModelDesc(ScopeModel scopeModel) { diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboClassPathBeanDefinitionScanner.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboClassPathBeanDefinitionScanner.java index fc8953bab54..6ecb422915d 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboClassPathBeanDefinitionScanner.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboClassPathBeanDefinitionScanner.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.config.spring.context.annotation; +import org.apache.dubbo.config.spring.aot.AotWithSpringDetector; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; @@ -53,7 +54,9 @@ public DubboClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, bool setResourceLoader(resourceLoader); - registerAnnotationConfigProcessors(registry); + if (!AotWithSpringDetector.useGeneratedArtifacts()) { + registerAnnotationConfigProcessors(registry); + } } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrar.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrar.java index 59cd3de7d80..fe2321bfa06 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrar.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrar.java @@ -20,7 +20,7 @@ import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; import org.apache.dubbo.config.spring.context.DubboSpringInitializer; - +import org.apache.dubbo.config.spring.util.SpringCompatUtils; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; @@ -70,7 +70,7 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B */ private void registerServiceAnnotationPostProcessor(Set packagesToScan, BeanDefinitionRegistry registry) { - BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationPostProcessor.class); + BeanDefinitionBuilder builder = rootBeanDefinition(SpringCompatUtils.serviceAnnotationPostProcessor()); builder.addConstructorArgValue(packagesToScan); builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanSupport.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanSupport.java index d571b4596f7..a1ff985c13e 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanSupport.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanSupport.java @@ -22,6 +22,7 @@ import org.apache.dubbo.config.annotation.ProvidedBy; import org.apache.dubbo.config.spring.Constants; import org.apache.dubbo.config.spring.ReferenceBean; +import org.apache.dubbo.config.spring.aot.AotWithSpringDetector; import org.apache.dubbo.config.spring.util.DubboAnnotationUtils; import org.apache.dubbo.rpc.service.GenericService; import org.springframework.beans.MutablePropertyValues; @@ -124,7 +125,12 @@ public static void convertReferenceProps(Map attributes, Class d public static String generateReferenceKey(Map attributes, ApplicationContext applicationContext) { - String interfaceClass = (String) attributes.get(ReferenceAttributes.INTERFACE); + String interfaceClass; + if (AotWithSpringDetector.useGeneratedArtifacts()) { + interfaceClass = (String) attributes.get(ReferenceAttributes.INTERFACE_NAME); + } else { + interfaceClass = (String) attributes.get(ReferenceAttributes.INTERFACE); + } Assert.notEmptyString(interfaceClass, "No interface class or name found from attributes"); String group = (String) attributes.get(ReferenceAttributes.GROUP); String version = (String) attributes.get(ReferenceAttributes.VERSION); diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/AnnotationBeanDefinitionParser.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/AnnotationBeanDefinitionParser.java index 69911edc93f..541a512c848 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/AnnotationBeanDefinitionParser.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/AnnotationBeanDefinitionParser.java @@ -19,6 +19,7 @@ import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; +import org.apache.dubbo.config.spring.util.SpringCompatUtils; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; @@ -73,7 +74,7 @@ protected boolean shouldGenerateIdAsFallback() { @Override protected Class getBeanClass(Element element) { - return ServiceAnnotationPostProcessor.class; + return SpringCompatUtils.serviceAnnotationPostProcessor(); } } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java index 10bb9b652d7..4f46297874a 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java @@ -31,6 +31,7 @@ import org.apache.dubbo.config.spring.ConfigCenterBean; import org.apache.dubbo.config.spring.ReferenceBean; import org.apache.dubbo.config.spring.ServiceBean; +import org.apache.dubbo.config.spring.aot.AotWithSpringDetector; import org.apache.dubbo.config.spring.beans.factory.config.ConfigurableSourceBeanMetadataElement; import org.apache.dubbo.config.spring.context.DubboSpringInitializer; @@ -100,6 +101,8 @@ public BeanDefinition parse(Element element, ParserContext parserContext) { * @since 2.7.5 */ private void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) { - AnnotationConfigUtils.registerAnnotationConfigProcessors(registry); + if (!AotWithSpringDetector.useGeneratedArtifacts()) { + AnnotationConfigUtils.registerAnnotationConfigProcessors(registry); + } } } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java index c369b1173eb..b33245125ff 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java @@ -16,21 +16,22 @@ */ package org.apache.dubbo.config.spring.util; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.dubbo.config.context.ConfigManager; import org.apache.dubbo.config.spring.beans.factory.annotation.DubboConfigAliasPostProcessor; import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; import org.apache.dubbo.config.spring.beans.factory.annotation.ServicePackagesHolder; import org.apache.dubbo.config.spring.beans.factory.config.DubboConfigDefaultPropertyValueBeanPostProcessor; import org.apache.dubbo.config.spring.context.DubboConfigApplicationListener; import org.apache.dubbo.config.spring.context.DubboConfigBeanInitializer; +import org.apache.dubbo.config.spring.context.DubboContextPostProcessor; import org.apache.dubbo.config.spring.context.DubboDeployApplicationListener; import org.apache.dubbo.config.spring.context.DubboInfraBeanRegisterPostProcessor; import org.apache.dubbo.config.spring.context.DubboSpringInitContext; import org.apache.dubbo.config.spring.reference.ReferenceBeanManager; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ModuleModel; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanPostProcessor; @@ -66,11 +67,13 @@ static void registerCommonBeans(BeanDefinitionRegistry registry) { registerInfrastructureBean(registry, ServicePackagesHolder.BEAN_NAME, ServicePackagesHolder.class); + registerInfrastructureBean(registry, DubboContextPostProcessor.BEAN_NAME, DubboContextPostProcessor.class); + registerInfrastructureBean(registry, ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class); // Since 2.5.7 Register @Reference Annotation Bean Processor as an infrastructure Bean - registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME, - ReferenceAnnotationBeanPostProcessor.class); + registerInfrastructureBean(registry, SpringCompatUtils.referenceAnnotationBeanPostProcessor().getName(), + SpringCompatUtils.referenceAnnotationBeanPostProcessor()); // TODO Whether DubboConfigAliasPostProcessor can be removed ? // Since 2.7.4 [Feature] https://github.com/apache/dubbo/issues/5093 @@ -89,7 +92,7 @@ static void registerCommonBeans(BeanDefinitionRegistry registry) { registerInfrastructureBean(registry, DubboConfigBeanInitializer.BEAN_NAME, DubboConfigBeanInitializer.class); // register infra bean if not exists later - registerInfrastructureBean(registry, DubboInfraBeanRegisterPostProcessor.BEAN_NAME, DubboInfraBeanRegisterPostProcessor.class); + registerInfrastructureBean(registry, DubboInfraBeanRegisterPostProcessor.BEAN_NAME, SpringCompatUtils.dubboInfraBeanRegisterPostProcessor()); } /** @@ -203,4 +206,12 @@ static ModuleModel getModuleModel(BeanFactory beanFactory) { return null; } + static ConfigManager getConfigManager(BeanFactory beanFactory) { + String beanName = ConfigManager.BEAN_NAME; + if (beanFactory.containsBean(beanName)) { + return beanFactory.getBean(beanName, ConfigManager.class); + } + return null; + } + } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringCompatUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringCompatUtils.java index a6a4d93faa7..b06784bbbf3 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringCompatUtils.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringCompatUtils.java @@ -18,6 +18,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; +import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; +import org.apache.dubbo.config.spring.context.DubboInfraBeanRegisterPostProcessor; import org.springframework.beans.PropertyValue; import org.springframework.beans.PropertyValues; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; @@ -30,7 +33,7 @@ import java.lang.reflect.Type; /** - * Spring Compatibility Utils for spring 3.x/4.x/5.x + * Spring Compatibility Utils for spring 3.x/4.x/5.x/6.x */ public class SpringCompatUtils { @@ -127,4 +130,28 @@ public static Class getGenericTypeOfReturnType(MethodMetadata factoryMethodMetad } return null; } + + public static Class referenceAnnotationBeanPostProcessor(){ + try { + return Class.forName("org.apache.dubbo.config.spring6.beans.factory.annotation.ReferenceAnnotationWithAotBeanPostProcessor"); + } catch (ClassNotFoundException e) { + return ReferenceAnnotationBeanPostProcessor.class; + } + } + + public static Class serviceAnnotationPostProcessor(){ + try { + return Class.forName("org.apache.dubbo.config.spring6.beans.factory.annotation.ServiceAnnotationWithAotPostProcessor"); + } catch (ClassNotFoundException e) { + return ServiceAnnotationPostProcessor.class; + } + } + + public static Class dubboInfraBeanRegisterPostProcessor(){ + try { + return Class.forName("org.apache.dubbo.config.spring6.context.DubboInfraBeanRegisterPostProcessor"); + } catch (ClassNotFoundException e) { + return DubboInfraBeanRegisterPostProcessor.class; + } + } } diff --git a/dubbo-config/dubbo-config-spring6/pom.xml b/dubbo-config/dubbo-config-spring6/pom.xml new file mode 100644 index 00000000000..b674b8116c9 --- /dev/null +++ b/dubbo-config/dubbo-config-spring6/pom.xml @@ -0,0 +1,84 @@ + + + 4.0.0 + + org.apache.dubbo + dubbo-config + ${revision} + + + dubbo-config-spring6 + + + 17 + 17 + UTF-8 + 6.0.7 + 3.0.4 + + + + + org.apache.dubbo + dubbo-config-api + ${project.parent.version} + + + + org.apache.dubbo + dubbo-config-spring + ${project.parent.version} + + + + org.springframework + spring-beans + ${spring.version} + + + org.springframework + spring-core + ${spring.version} + + + org.springframework + spring-web + ${spring.version} + + + org.springframework + spring-context + ${spring.version} + + + javax.servlet + javax.servlet-api + provided + + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot.version} + test + + + junit-vintage-engine + org.junit.vintage + + + + org.apache.logging.log4j + log4j-api + + + + + + + + + + diff --git a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java new file mode 100644 index 00000000000..bcb2917b88e --- /dev/null +++ b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java @@ -0,0 +1,841 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.config.spring6.beans.factory.annotation; + + +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.ArrayUtils; +import org.apache.dubbo.common.utils.Assert; +import org.apache.dubbo.common.utils.ClassUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.config.annotation.DubboReference; +import org.apache.dubbo.config.annotation.Reference; +import org.apache.dubbo.config.spring.Constants; +import org.apache.dubbo.config.spring.ReferenceBean; +import org.apache.dubbo.config.spring.beans.factory.annotation.AbstractAnnotationBeanPostProcessor; +import org.apache.dubbo.config.spring.context.event.DubboConfigInitEvent; +import org.apache.dubbo.config.spring.reference.ReferenceAttributes; +import org.apache.dubbo.config.spring.reference.ReferenceBeanManager; +import org.apache.dubbo.config.spring.reference.ReferenceBeanSupport; +import org.apache.dubbo.config.spring.util.SpringCompatUtils; +import org.apache.dubbo.config.spring6.beans.factory.aot.ReferencedFieldValueResolver; +import org.apache.dubbo.config.spring6.beans.factory.aot.ReferencedMethodArgumentsResolver; +import org.apache.dubbo.rpc.service.Destroyable; +import org.apache.dubbo.rpc.service.EchoService; +import org.apache.dubbo.rpc.service.GenericService; +import org.springframework.aop.SpringProxy; +import org.springframework.aop.framework.Advised; +import org.springframework.aot.generate.AccessControl; +import org.springframework.aot.generate.GeneratedClass; +import org.springframework.aot.generate.GeneratedMethod; +import org.springframework.aot.generate.GenerationContext; +import org.springframework.aot.hint.ExecutableMode; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.TypeReference; +import org.springframework.aot.hint.support.ClassHintUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.PropertyValue; +import org.springframework.beans.PropertyValues; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; +import org.springframework.beans.factory.annotation.InjectionMetadata; +import org.springframework.beans.factory.aot.AutowiredArgumentsCodeGenerator; +import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; +import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor; +import org.springframework.beans.factory.aot.BeanRegistrationCode; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.DependencyDescriptor; +import org.springframework.beans.factory.support.AutowireCandidateResolver; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.beans.factory.support.RegisteredBean; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.DecoratingProxy; +import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.type.MethodMetadata; +import org.springframework.javapoet.ClassName; +import org.springframework.javapoet.CodeBlock; +import org.springframework.lang.Nullable; +import org.springframework.util.CollectionUtils; + +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import static com.alibaba.spring.util.AnnotationUtils.getAttribute; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUBBO_BEAN_INITIALIZER; +import static org.apache.dubbo.common.utils.AnnotationUtils.filterDefaultValues; +import static org.springframework.util.StringUtils.hasText; + +/** + *

+ * Step 1: + * The purpose of implementing {@link BeanFactoryPostProcessor} is to scan the registration reference bean definition earlier, + * so that it can be shared with the xml bean configuration. + *

+ * + *

+ * Step 2: + * By implementing {@link org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor}, + * inject the reference bean instance into the fields and setter methods which annotated with {@link DubboReference}. + *

+ * + * @see DubboReference + * @see Reference + * @see com.alibaba.dubbo.config.annotation.Reference + * @since 2.5.7 + */ +public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotationBeanPostProcessor + implements ApplicationContextAware, BeanRegistrationAotProcessor, BeanFactoryPostProcessor { + + /** + * The bean name of {@link ReferenceAnnotationWithAotBeanPostProcessor} + */ + public static final String BEAN_NAME = ReferenceAnnotationWithAotBeanPostProcessor.class.getName(); + + /** + * Cache size + */ + private static final int CACHE_SIZE = Integer.getInteger(BEAN_NAME + ".cache.size", 32); + + private final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(getClass()); + + private final ConcurrentMap injectedFieldReferenceBeanCache = + new ConcurrentHashMap<>(CACHE_SIZE); + + private final ConcurrentMap injectedMethodReferenceBeanCache = + new ConcurrentHashMap<>(CACHE_SIZE); + + private ApplicationContext applicationContext; + + private ReferenceBeanManager referenceBeanManager; + private BeanDefinitionRegistry beanDefinitionRegistry; + + @Nullable + private ConfigurableListableBeanFactory beanFactory; + + /** + * {@link com.alibaba.dubbo.config.annotation.Reference @com.alibaba.dubbo.config.annotation.Reference} has been supported since 2.7.3 + *

+ * {@link DubboReference @DubboReference} has been supported since 2.7.7 + */ + public ReferenceAnnotationWithAotBeanPostProcessor() { + super(DubboReference.class, Reference.class, com.alibaba.dubbo.config.annotation.Reference.class); + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + + String[] beanNames = beanFactory.getBeanDefinitionNames(); + for (String beanName : beanNames) { + Class beanType; + if (beanFactory.isFactoryBean(beanName)) { + BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); + if (isReferenceBean(beanDefinition)) { + continue; + } + if (isAnnotatedReferenceBean(beanDefinition)) { + // process @DubboReference at java-config @bean method + processReferenceAnnotatedBeanDefinition(beanName, (AnnotatedBeanDefinition) beanDefinition); + continue; + } + + String beanClassName = beanDefinition.getBeanClassName(); + beanType = ClassUtils.resolveClass(beanClassName, getClassLoader()); + } else { + beanType = beanFactory.getType(beanName); + } + if (beanType != null) { + AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null); + try { + prepareInjection(metadata); + } catch (BeansException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException("Prepare dubbo reference injection element failed", e); + } + } + } + +// if (beanFactory instanceof AbstractBeanFactory) { +// List beanPostProcessors = ((AbstractBeanFactory) beanFactory).getBeanPostProcessors(); +// for (BeanPostProcessor beanPostProcessor : beanPostProcessors) { +// if (beanPostProcessor == this) { +// // This bean has been registered as BeanPostProcessor at org.apache.dubbo.config.spring.context.DubboInfraBeanRegisterPostProcessor.postProcessBeanFactory() +// // so destroy this bean here, prevent register it as BeanPostProcessor again, avoid cause BeanPostProcessorChecker detection error +// beanDefinitionRegistry.removeBeanDefinition(BEAN_NAME); +// break; +// } +// } +// } + + try { + // this is an early event, it will be notified at org.springframework.context.support.AbstractApplicationContext.registerListeners() + applicationContext.publishEvent(new DubboConfigInitEvent(applicationContext)); + } catch (Exception e) { + // if spring version is less than 4.2, it does not support early application event + logger.warn(CONFIG_DUBBO_BEAN_INITIALIZER, "", "", "publish early application event failed, please upgrade spring version to 4.2.x or later: " + e); + } + } + + /** + * check whether is @DubboReference at java-config @bean method + */ + private boolean isAnnotatedReferenceBean(BeanDefinition beanDefinition) { + if (beanDefinition instanceof AnnotatedBeanDefinition) { + AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDefinition; + String beanClassName = SpringCompatUtils.getFactoryMethodReturnType(annotatedBeanDefinition); + if (beanClassName != null && ReferenceBean.class.getName().equals(beanClassName)) { + return true; + } + } + return false; + } + + /** + * process @DubboReference at java-config @bean method + *

+     * @Configuration
+     * public class ConsumerConfig {
+     *
+     *      @Bean
+     *      @DubboReference(group="demo", version="1.2.3")
+     *      public ReferenceBean<DemoService> demoService() {
+     *          return new ReferenceBean();
+     *      }
+     *
+     * }
+     * 
+ * + * @param beanName + * @param beanDefinition + */ + private void processReferenceAnnotatedBeanDefinition(String beanName, AnnotatedBeanDefinition beanDefinition) { + + MethodMetadata factoryMethodMetadata = SpringCompatUtils.getFactoryMethodMetadata(beanDefinition); + + // Extract beanClass from generic return type of java-config bean method: ReferenceBean + // see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBeanFromMethod + Class beanClass = getBeanFactory().getType(beanName); + if (beanClass == Object.class) { + beanClass = SpringCompatUtils.getGenericTypeOfReturnType(factoryMethodMetadata); + } + if (beanClass == Object.class) { + // bean class is invalid, ignore it + return; + } + + if (beanClass == null) { + String beanMethodSignature = factoryMethodMetadata.getDeclaringClassName() + "#" + factoryMethodMetadata.getMethodName() + "()"; + throw new BeanCreationException("The ReferenceBean is missing necessary generic type, which returned by the @Bean method of Java-config class. " + + "The generic type of the returned ReferenceBean must be specified as the referenced interface type, " + + "such as ReferenceBean. Please check bean method: " + beanMethodSignature); + } + + // get dubbo reference annotation attributes + Map annotationAttributes = null; + // try all dubbo reference annotation types + for (Class annotationType : getAnnotationTypes()) { + if (factoryMethodMetadata.isAnnotated(annotationType.getName())) { + // Since Spring 5.2 + // return factoryMethodMetadata.getAnnotations().get(annotationType).filterDefaultValues().asMap(); + // Compatible with Spring 4.x + annotationAttributes = factoryMethodMetadata.getAnnotationAttributes(annotationType.getName()); + annotationAttributes = filterDefaultValues(annotationType, annotationAttributes); + break; + } + } + + if (annotationAttributes != null) { + // @DubboReference on @Bean method + LinkedHashMap attributes = new LinkedHashMap<>(annotationAttributes); + // reset id attribute + attributes.put(ReferenceAttributes.ID, beanName); + // convert annotation props + ReferenceBeanSupport.convertReferenceProps(attributes, beanClass); + + // get interface + String interfaceName = (String) attributes.get(ReferenceAttributes.INTERFACE); + + // check beanClass and reference interface class + if (!StringUtils.isEquals(interfaceName, beanClass.getName()) && beanClass != GenericService.class) { + String beanMethodSignature = factoryMethodMetadata.getDeclaringClassName() + "#" + factoryMethodMetadata.getMethodName() + "()"; + throw new BeanCreationException("The 'interfaceClass' or 'interfaceName' attribute value of @DubboReference annotation " + + "is inconsistent with the generic type of the ReferenceBean returned by the bean method. " + + "The interface class of @DubboReference is: " + interfaceName + ", but return ReferenceBean<" + beanClass.getName() + ">. " + + "Please remove the 'interfaceClass' and 'interfaceName' attributes from @DubboReference annotation. " + + "Please check bean method: " + beanMethodSignature); + } + + Class interfaceClass = beanClass; + + // set attribute instead of property values + beanDefinition.setAttribute(Constants.REFERENCE_PROPS, attributes); + beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, interfaceClass); + beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, interfaceName); + } else { + // raw reference bean + // the ReferenceBean is not yet initialized + beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, beanClass); + if (beanClass != GenericService.class) { + beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, beanClass.getName()); + } + } + + // set id + beanDefinition.getPropertyValues().add(ReferenceAttributes.ID, beanName); + } + + @Override + public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { + if (beanType != null) { + if (isReferenceBean(beanDefinition)) { + //mark property value as optional + List propertyValues = beanDefinition.getPropertyValues().getPropertyValueList(); + for (PropertyValue propertyValue : propertyValues) { + propertyValue.setOptional(true); + } + } else if (isAnnotatedReferenceBean(beanDefinition)) { + // extract beanClass from java-config bean method generic return type: ReferenceBean + //Class beanClass = getBeanFactory().getType(beanName); + } else { + AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null); + metadata.checkConfigMembers(beanDefinition); + try { + prepareInjection(metadata); + } catch (Exception e) { + throw new IllegalStateException("Prepare dubbo reference injection element failed", e); + } + } + } + } + + /** + * Alternatives to the {@link #postProcessProperties(PropertyValues, Object, String)}, that removed as of Spring + * Framework 6.0.0, and in favor of {@link #postProcessProperties(PropertyValues, Object, String)}. + *

In order to be compatible with the lower version of Spring, it is still retained. + * + * @see #postProcessProperties + */ + public PropertyValues postProcessPropertyValues( + PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { + return postProcessProperties(pvs, bean, beanName); + } + + /** + * Alternatives to the {@link #postProcessPropertyValues(PropertyValues, PropertyDescriptor[], Object, String)}. + * + * @see #postProcessPropertyValues + */ + @Override + public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) + throws BeansException { + try { + AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs); + prepareInjection(metadata); + metadata.inject(bean, beanName, pvs); + } catch (BeansException ex) { + throw ex; + } catch (Throwable ex) { + throw new BeanCreationException(beanName, "Injection of @" + getAnnotationType().getSimpleName() + + " dependencies is failed", ex); + } + return pvs; + } + + private boolean isReferenceBean(BeanDefinition beanDefinition) { + return ReferenceBean.class.getName().equals(beanDefinition.getBeanClassName()); + } + + @Override + @Nullable + public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { + Class beanClass = registeredBean.getBeanClass(); + String beanName = registeredBean.getBeanName(); + RootBeanDefinition beanDefinition = registeredBean.getMergedBeanDefinition(); + AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanDefinition, beanClass, beanName); + if (!CollectionUtils.isEmpty(metadata.getFieldElements()) || !CollectionUtils.isEmpty(metadata.getMethodElements())) { + return new AotContribution(beanClass, metadata, getAutowireCandidateResolver()); + } + return null; + } + + private AnnotatedInjectionMetadata findInjectionMetadata(RootBeanDefinition beanDefinition, Class beanType, String beanName) { + AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null); + metadata.checkConfigMembers(beanDefinition); + return metadata; + } + + protected void prepareInjection(AnnotatedInjectionMetadata metadata) throws BeansException { + try { + //find and register bean definition for @DubboReference/@Reference + for (AnnotatedFieldElement fieldElement : metadata.getFieldElements()) { + if (fieldElement.injectedObject != null) { + continue; + } + Class injectedType = fieldElement.field.getType(); + AnnotationAttributes attributes = fieldElement.attributes; + String referenceBeanName = registerReferenceBean(fieldElement.getPropertyName(), injectedType, attributes, fieldElement.field); + + //associate fieldElement and reference bean + fieldElement.injectedObject = referenceBeanName; + injectedFieldReferenceBeanCache.put(fieldElement, referenceBeanName); + + } + + for (AnnotatedMethodElement methodElement : metadata.getMethodElements()) { + if (methodElement.injectedObject != null) { + continue; + } + Class injectedType = methodElement.getInjectedType(); + AnnotationAttributes attributes = methodElement.attributes; + String referenceBeanName = registerReferenceBean(methodElement.getPropertyName(), injectedType, attributes, methodElement.method); + + //associate methodElement and reference bean + methodElement.injectedObject = referenceBeanName; + injectedMethodReferenceBeanCache.put(methodElement, referenceBeanName); + } + } catch (ClassNotFoundException e) { + throw new BeanCreationException("prepare reference annotation failed", e); + } + } + + public String registerReferenceBean(String propertyName, Class injectedType, Map attributes, Member member) throws BeansException { + + boolean renameable = true; + // referenceBeanName + String referenceBeanName = getAttribute(attributes, ReferenceAttributes.ID); + if (hasText(referenceBeanName)) { + renameable = false; + } else { + referenceBeanName = propertyName; + } + + String checkLocation = "Please check " + member.toString(); + + // convert annotation props + ReferenceBeanSupport.convertReferenceProps(attributes, injectedType); + + // get interface + String interfaceName = (String) attributes.get(ReferenceAttributes.INTERFACE); + if (StringUtils.isBlank(interfaceName)) { + throw new BeanCreationException("Need to specify the 'interfaceName' or 'interfaceClass' attribute of '@DubboReference' if enable generic. " + checkLocation); + } + + // check reference key + String referenceKey = ReferenceBeanSupport.generateReferenceKey(attributes, applicationContext); + + // find reference bean name by reference key + List registeredReferenceBeanNames = referenceBeanManager.getBeanNamesByKey(referenceKey); + if (registeredReferenceBeanNames.size() > 0) { + // found same name and reference key + if (registeredReferenceBeanNames.contains(referenceBeanName)) { + return referenceBeanName; + } + } + + //check bean definition + boolean isContains; + if ((isContains = beanDefinitionRegistry.containsBeanDefinition(referenceBeanName)) || beanDefinitionRegistry.isAlias(referenceBeanName)) { + String preReferenceBeanName = referenceBeanName; + if (!isContains) { + // Look in the alias for the origin bean name + String[] aliases = beanDefinitionRegistry.getAliases(referenceBeanName); + if (ArrayUtils.isNotEmpty(aliases)) { + for (String alias : aliases) { + if (beanDefinitionRegistry.containsBeanDefinition(alias)) { + preReferenceBeanName = alias; + break; + } + } + } + } + BeanDefinition prevBeanDefinition = beanDefinitionRegistry.getBeanDefinition(preReferenceBeanName); + String prevBeanType = prevBeanDefinition.getBeanClassName(); + String prevBeanDesc = referenceBeanName + "[" + prevBeanType + "]"; + String newBeanDesc = referenceBeanName + "[" + referenceKey + "]"; + + if (isReferenceBean(prevBeanDefinition)) { + //check reference key + String prevReferenceKey = ReferenceBeanSupport.generateReferenceKey(prevBeanDefinition, applicationContext); + if (StringUtils.isEquals(prevReferenceKey, referenceKey)) { + //found matched dubbo reference bean, ignore register + return referenceBeanName; + } + //get interfaceName from attribute + Assert.notNull(prevBeanDefinition, "The interface class of ReferenceBean is not initialized"); + prevBeanDesc = referenceBeanName + "[" + prevReferenceKey + "]"; + } + + // bean name from attribute 'id' or java-config bean, cannot be renamed + if (!renameable) { + throw new BeanCreationException("Already exists another bean definition with the same bean name [" + referenceBeanName + "], " + + "but cannot rename the reference bean name (specify the id attribute or java-config bean), " + + "please modify the name of one of the beans: " + + "prev: " + prevBeanDesc + ", new: " + newBeanDesc + ". " + checkLocation); + } + + // the prev bean type is different, rename the new reference bean + int index = 2; + String newReferenceBeanName = null; + while (newReferenceBeanName == null || beanDefinitionRegistry.containsBeanDefinition(newReferenceBeanName) + || beanDefinitionRegistry.isAlias(newReferenceBeanName)) { + newReferenceBeanName = referenceBeanName + "#" + index; + index++; + // double check found same name and reference key + if (registeredReferenceBeanNames.contains(newReferenceBeanName)) { + return newReferenceBeanName; + } + } + newBeanDesc = newReferenceBeanName + "[" + referenceKey + "]"; + + logger.warn(CONFIG_DUBBO_BEAN_INITIALIZER, "", "", "Already exists another bean definition with the same bean name [" + referenceBeanName + "], " + + "rename dubbo reference bean to [" + newReferenceBeanName + "]. " + + "It is recommended to modify the name of one of the beans to avoid injection problems. " + + "prev: " + prevBeanDesc + ", new: " + newBeanDesc + ". " + checkLocation); + referenceBeanName = newReferenceBeanName; + } + attributes.put(ReferenceAttributes.ID, referenceBeanName); + + // If registered matched reference before, just register alias + if (registeredReferenceBeanNames.size() > 0) { + beanDefinitionRegistry.registerAlias(registeredReferenceBeanNames.get(0), referenceBeanName); + referenceBeanManager.registerReferenceKeyAndBeanName(referenceKey, referenceBeanName); + return referenceBeanName; + } + + Class interfaceClass = injectedType; + + // TODO Only register one reference bean for same (group, interface, version) + + // Register the reference bean definition to the beanFactory + RootBeanDefinition beanDefinition = new RootBeanDefinition(); + beanDefinition.setBeanClassName(ReferenceBean.class.getName()); + beanDefinition.getPropertyValues().add(ReferenceAttributes.ID, referenceBeanName); + + // set attribute instead of property values + beanDefinition.setAttribute(Constants.REFERENCE_PROPS, attributes); + beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, interfaceClass); + beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, interfaceName); +// beanDefinition.getPropertyValues().add(Constants.REFERENCE_PROPS,attributes); + beanDefinition.getPropertyValues().add(ReferenceAttributes.INTERFACE_CLASS, interfaceClass); + beanDefinition.getPropertyValues().add(ReferenceAttributes.INTERFACE_NAME, interfaceName); + // create decorated definition for reference bean, Avoid being instantiated when getting the beanType of ReferenceBean + // see org.springframework.beans.factory.support.AbstractBeanFactory#getTypeForFactoryBean() + GenericBeanDefinition targetDefinition = new GenericBeanDefinition(); + targetDefinition.setBeanClass(interfaceClass); + beanDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, referenceBeanName + "_decorated")); + + // signal object type since Spring 5.2 + beanDefinition.setAttribute(Constants.OBJECT_TYPE_ATTRIBUTE, interfaceClass); + + beanDefinitionRegistry.registerBeanDefinition(referenceBeanName, beanDefinition); + referenceBeanManager.registerReferenceKeyAndBeanName(referenceKey, referenceBeanName); + logger.info("Register dubbo reference bean: " + referenceBeanName + " = " + referenceKey + " at " + member); + return referenceBeanName; + } + + @Override + protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class injectedType, + AnnotatedInjectElement injectedElement) throws Exception { + + if (injectedElement.injectedObject == null) { + throw new IllegalStateException("The AnnotatedInjectElement of @DubboReference should be inited before injection"); + } + + return getBeanFactory().getBean((String) injectedElement.injectedObject); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + this.referenceBeanManager = applicationContext.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class); + this.beanDefinitionRegistry = (BeanDefinitionRegistry) applicationContext.getAutowireCapableBeanFactory(); + } + + @Override + public void destroy() throws Exception { + super.destroy(); + this.injectedFieldReferenceBeanCache.clear(); + this.injectedMethodReferenceBeanCache.clear(); + } + + /** + * Gets all beans of {@link ReferenceBean} + * + * @deprecated use {@link ReferenceBeanManager#getReferences()} instead + */ + @Deprecated + public Collection> getReferenceBeans() { + return Collections.emptyList(); + } + + /** + * Get {@link ReferenceBean} {@link Map} in injected field. + * + * @return non-null {@link Map} + * @since 2.5.11 + */ + public Map> getInjectedFieldReferenceBeanMap() { + Map> map = new HashMap<>(); + for (Map.Entry entry : injectedFieldReferenceBeanCache.entrySet()) { + map.put(entry.getKey(), referenceBeanManager.getById(entry.getValue())); + } + return Collections.unmodifiableMap(map); + } + + /** + * Get {@link ReferenceBean} {@link Map} in injected method. + * + * @return non-null {@link Map} + * @since 2.5.11 + */ + public Map> getInjectedMethodReferenceBeanMap() { + Map> map = new HashMap<>(); + for (Map.Entry entry : injectedMethodReferenceBeanCache.entrySet()) { + map.put(entry.getKey(), referenceBeanManager.getById(entry.getValue())); + } + return Collections.unmodifiableMap(map); + } + + @Nullable + private AutowireCandidateResolver getAutowireCandidateResolver() { + if (this.beanFactory instanceof DefaultListableBeanFactory) { + return ((DefaultListableBeanFactory) this.beanFactory).getAutowireCandidateResolver(); + } + return null; + } + + + private static class AotContribution implements BeanRegistrationAotContribution { + + private static final String REGISTERED_BEAN_PARAMETER = "registeredBean"; + + private static final String INSTANCE_PARAMETER = "instance"; + + private final Class target; + + private final AnnotatedInjectionMetadata annotatedInjectionMetadata; + + @Nullable + private final AutowireCandidateResolver candidateResolver; + + AotContribution(Class target, AnnotatedInjectionMetadata annotatedInjectionMetadata, AutowireCandidateResolver candidateResolver) { + + this.target = target; + this.annotatedInjectionMetadata = annotatedInjectionMetadata; + this.candidateResolver = candidateResolver; + } + + @Override + public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) { + GeneratedClass generatedClass = generationContext.getGeneratedClasses() + .addForFeatureComponent("DubboReference", this.target, type -> { + type.addJavadoc("DubboReference for {@link $T}.", this.target); + type.addModifiers(javax.lang.model.element.Modifier.PUBLIC); + }); + GeneratedMethod generateMethod = generatedClass.getMethods().add("apply", method -> { + method.addJavadoc("Apply the dubbo reference."); + method.addModifiers(javax.lang.model.element.Modifier.PUBLIC, + javax.lang.model.element.Modifier.STATIC); + method.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER); + method.addParameter(this.target, INSTANCE_PARAMETER); + method.returns(this.target); + method.addCode(generateMethodCode(generatedClass.getName(), + generationContext.getRuntimeHints())); + }); + beanRegistrationCode.addInstancePostProcessor(generateMethod.toMethodReference()); + + if (this.candidateResolver != null) { + registerHints(generationContext.getRuntimeHints()); + } + } + + private CodeBlock generateMethodCode(ClassName targetClassName, RuntimeHints hints) { + CodeBlock.Builder code = CodeBlock.builder(); + if (!CollectionUtils.isEmpty(this.annotatedInjectionMetadata.getFieldElements())) { + for (AnnotatedInjectElement referenceElement : this.annotatedInjectionMetadata.getFieldElements()) { + code.addStatement(generateMethodStatementForElement( + targetClassName, referenceElement, hints)); + } + } + if (!CollectionUtils.isEmpty(this.annotatedInjectionMetadata.getMethodElements())) { + for (AnnotatedInjectElement referenceElement : this.annotatedInjectionMetadata.getMethodElements()) { + code.addStatement(generateMethodStatementForElement( + targetClassName, referenceElement, hints)); + } + } + code.addStatement("return $L", INSTANCE_PARAMETER); + return code.build(); + } + + private CodeBlock generateMethodStatementForElement(ClassName targetClassName, + AnnotatedInjectElement referenceElement, RuntimeHints hints) { + + Member member = referenceElement.getMember(); + AnnotationAttributes attributes = referenceElement.attributes; + Object injectedObject = referenceElement.injectedObject; + + try { + Class c = referenceElement.getInjectedType(); + hints.reflection().registerType(TypeReference.of(c), MemberCategory.INVOKE_PUBLIC_METHODS); + hints.proxies().registerJdkProxy(c, EchoService.class, Destroyable.class); + hints.proxies().registerJdkProxy(c, EchoService.class, Destroyable.class, SpringProxy.class, Advised.class, DecoratingProxy.class); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + + if (member instanceof Field) { + return generateMethodStatementForField( + targetClassName, (Field) member, attributes, injectedObject, hints); + } + if (member instanceof Method) { + return generateMethodStatementForMethod( + targetClassName, (Method) member, attributes, injectedObject, hints); + } + throw new IllegalStateException( + "Unsupported member type " + member.getClass().getName()); + } + + private CodeBlock generateMethodStatementForField(ClassName targetClassName, + Field field, AnnotationAttributes attributes, Object injectedObject, RuntimeHints hints) { + + hints.reflection().registerField(field); + CodeBlock resolver = CodeBlock.of("$T.$L($S)", + ReferencedFieldValueResolver.class, + "forRequiredField", field.getName()); + CodeBlock shortcutResolver = CodeBlock.of("$L.withShortcut($S)", resolver, injectedObject); + AccessControl accessControl = AccessControl.forMember(field); + + if (!accessControl.isAccessibleFrom(targetClassName)) { + return CodeBlock.of("$L.resolveAndSet($L, $L)", shortcutResolver, + REGISTERED_BEAN_PARAMETER, INSTANCE_PARAMETER); + } + return CodeBlock.of("$L.$L = $L.resolve($L)", INSTANCE_PARAMETER, + field.getName(), shortcutResolver, REGISTERED_BEAN_PARAMETER); + } + + private CodeBlock generateMethodStatementForMethod(ClassName targetClassName, + Method method, AnnotationAttributes attributes, Object injectedObject, RuntimeHints hints) { + + CodeBlock.Builder code = CodeBlock.builder(); + code.add("$T.$L", ReferencedMethodArgumentsResolver.class, "forRequiredMethod"); + code.add("($S", method.getName()); + if (method.getParameterCount() > 0) { + code.add(", $L", generateParameterTypesCode(method.getParameterTypes())); + } + code.add(")"); + if (method.getParameterCount() > 0) { + Parameter[] parameters = method.getParameters(); + String[] parameterNames = new String[parameters.length]; + for (int i = 0; i < parameterNames.length; i++) { + parameterNames[i] = parameters[i].getName(); + } + code.add(".withShortcut($L)", generateParameterNamesCode(parameterNames)); + } + AccessControl accessControl = AccessControl.forMember(method); + if (!accessControl.isAccessibleFrom(targetClassName)) { + hints.reflection().registerMethod(method, ExecutableMode.INVOKE); + code.add(".resolveAndInvoke($L, $L)", REGISTERED_BEAN_PARAMETER, INSTANCE_PARAMETER); + } else { + hints.reflection().registerMethod(method, ExecutableMode.INTROSPECT); + CodeBlock arguments = new AutowiredArgumentsCodeGenerator(this.target, + method).generateCode(method.getParameterTypes()); + CodeBlock injectionCode = CodeBlock.of("args -> $L.$L($L)", + INSTANCE_PARAMETER, method.getName(), arguments); + code.add(".resolve($L, $L)", REGISTERED_BEAN_PARAMETER, injectionCode); + } + return code.build(); + } + + private CodeBlock generateParameterNamesCode(String[] parameterNames) { + CodeBlock.Builder code = CodeBlock.builder(); + for (int i = 0; i < parameterNames.length; i++) { + code.add(i != 0 ? ", " : ""); + code.add("$S", parameterNames[i]); + } + return code.build(); + } + + private CodeBlock generateParameterTypesCode(Class[] parameterTypes) { + CodeBlock.Builder code = CodeBlock.builder(); + for (int i = 0; i < parameterTypes.length; i++) { + code.add(i != 0 ? ", " : ""); + code.add("$T.class", parameterTypes[i]); + } + return code.build(); + } + + private void registerHints(RuntimeHints runtimeHints) { + if (!CollectionUtils.isEmpty(this.annotatedInjectionMetadata.getFieldElements())) { + for (AnnotatedInjectElement referenceElement : this.annotatedInjectionMetadata.getFieldElements()) { + Member member = referenceElement.getMember(); + if (member instanceof Field) { + Field field = (Field) member; + DependencyDescriptor dependencyDescriptor = new DependencyDescriptor(field, true); + registerProxyIfNecessary(runtimeHints, dependencyDescriptor); + } + } + } + if (!CollectionUtils.isEmpty(this.annotatedInjectionMetadata.getMethodElements())) { + for (AnnotatedInjectElement referenceElement : this.annotatedInjectionMetadata.getMethodElements()) { + Member member = referenceElement.getMember(); + if (member instanceof Method) { + Method method = (Method) member; + Class[] parameterTypes = method.getParameterTypes(); + for (int i = 0; i < parameterTypes.length; i++) { + MethodParameter methodParam = new MethodParameter(method, i); + DependencyDescriptor dependencyDescriptor = new DependencyDescriptor(methodParam, true); + registerProxyIfNecessary(runtimeHints, dependencyDescriptor); + } + } + } + } + } + + private void registerProxyIfNecessary(RuntimeHints runtimeHints, DependencyDescriptor dependencyDescriptor) { + if (this.candidateResolver != null) { + Class proxyClass = + this.candidateResolver.getLazyResolutionProxyClass(dependencyDescriptor, null); + if (proxyClass != null) { + ClassHintUtils.registerProxyIfNecessary(proxyClass, runtimeHints); + } + } + } + + } +} diff --git a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java new file mode 100644 index 00000000000..6254c702ae0 --- /dev/null +++ b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.config.spring6.beans.factory.annotation; + +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.config.annotation.Service; +import org.apache.dubbo.config.spring.ServiceBean; +import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; +import org.apache.dubbo.config.spring.schema.AnnotationBeanDefinitionParser; +import org.springframework.aot.generate.GenerationContext; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.TypeReference; +import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; +import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor; +import org.springframework.beans.factory.aot.BeanRegistrationCode; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; +import org.springframework.beans.factory.support.RegisteredBean; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.beans.factory.xml.BeanDefinitionParser; + +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collectors; + +import static java.util.Arrays.asList; + +/** + * A {@link BeanFactoryPostProcessor} used for processing of {@link Service @Service} annotated classes and annotated bean in java config classes. + * It's also the infrastructure class of XML {@link BeanDefinitionParser} on <dubbo:annotation /> + * + * @see AnnotationBeanDefinitionParser + * @see BeanDefinitionRegistryPostProcessor + * @since 3.2 + */ +public class ServiceAnnotationWithAotPostProcessor extends ServiceAnnotationPostProcessor implements BeanRegistrationAotProcessor { + + private final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(getClass()); + + public ServiceAnnotationWithAotPostProcessor(String... packagesToScan) { + super(packagesToScan); + } + + public ServiceAnnotationWithAotPostProcessor(Collection packagesToScan) { + super(packagesToScan); + } + + @Override + public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { + Class beanClass = registeredBean.getBeanClass(); + if (beanClass.equals(ServiceBean.class)) { + RootBeanDefinition beanDefinition = registeredBean.getMergedBeanDefinition(); + String interfaceName = (String) beanDefinition.getPropertyValues().get("interface"); + try { + Class c = Class.forName(interfaceName); + return new DubboServiceBeanRegistrationAotContribution(c); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else if (servicePackagesHolder.isClassScanned(beanClass.getName())) { + return new DubboServiceBeanRegistrationAotContribution(beanClass); + } + + return null; + } + + private static class DubboServiceBeanRegistrationAotContribution implements BeanRegistrationAotContribution { + + private final Class cl; + + public DubboServiceBeanRegistrationAotContribution(Class cl) { + this.cl = cl; + } + + @Override + public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) { + generationContext.getRuntimeHints().reflection().registerType(TypeReference.of(cl), + MemberCategory.INVOKE_PUBLIC_METHODS); + + } + } + +} diff --git a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/AutowiredElementResolver.java b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/AutowiredElementResolver.java new file mode 100644 index 00000000000..b71411b9958 --- /dev/null +++ b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/AutowiredElementResolver.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.config.spring6.beans.factory.aot; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.beans.factory.config.DependencyDescriptor; +import org.springframework.core.log.LogMessage; + +import javax.lang.model.element.Element; +import java.util.Set; + +/** + * Base class for resolvers that support autowiring related to an + * {@link Element}. + */ +abstract class AutowiredElementResolver { + + private final Log logger = LogFactory.getLog(getClass()); + + protected final void registerDependentBeans(ConfigurableBeanFactory beanFactory, + String beanName, Set autowiredBeanNames) { + + for (String autowiredBeanName : autowiredBeanNames) { + if (beanFactory.containsBean(autowiredBeanName)) { + beanFactory.registerDependentBean(autowiredBeanName, beanName); + } + logger.trace(LogMessage.format( + "Autowiring by type from bean name %s' to bean named '%s'", beanName, + autowiredBeanName)); + } + } + + + /** + * {@link DependencyDescriptor} that supports shortcut bean resolution. + */ + @SuppressWarnings("serial") + static class ShortcutDependencyDescriptor extends DependencyDescriptor { + + private final String shortcut; + + private final Class requiredType; + + + public ShortcutDependencyDescriptor(DependencyDescriptor original, + String shortcut, Class requiredType) { + super(original); + this.shortcut = shortcut; + this.requiredType = requiredType; + } + + + @Override + public Object resolveShortcut(BeanFactory beanFactory) { + return beanFactory.getBean(this.shortcut, this.requiredType); + } + } + +} diff --git a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedFieldValueResolver.java b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedFieldValueResolver.java new file mode 100644 index 00000000000..d89e7ddbabe --- /dev/null +++ b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedFieldValueResolver.java @@ -0,0 +1,210 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.config.spring6.beans.factory.aot; + +import org.apache.dubbo.config.spring6.beans.factory.annotation.ReferenceAnnotationWithAotBeanPostProcessor; +import org.springframework.aot.hint.ExecutableMode; +import org.springframework.beans.BeansException; +import org.springframework.beans.TypeConverter; +import org.springframework.beans.factory.InjectionPoint; +import org.springframework.beans.factory.UnsatisfiedDependencyException; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.beans.factory.config.DependencyDescriptor; +import org.springframework.beans.factory.support.RegisteredBean; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; +import org.springframework.util.function.ThrowingConsumer; + +import java.lang.reflect.Field; +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * Resolver used to support the autowiring of fields. Typically used in + * AOT-processed applications as a targeted alternative to the + * {@link ReferenceAnnotationWithAotBeanPostProcessor + * ReferenceAnnotationBeanPostProcessor}. + * + *

When resolving arguments in a native image, the {@link Field} being used must + * be marked with an {@link ExecutableMode#INTROSPECT introspection} hint so + * that field annotations can be read. Full {@link ExecutableMode#INVOKE + * invocation} hints are only required if the + * {@link #resolveAndSet(RegisteredBean, Object)} method of this class is being + * used (typically to support private fields). + * + */ +public final class ReferencedFieldValueResolver extends AutowiredElementResolver { + + private final String fieldName; + + private final boolean required; + + @Nullable + private final String shortcut; + + + private ReferencedFieldValueResolver(String fieldName, boolean required, + @Nullable String shortcut) { + + Assert.hasText(fieldName, "'fieldName' must not be empty"); + this.fieldName = fieldName; + this.required = required; + this.shortcut = shortcut; + } + + + /** + * Create a new {@link ReferencedFieldValueResolver} for the specified field + * where injection is optional. + * @param fieldName the field name + * @return a new {@link ReferencedFieldValueResolver} instance + */ + public static ReferencedFieldValueResolver forField(String fieldName) { + return new ReferencedFieldValueResolver(fieldName, false, null); + } + + /** + * Create a new {@link ReferencedFieldValueResolver} for the specified field + * where injection is required. + * @param fieldName the field name + * @return a new {@link ReferencedFieldValueResolver} instance + */ + public static ReferencedFieldValueResolver forRequiredField(String fieldName) { + return new ReferencedFieldValueResolver(fieldName, true, null); + } + + + /** + * Return a new {@link ReferencedFieldValueResolver} instance that uses a + * direct bean name injection shortcut. + * @param beanName the bean name to use as a shortcut + * @return a new {@link ReferencedFieldValueResolver} instance that uses the + * shortcuts + */ + public ReferencedFieldValueResolver withShortcut(String beanName) { + return new ReferencedFieldValueResolver(this.fieldName, this.required, beanName); + } + + /** + * Resolve the field for the specified registered bean and provide it to the + * given action. + * @param registeredBean the registered bean + * @param action the action to execute with the resolved field value + */ + public void resolve(RegisteredBean registeredBean, ThrowingConsumer action) { + Assert.notNull(registeredBean, "'registeredBean' must not be null"); + Assert.notNull(action, "'action' must not be null"); + T resolved = resolve(registeredBean); + if (resolved != null) { + action.accept(resolved); + } + } + + /** + * Resolve the field value for the specified registered bean. + * @param registeredBean the registered bean + * @param requiredType the required type + * @return the resolved field value + */ + @Nullable + @SuppressWarnings("unchecked") + public T resolve(RegisteredBean registeredBean, Class requiredType) { + Object value = resolveObject(registeredBean); + Assert.isInstanceOf(requiredType, value); + return (T) value; + } + + /** + * Resolve the field value for the specified registered bean. + * @param registeredBean the registered bean + * @return the resolved field value + */ + @Nullable + @SuppressWarnings("unchecked") + public T resolve(RegisteredBean registeredBean) { + return (T) resolveObject(registeredBean); + } + + /** + * Resolve the field value for the specified registered bean. + * @param registeredBean the registered bean + * @return the resolved field value + */ + @Nullable + public Object resolveObject(RegisteredBean registeredBean) { + Assert.notNull(registeredBean, "'registeredBean' must not be null"); + return resolveValue(registeredBean, getField(registeredBean)); + } + + /** + * Resolve the field value for the specified registered bean and set it + * using reflection. + * @param registeredBean the registered bean + * @param instance the bean instance + */ + public void resolveAndSet(RegisteredBean registeredBean, Object instance) { + Assert.notNull(registeredBean, "'registeredBean' must not be null"); + Assert.notNull(instance, "'instance' must not be null"); + Field field = getField(registeredBean); + Object resolved = resolveValue(registeredBean, field); + if (resolved != null) { + ReflectionUtils.makeAccessible(field); + ReflectionUtils.setField(field, instance, resolved); + } + } + + @Nullable + private Object resolveValue(RegisteredBean registeredBean, Field field) { + String beanName = registeredBean.getBeanName(); + Class beanClass = registeredBean.getBeanClass(); + ConfigurableBeanFactory beanFactory = registeredBean.getBeanFactory(); + DependencyDescriptor descriptor = new DependencyDescriptor(field, this.required); + descriptor.setContainingClass(beanClass); + if (this.shortcut != null) { + descriptor = new ShortcutDependencyDescriptor(descriptor, this.shortcut, + field.getType()); + } + Set autowiredBeanNames = new LinkedHashSet<>(1); + TypeConverter typeConverter = beanFactory.getTypeConverter(); + try { + Assert.isInstanceOf(AutowireCapableBeanFactory.class, beanFactory); + + Object injectedObject = beanFactory.getBean(shortcut); + + + Object value = ((AutowireCapableBeanFactory) beanFactory).resolveDependency( + descriptor, beanName, autowiredBeanNames, typeConverter); + registerDependentBeans(beanFactory, beanName, autowiredBeanNames); + return injectedObject; + } + catch (BeansException ex) { + throw new UnsatisfiedDependencyException(null, beanName, + new InjectionPoint(field), ex); + } + } + + private Field getField(RegisteredBean registeredBean) { + Field field = ReflectionUtils.findField(registeredBean.getBeanClass(), + this.fieldName); + Assert.notNull(field, () -> "No field '" + this.fieldName + "' found on " + + registeredBean.getBeanClass().getName()); + return field; + } + +} diff --git a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedMethodArgumentsResolver.java b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedMethodArgumentsResolver.java new file mode 100644 index 00000000000..32fdd9e1a9c --- /dev/null +++ b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedMethodArgumentsResolver.java @@ -0,0 +1,222 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.config.spring6.beans.factory.aot; + +import org.apache.dubbo.config.spring6.beans.factory.annotation.ReferenceAnnotationWithAotBeanPostProcessor; +import org.springframework.aot.hint.ExecutableMode; +import org.springframework.beans.BeansException; +import org.springframework.beans.TypeConverter; +import org.springframework.beans.factory.InjectionPoint; +import org.springframework.beans.factory.UnsatisfiedDependencyException; +import org.springframework.beans.factory.aot.AutowiredArguments; +import org.springframework.beans.factory.aot.AutowiredFieldValueResolver; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.beans.factory.config.DependencyDescriptor; +import org.springframework.beans.factory.support.RegisteredBean; +import org.springframework.core.MethodParameter; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; +import org.springframework.util.function.ThrowingConsumer; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Resolver used to support the autowiring of methods. Typically used in + * AOT-processed applications as a targeted alternative to the + * {@link ReferenceAnnotationWithAotBeanPostProcessor + * ReferenceAnnotationBeanPostProcessor}. + * + *

When resolving arguments in a native image, the {@link Method} being used + * must be marked with an {@link ExecutableMode#INTROSPECT introspection} hint + * so that field annotations can be read. Full {@link ExecutableMode#INVOKE + * invocation} hints are only required if the + * {@link #resolveAndInvoke(RegisteredBean, Object)} method of this class is + * being used (typically to support private methods). + * + */ +public final class ReferencedMethodArgumentsResolver extends AutowiredElementResolver { + + private final String methodName; + + private final Class[] parameterTypes; + + private final boolean required; + + @Nullable + private final String[] shortcuts; + + + private ReferencedMethodArgumentsResolver(String methodName, Class[] parameterTypes, + boolean required, @Nullable String[] shortcuts) { + + Assert.hasText(methodName, "'methodName' must not be empty"); + this.methodName = methodName; + this.parameterTypes = parameterTypes; + this.required = required; + this.shortcuts = shortcuts; + } + + /** + * Create a new {@link ReferencedMethodArgumentsResolver} for the specified + * method where injection is optional. + * + * @param methodName the method name + * @param parameterTypes the factory method parameter types + * @return a new {@link org.springframework.beans.factory.aot.AutowiredFieldValueResolver} instance + */ + public static ReferencedMethodArgumentsResolver forMethod(String methodName, + Class... parameterTypes) { + + return new ReferencedMethodArgumentsResolver(methodName, parameterTypes, false, + null); + } + + /** + * Create a new {@link ReferencedMethodArgumentsResolver} for the specified + * method where injection is required. + * + * @param methodName the method name + * @param parameterTypes the factory method parameter types + * @return a new {@link AutowiredFieldValueResolver} instance + */ + public static ReferencedMethodArgumentsResolver forRequiredMethod(String methodName, + Class... parameterTypes) { + + return new ReferencedMethodArgumentsResolver(methodName, parameterTypes, true, + null); + } + + /** + * Return a new {@link ReferencedMethodArgumentsResolver} instance + * that uses direct bean name injection shortcuts for specific parameters. + * + * @param beanNames the bean names to use as shortcuts (aligned with the + * method parameters) + * @return a new {@link ReferencedMethodArgumentsResolver} instance that uses + * the shortcuts + */ + public ReferencedMethodArgumentsResolver withShortcut(String... beanNames) { + return new ReferencedMethodArgumentsResolver(this.methodName, this.parameterTypes, + this.required, beanNames); + } + + /** + * Resolve the method arguments for the specified registered bean and + * provide it to the given action. + * + * @param registeredBean the registered bean + * @param action the action to execute with the resolved method arguments + */ + public void resolve(RegisteredBean registeredBean, + ThrowingConsumer action) { + + Assert.notNull(registeredBean, "'registeredBean' must not be null"); + Assert.notNull(action, "'action' must not be null"); + AutowiredArguments resolved = resolve(registeredBean); + if (resolved != null) { + action.accept(resolved); + } + } + + /** + * Resolve the method arguments for the specified registered bean. + * + * @param registeredBean the registered bean + * @return the resolved method arguments + */ + @Nullable + public AutowiredArguments resolve(RegisteredBean registeredBean) { + Assert.notNull(registeredBean, "'registeredBean' must not be null"); + return resolveArguments(registeredBean, getMethod(registeredBean)); + } + + /** + * Resolve the method arguments for the specified registered bean and invoke + * the method using reflection. + * + * @param registeredBean the registered bean + * @param instance the bean instance + */ + public void resolveAndInvoke(RegisteredBean registeredBean, Object instance) { + Assert.notNull(registeredBean, "'registeredBean' must not be null"); + Assert.notNull(instance, "'instance' must not be null"); + Method method = getMethod(registeredBean); + AutowiredArguments resolved = resolveArguments(registeredBean, method); + if (resolved != null) { + ReflectionUtils.makeAccessible(method); + ReflectionUtils.invokeMethod(method, instance, resolved.toArray()); + } + } + + @Nullable + private AutowiredArguments resolveArguments(RegisteredBean registeredBean, + Method method) { + + String beanName = registeredBean.getBeanName(); + Class beanClass = registeredBean.getBeanClass(); + ConfigurableBeanFactory beanFactory = registeredBean.getBeanFactory(); + Assert.isInstanceOf(AutowireCapableBeanFactory.class, beanFactory); + AutowireCapableBeanFactory autowireCapableBeanFactory = (AutowireCapableBeanFactory) beanFactory; + int argumentCount = method.getParameterCount(); + Object[] arguments = new Object[argumentCount]; + Set autowiredBeanNames = new LinkedHashSet<>(argumentCount); + TypeConverter typeConverter = beanFactory.getTypeConverter(); + for (int i = 0; i < argumentCount; i++) { + MethodParameter parameter = new MethodParameter(method, i); + DependencyDescriptor descriptor = new DependencyDescriptor(parameter, + this.required); + descriptor.setContainingClass(beanClass); + String shortcut = (this.shortcuts != null) ? this.shortcuts[i] : null; + if (shortcut != null) { + descriptor = new ShortcutDependencyDescriptor(descriptor, shortcut, + parameter.getParameterType()); + } + try { + Object injectedArgument = beanFactory.getBean(shortcut); + Object argument = autowireCapableBeanFactory.resolveDependency(descriptor, + beanName, autowiredBeanNames, typeConverter); + arguments[i] = injectedArgument; + } catch (BeansException ex) { + throw new UnsatisfiedDependencyException(null, beanName, + new InjectionPoint(parameter), ex); + } + } + registerDependentBeans(beanFactory, beanName, autowiredBeanNames); + return AutowiredArguments.of(arguments); + } + + private Method getMethod(RegisteredBean registeredBean) { + Method method = ReflectionUtils.findMethod(registeredBean.getBeanClass(), + this.methodName, this.parameterTypes); + Assert.notNull(method, () -> + "Method '" + this.methodName + "' with parameter types [" + toCommaSeparatedNames(this.parameterTypes) + "] declared on " + registeredBean.getBeanClass().getName() + " could not be found."); + return method; + } + + private String toCommaSeparatedNames(Class... parameterTypes) { + return Arrays.stream(parameterTypes).map(Class::getName) + .collect(Collectors.joining(", ")); + } + +} diff --git a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/context/DubboInfraBeanRegisterPostProcessor.java b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/context/DubboInfraBeanRegisterPostProcessor.java new file mode 100644 index 00000000000..3595122551d --- /dev/null +++ b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/context/DubboInfraBeanRegisterPostProcessor.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.config.spring6.context; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; + + +/** + * Register some infrastructure beans if not exists. + * This post-processor MUST impl BeanDefinitionRegistryPostProcessor, + * in order to enable the registered BeanFactoryPostProcessor bean to be loaded and executed. + * + * @see org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors( + *ConfigurableListableBeanFactory, java.util.List) + */ +public class DubboInfraBeanRegisterPostProcessor implements BeanDefinitionRegistryPostProcessor { + + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + } + +} diff --git a/dubbo-config/pom.xml b/dubbo-config/pom.xml index dcbb5355ebb..8fe60edd832 100644 --- a/dubbo-config/pom.xml +++ b/dubbo-config/pom.xml @@ -32,6 +32,7 @@ dubbo-config-api dubbo-config-spring + dubbo-config-spring6 diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index 1fb37abbc7e..ae098363611 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -102,7 +102,7 @@ 4.5.14 4.4.16 1.2.83 - 2.0.23 + 2.0.27 3.4.14 4.3.0 2.12.0 diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml index ade64fe84d5..8c86ea543b4 100644 --- a/dubbo-distribution/dubbo-all/pom.xml +++ b/dubbo-distribution/dubbo-all/pom.xml @@ -1315,6 +1315,20 @@ + + + META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar + + + + + + META-INF/dubbo/internal/org.apache.dubbo.aot.api.ProxyDescriberRegistrar + + + diff --git a/dubbo-metadata/dubbo-metadata-api/pom.xml b/dubbo-metadata/dubbo-metadata-api/pom.xml index c951e1d36b3..5557b161377 100644 --- a/dubbo-metadata/dubbo-metadata-api/pom.xml +++ b/dubbo-metadata/dubbo-metadata-api/pom.xml @@ -85,6 +85,12 @@ compile + + org.apache.dubbo + dubbo-native + ${project.parent.version} + + diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/aot/MetadataProxyDescriberRegistrar.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/aot/MetadataProxyDescriberRegistrar.java new file mode 100644 index 00000000000..04db2f81db7 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/aot/MetadataProxyDescriberRegistrar.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.metadata.aot; + +import org.apache.dubbo.aot.api.JdkProxyDescriber; +import org.apache.dubbo.aot.api.ProxyDescriberRegistrar; +import org.apache.dubbo.metadata.MetadataService; +import org.apache.dubbo.rpc.service.Destroyable; +import org.apache.dubbo.rpc.service.EchoService; + +import java.util.ArrayList; +import java.util.List; + +public class MetadataProxyDescriberRegistrar implements ProxyDescriberRegistrar { + @Override + public List getJdkProxyDescribers() { + List describers = new ArrayList<>(); + describers.add(buildJdkProxyDescriber(MetadataService.class)); + return describers; + } + + private JdkProxyDescriber buildJdkProxyDescriber(Class cl) { + List proxiedInterfaces = new ArrayList<>(); + proxiedInterfaces.add(cl.getName()); + proxiedInterfaces.add(EchoService.class.getName()); + proxiedInterfaces.add(Destroyable.class.getName()); + return new JdkProxyDescriber(proxiedInterfaces, null); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/aot/MetadataReflectionTypeDescriberRegistrar.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/aot/MetadataReflectionTypeDescriberRegistrar.java new file mode 100644 index 00000000000..46ba6b2e04e --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/aot/MetadataReflectionTypeDescriberRegistrar.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.metadata.aot; + +import org.apache.dubbo.aot.api.MemberCategory; +import org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar; +import org.apache.dubbo.aot.api.TypeDescriber; +import org.apache.dubbo.metadata.MetadataInfo; +import org.apache.dubbo.metadata.MetadataService; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + + +public class MetadataReflectionTypeDescriberRegistrar implements ReflectionTypeDescriberRegistrar { + + @Override + public List getTypeDescribers() { + List typeDescribers = new ArrayList<>(); + typeDescribers.add(buildTypeDescriberWithPublicMethod(MetadataService.class)); + typeDescribers.add(buildTypeDescriberWithDeclaredConstructors(MetadataInfo.class)); + return typeDescribers; + } + + private TypeDescriber buildTypeDescriberWithPublicMethod(Class cl) { + Set memberCategories = new HashSet<>(); + memberCategories.add(MemberCategory.INVOKE_PUBLIC_METHODS); + return new TypeDescriber(cl.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories); + } + + private TypeDescriber buildTypeDescriberWithDeclaredConstructors(Class cl) { + Set memberCategories = new HashSet<>(); + memberCategories.add(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); + return new TypeDescriber(cl.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ProxyDescriberRegistrar b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ProxyDescriberRegistrar new file mode 100644 index 00000000000..c49ddd67ca7 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ProxyDescriberRegistrar @@ -0,0 +1 @@ +metadata=org.apache.dubbo.metadata.aot.MetadataProxyDescriberRegistrar diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar new file mode 100644 index 00000000000..d6dae5fb5f6 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar @@ -0,0 +1 @@ +metadata=org.apache.dubbo.metadata.aot.MetadataReflectionTypeDescriberRegistrar diff --git a/dubbo-metrics/dubbo-metrics-default/pom.xml b/dubbo-metrics/dubbo-metrics-default/pom.xml index 87ec6a3b9bc..27e5ccfe825 100644 --- a/dubbo-metrics/dubbo-metrics-default/pom.xml +++ b/dubbo-metrics/dubbo-metrics-default/pom.xml @@ -36,6 +36,13 @@ dubbo-metrics-api ${project.parent.version} + + + org.apache.dubbo + dubbo-native + ${project.parent.version} + + io.micrometer micrometer-test diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/aot/DefaultMetricsReflectionTypeDescriberRegistrar.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/aot/DefaultMetricsReflectionTypeDescriberRegistrar.java new file mode 100644 index 00000000000..0a0ea43762d --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/aot/DefaultMetricsReflectionTypeDescriberRegistrar.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.metrics.aot; + +import org.apache.dubbo.aot.api.MemberCategory; +import org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar; +import org.apache.dubbo.aot.api.TypeDescriber; +import org.apache.dubbo.metrics.collector.HistogramMetricsCollector; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class DefaultMetricsReflectionTypeDescriberRegistrar implements ReflectionTypeDescriberRegistrar { + + @Override + public List getTypeDescribers() { + List typeDescribers = new ArrayList<>(); + typeDescribers.add(buildTypeDescriberWithDeclaredConstructors(HistogramMetricsCollector.class)); + return typeDescribers; + } + + private TypeDescriber buildTypeDescriberWithDeclaredConstructors(Class cl) { + Set memberCategories = new HashSet<>(); + memberCategories.add(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); + return new TypeDescriber(cl.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories); + } +} diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar b/dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar new file mode 100644 index 00000000000..3b3accbdcf1 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar @@ -0,0 +1 @@ +defaultMetrics=org.apache.dubbo.metrics.aot.DefaultMetricsReflectionTypeDescriberRegistrar diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metrics.collector.MetricsCollector b/dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metrics.collector.MetricsCollector new file mode 100644 index 00000000000..488b68d50fe --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metrics.collector.MetricsCollector @@ -0,0 +1,3 @@ +default=org.apache.dubbo.metrics.collector.DefaultMetricsCollector +aggregateMetricsCollector=org.apache.dubbo.metrics.collector.AggregateMetricsCollector +configCenterMetricsCollector=org.apache.dubbo.metrics.collector.ConfigCenterMetricsCollector diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ConditionalDescriber.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ConditionalDescriber.java similarity index 96% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ConditionalDescriber.java rename to dubbo-native/src/main/java/org/apache/dubbo/aot/api/ConditionalDescriber.java index bf158f05008..7a291743a7d 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ConditionalDescriber.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ConditionalDescriber.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.aot.generate; +package org.apache.dubbo.aot.api; /** * A describer that describes the conditions for the configuration to take effect. diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableMode.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ExecutableMode.java similarity index 97% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableMode.java rename to dubbo-native/src/main/java/org/apache/dubbo/aot/api/ExecutableMode.java index c5ea9bd02a1..a44fe7f06d7 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableMode.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ExecutableMode.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.apache.dubbo.aot.generate; +package org.apache.dubbo.aot.api; import java.lang.reflect.Executable; diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/FieldDescriber.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/FieldDescriber.java similarity index 96% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/FieldDescriber.java rename to dubbo-native/src/main/java/org/apache/dubbo/aot/api/FieldDescriber.java index d38b8fbe92b..055610caa0f 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/FieldDescriber.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/FieldDescriber.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.aot.generate; +package org.apache.dubbo.aot.api; import java.lang.reflect.Field; diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/JdkProxyDescriber.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/JdkProxyDescriber.java new file mode 100644 index 00000000000..325f544132d --- /dev/null +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/JdkProxyDescriber.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.aot.api; + +import java.util.List; +import java.util.Objects; + +/** + * A describer that describes the need for a JDK interface-based {@link java.lang.reflect.Proxy}. + */ +public class JdkProxyDescriber implements ConditionalDescriber { + + private final List proxiedInterfaces; + + private final String reachableType; + + + public JdkProxyDescriber(List proxiedInterfaces, String reachableType) { + this.proxiedInterfaces = proxiedInterfaces; + this.reachableType = reachableType; + } + + public List getProxiedInterfaces() { + return proxiedInterfaces; + } + + @Override + public String getReachableType() { + return reachableType; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + JdkProxyDescriber that = (JdkProxyDescriber) o; + return Objects.equals(proxiedInterfaces, that.proxiedInterfaces) && Objects.equals(reachableType, that.reachableType); + } + + @Override + public int hashCode() { + return Objects.hash(proxiedInterfaces, reachableType); + } +} diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/MemberCategory.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java similarity index 98% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/MemberCategory.java rename to dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java index 7da49da4fbc..fc8659d05f3 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/MemberCategory.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.apache.dubbo.aot.generate; +package org.apache.dubbo.aot.api; import java.lang.reflect.Constructor; import java.lang.reflect.Field; diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/MemberDescriber.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberDescriber.java similarity index 96% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/MemberDescriber.java rename to dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberDescriber.java index 2e66c3d6625..8579d6a3f24 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/MemberDescriber.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberDescriber.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.aot.generate; +package org.apache.dubbo.aot.api; import java.lang.reflect.Member; diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ProxyDescriberRegistrar.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ProxyDescriberRegistrar.java new file mode 100644 index 00000000000..85377c5df64 --- /dev/null +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ProxyDescriberRegistrar.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.aot.api; + +import org.apache.dubbo.common.extension.SPI; + +import java.util.List; + +@SPI +public interface ProxyDescriberRegistrar { + List getJdkProxyDescribers(); +} diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ReflectionTypeDescriberRegistrar.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ReflectionTypeDescriberRegistrar.java new file mode 100644 index 00000000000..beffa897751 --- /dev/null +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ReflectionTypeDescriberRegistrar.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.aot.api; + +import org.apache.dubbo.common.extension.SPI; + +import java.util.List; + +@SPI +public interface ReflectionTypeDescriberRegistrar { + List getTypeDescribers(); +} diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceBundleDescriber.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceBundleDescriber.java similarity index 98% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceBundleDescriber.java rename to dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceBundleDescriber.java index 35fab65e49a..0e640974aa4 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceBundleDescriber.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceBundleDescriber.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.aot.generate; +package org.apache.dubbo.aot.api; import java.util.List; import java.util.Objects; diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceDescriberRegistrar.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceDescriberRegistrar.java new file mode 100644 index 00000000000..bb18dd1f3d6 --- /dev/null +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceDescriberRegistrar.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.aot.api; + +import org.apache.dubbo.common.extension.SPI; + +import java.util.List; + +@SPI +public interface ResourceDescriberRegistrar { + List getResourcePatternDescribers(); + + List getResourceBundleDescribers(); +} diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourcePatternDescriber.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourcePatternDescriber.java similarity index 97% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourcePatternDescriber.java rename to dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourcePatternDescriber.java index 1e557c7330a..d52ea4d2b91 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourcePatternDescriber.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourcePatternDescriber.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.aot.generate; +package org.apache.dubbo.aot.api; import java.util.Arrays; import java.util.regex.Pattern; diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/TypeDescriber.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/TypeDescriber.java similarity index 95% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/TypeDescriber.java rename to dubbo-native/src/main/java/org/apache/dubbo/aot/api/TypeDescriber.java index a41f0bb2b88..37451b6baa3 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/TypeDescriber.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/api/TypeDescriber.java @@ -14,7 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.aot.generate; +package org.apache.dubbo.aot.api; + +import org.apache.dubbo.aot.generate.ExecutableDescriber; import java.util.Set; diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/AotProcessor.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/AotProcessor.java index c375c0934fc..a2c15e4bf7d 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/AotProcessor.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/AotProcessor.java @@ -16,6 +16,12 @@ */ package org.apache.dubbo.aot.generate; +import org.apache.dubbo.aot.api.JdkProxyDescriber; +import org.apache.dubbo.aot.api.ProxyDescriberRegistrar; +import org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar; +import org.apache.dubbo.aot.api.TypeDescriber; +import org.apache.dubbo.rpc.model.FrameworkModel; + import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; @@ -44,10 +50,31 @@ public static void main(String[] args) { .registerSpiExtensionType(new ArrayList<>(ClassSourceScanner.INSTANCE.distinctSpiExtensionClasses(ResourceScanner.INSTANCE.distinctSpiResource()).values())) .registerAdaptiveType(new ArrayList<>(ClassSourceScanner.INSTANCE.adaptiveClasses().values())) .registerBeanType(ClassSourceScanner.INSTANCE.scopeModelInitializer()) - .registerConfigType(ClassSourceScanner.INSTANCE.configClasses()); + .registerConfigType(ClassSourceScanner.INSTANCE.configClasses()) + .registerTypeDescriber(getTypes()); writer.writeReflectionConfig(reflectRepository); + ProxyConfigMetadataRepository proxyRepository = new ProxyConfigMetadataRepository(); + proxyRepository.registerProxyDescribers(getProxyDescribers()); + writer.writeProxyConfig(proxyRepository); + } + + private static List getTypes() { + List typeDescribers = new ArrayList<>(); + FrameworkModel.defaultModel().defaultApplication().getExtensionLoader(ReflectionTypeDescriberRegistrar.class).getSupportedExtensionInstances().forEach(reflectionTypeDescriberRegistrar -> { + typeDescribers.addAll(reflectionTypeDescriberRegistrar.getTypeDescribers()); + }); + + return typeDescribers; + } + + private static List getProxyDescribers() { + List jdkProxyDescribers = new ArrayList<>(); + FrameworkModel.defaultModel().defaultApplication().getExtensionLoader(ProxyDescriberRegistrar.class).getSupportedExtensionInstances().forEach(reflectionTypeDescriberRegistrar -> { + jdkProxyDescribers.addAll(reflectionTypeDescriberRegistrar.getJdkProxyDescribers()); + }); + return jdkProxyDescribers; } diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableDescriber.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableDescriber.java index 3423a50e007..b272a17a2bb 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableDescriber.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableDescriber.java @@ -17,6 +17,9 @@ package org.apache.dubbo.aot.generate; +import org.apache.dubbo.aot.api.ExecutableMode; +import org.apache.dubbo.aot.api.MemberDescriber; + import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.util.Arrays; diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/JarScanner.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/JarScanner.java index e39da4818ce..52b06593559 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/JarScanner.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/JarScanner.java @@ -93,7 +93,6 @@ private void scanFile(String resource) { File[] listFiles = directory.listFiles(); if (listFiles != null) { for (File file : listFiles) { - System.out.println("scanFile: " + file.getPath()); if (file.isDirectory()) { scanFile(file.getPath()); } else { diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/NativeConfigurationWriter.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/NativeConfigurationWriter.java index 86299d02af6..88770d54842 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/NativeConfigurationWriter.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/NativeConfigurationWriter.java @@ -27,6 +27,7 @@ * Write Write configuration metadata information in * {@link ResourceConfigMetadataRepository} and {@link ReflectConfigMetadataRepository} * as GraalVM native configuration. + * * @see Native Image Build Configuration */ public class NativeConfigurationWriter { @@ -49,8 +50,7 @@ protected void writeTo(String fileName, Consumer writer) { try (FileWriter out = new FileWriter(file)) { writer.accept(createJsonWriter(out)); } - } - catch (IOException ex) { + } catch (IOException ex) { throw new IllegalStateException("Failed to write native configuration for " + fileName, ex); } } @@ -58,7 +58,7 @@ protected void writeTo(String fileName, Consumer writer) { private File createIfNecessary(String filename) throws IOException { Path outputDirectory = this.basePath.resolve("META-INF").resolve("native-image"); if (this.groupId != null && this.artifactId != null) { - outputDirectory = outputDirectory.resolve(this.groupId).resolve(this.artifactId); + outputDirectory = outputDirectory.resolve(this.groupId).resolve(this.artifactId).resolve("dubbo"); } outputDirectory.toFile().mkdirs(); File file = outputDirectory.resolve(filename).toFile(); @@ -77,6 +77,11 @@ public void writeResourceConfig(ResourceConfigMetadataRepository repository) { ResourceConfigWriter.INSTANCE.write(writer, repository)); } + public void writeProxyConfig(ProxyConfigMetadataRepository repository) { + writeTo("proxy-config.json", writer -> + ProxyConfigWriter.INSTANCE.write(writer, repository)); + } + private BasicJsonWriter createJsonWriter(Writer out) { return new BasicJsonWriter(out); } diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigMetadataRepository.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigMetadataRepository.java new file mode 100644 index 00000000000..25b89d8844b --- /dev/null +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigMetadataRepository.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.aot.generate; + + +import org.apache.dubbo.aot.api.JdkProxyDescriber; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +public class ProxyConfigMetadataRepository { + + private final Set jdkProxyDescribers; + + public ProxyConfigMetadataRepository() { + this.jdkProxyDescribers = new LinkedHashSet<>(); + } + + public ProxyConfigMetadataRepository registerProxyDescriber(JdkProxyDescriber describer) { + this.jdkProxyDescribers.add(describer); + return this; + } + + public ProxyConfigMetadataRepository registerProxyDescribers(List describers) { + this.jdkProxyDescribers.addAll(describers.stream().filter(Objects::nonNull).collect(Collectors.toList())); + return this; + } + + + public Set getProxyDescribers() { + return jdkProxyDescribers; + } +} diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigWriter.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigWriter.java new file mode 100644 index 00000000000..ac429341d0f --- /dev/null +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigWriter.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.aot.generate; + +import org.apache.dubbo.aot.api.JdkProxyDescriber; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Write a {@link ProxyConfigMetadataRepository} to the JSON output expected by the GraalVM + * {@code native-image} compiler, typically named {@code proxy-config.json}. + */ +public class ProxyConfigWriter { + + public static final ProxyConfigWriter INSTANCE = new ProxyConfigWriter(); + + public void write(BasicJsonWriter writer, ProxyConfigMetadataRepository repository) { + writer.writeArray(repository.getProxyDescribers().stream().map(this::toAttributes).collect(Collectors.toList())); + } + + private Map toAttributes(JdkProxyDescriber describer) { + Map attributes = new LinkedHashMap<>(); + handleCondition(attributes, describer); + attributes.put("interfaces", describer.getProxiedInterfaces()); + return attributes; + } + + private void handleCondition(Map attributes, JdkProxyDescriber describer) { + if (describer.getReachableType() != null) { + Map conditionAttributes = new LinkedHashMap<>(); + conditionAttributes.put("typeReachable", describer.getReachableType()); + attributes.put("condition", conditionAttributes); + } + } +} diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectConfigMetadataRepository.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectConfigMetadataRepository.java index 1a22d35e33f..5cb546dbd27 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectConfigMetadataRepository.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectConfigMetadataRepository.java @@ -16,6 +16,9 @@ */ package org.apache.dubbo.aot.generate; +import org.apache.dubbo.aot.api.MemberCategory; +import org.apache.dubbo.aot.api.TypeDescriber; + import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -24,7 +27,7 @@ import java.util.Set; import java.util.stream.Collectors; -import static org.apache.dubbo.aot.generate.ExecutableMode.INVOKE; +import static org.apache.dubbo.aot.api.ExecutableMode.INVOKE; public class ReflectConfigMetadataRepository { @@ -34,22 +37,22 @@ public ReflectConfigMetadataRepository() { this.types = new ArrayList<>(); } - public ReflectConfigMetadataRepository registerSpiExtensionType(List> classes) { + protected ReflectConfigMetadataRepository registerSpiExtensionType(List> classes) { types.addAll(classes.stream().filter(Objects::nonNull).map(this::buildTypeDescriberWithConstructor).collect(Collectors.toList())); return this; } - public ReflectConfigMetadataRepository registerAdaptiveType(List> classes) { + protected ReflectConfigMetadataRepository registerAdaptiveType(List> classes) { types.addAll(classes.stream().filter(Objects::nonNull).map(this::buildTypeDescriberWithConstructor).collect(Collectors.toList())); return this; } - public ReflectConfigMetadataRepository registerBeanType(List> classes) { + protected ReflectConfigMetadataRepository registerBeanType(List> classes) { types.addAll(classes.stream().filter(Objects::nonNull).map(this::buildTypeDescriberWithConstructor).collect(Collectors.toList())); return this; } - public ReflectConfigMetadataRepository registerConfigType(List> classes) { + protected ReflectConfigMetadataRepository registerConfigType(List> classes) { types.addAll(classes.stream().filter(Objects::nonNull).map(this::buildTypeDescriberWithConstructor).collect(Collectors.toList())); return this; } @@ -61,6 +64,10 @@ private TypeDescriber buildTypeDescriberWithConstructor(Class c) { return new TypeDescriber(c.getName(), null, new HashSet<>(), constructors, new HashSet<>(), memberCategories); } + public void registerTypeDescriber(List typeDescribers) { + types.addAll(typeDescribers.stream().filter(Objects::nonNull).collect(Collectors.toList())); + } + public List getTypes() { return types; } diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectionConfigWriter.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectionConfigWriter.java index 16ad5cb2110..aed61459921 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectionConfigWriter.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectionConfigWriter.java @@ -16,6 +16,11 @@ */ package org.apache.dubbo.aot.generate; +import org.apache.dubbo.aot.api.ExecutableMode; +import org.apache.dubbo.aot.api.FieldDescriber; +import org.apache.dubbo.aot.api.MemberCategory; +import org.apache.dubbo.aot.api.TypeDescriber; + import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigMetadataRepository.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigMetadataRepository.java index 372d6c40baf..c44ddc08003 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigMetadataRepository.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigMetadataRepository.java @@ -17,6 +17,9 @@ package org.apache.dubbo.aot.generate; +import org.apache.dubbo.aot.api.ResourceBundleDescriber; +import org.apache.dubbo.aot.api.ResourcePatternDescriber; + import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigWriter.java b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigWriter.java index 6d1b551dd6f..bb8c8f58161 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigWriter.java +++ b/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigWriter.java @@ -16,6 +16,10 @@ */ package org.apache.dubbo.aot.generate; +import org.apache.dubbo.aot.api.ConditionalDescriber; +import org.apache.dubbo.aot.api.ResourceBundleDescriber; +import org.apache.dubbo.aot.api.ResourcePatternDescriber; + import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; diff --git a/dubbo-native/src/test/java/org/apache/dubbo/aot/generate/ResourcePatternDescriberTest.java b/dubbo-native/src/test/java/org/apache/dubbo/aot/generate/ResourcePatternDescriberTest.java index dd4e489efc9..f93a953ebf0 100644 --- a/dubbo-native/src/test/java/org/apache/dubbo/aot/generate/ResourcePatternDescriberTest.java +++ b/dubbo-native/src/test/java/org/apache/dubbo/aot/generate/ResourcePatternDescriberTest.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.aot.generate; +import org.apache.dubbo.aot.api.ResourcePatternDescriber; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/dubbo-plugin/dubbo-qos/pom.xml b/dubbo-plugin/dubbo-qos/pom.xml index 3a84b3a798e..1affb789b05 100644 --- a/dubbo-plugin/dubbo-qos/pom.xml +++ b/dubbo-plugin/dubbo-qos/pom.xml @@ -75,5 +75,11 @@ dubbo-qos-api ${project.version} + + + org.apache.dubbo + dubbo-native + ${project.parent.version} + diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/aot/QosReflectionTypeDescriberRegistrar.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/aot/QosReflectionTypeDescriberRegistrar.java new file mode 100644 index 00000000000..d99044f7444 --- /dev/null +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/aot/QosReflectionTypeDescriberRegistrar.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.qos.aot; + +import org.apache.dubbo.aot.api.MemberCategory; +import org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar; +import org.apache.dubbo.aot.api.TypeDescriber; + +import java.nio.channels.spi.SelectorProvider; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + + +public class QosReflectionTypeDescriberRegistrar implements ReflectionTypeDescriberRegistrar { + + @Override + public List getTypeDescribers() { + List typeDescribers = new ArrayList<>(); + typeDescribers.add(buildTypeDescriberWithPublicMethod(SelectorProvider.class)); + return typeDescribers; + } + + private TypeDescriber buildTypeDescriberWithPublicMethod(Class cl) { + Set memberCategories = new HashSet<>(); + memberCategories.add(MemberCategory.INVOKE_PUBLIC_METHODS); + return new TypeDescriber(cl.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories); + } +} diff --git a/dubbo-plugin/dubbo-qos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar b/dubbo-plugin/dubbo-qos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar new file mode 100644 index 00000000000..0da22f85319 --- /dev/null +++ b/dubbo-plugin/dubbo-qos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar @@ -0,0 +1 @@ +qos=org.apache.dubbo.qos.aot.QosReflectionTypeDescriberRegistrar diff --git a/dubbo-registry/dubbo-registry-api/pom.xml b/dubbo-registry/dubbo-registry-api/pom.xml index 4c3a15f3536..c35a64b5782 100644 --- a/dubbo-registry/dubbo-registry-api/pom.xml +++ b/dubbo-registry/dubbo-registry-api/pom.xml @@ -105,5 +105,11 @@ ${project.parent.version} compile + + + org.apache.dubbo + dubbo-native + ${project.parent.version} + diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryScopeModelInitializer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryScopeModelInitializer.java index 6be4e29947a..e2de1cbf86a 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryScopeModelInitializer.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryScopeModelInitializer.java @@ -17,6 +17,7 @@ package org.apache.dubbo.registry; import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; +import org.apache.dubbo.registry.client.metadata.MetadataServiceDelegation; import org.apache.dubbo.registry.support.RegistryManager; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.FrameworkModel; @@ -33,6 +34,7 @@ public void initializeFrameworkModel(FrameworkModel frameworkModel) { public void initializeApplicationModel(ApplicationModel applicationModel) { ScopeBeanFactory beanFactory = applicationModel.getBeanFactory(); beanFactory.registerBean(RegistryManager.class); + beanFactory.registerBean(MetadataServiceDelegation.class); } @Override diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/aot/RegistryReflectionTypeDescriberRegistrar.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/aot/RegistryReflectionTypeDescriberRegistrar.java new file mode 100644 index 00000000000..94d8a635f7f --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/aot/RegistryReflectionTypeDescriberRegistrar.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.registry.aot; + +import org.apache.dubbo.aot.api.MemberCategory; +import org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar; +import org.apache.dubbo.aot.api.TypeDescriber; +import org.apache.dubbo.registry.client.metadata.MetadataServiceDelegation; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + + +public class RegistryReflectionTypeDescriberRegistrar implements ReflectionTypeDescriberRegistrar { + + @Override + public List getTypeDescribers() { + List typeDescribers = new ArrayList<>(); + typeDescribers.add(buildTypeDescriberWithDeclaredMethod(MetadataServiceDelegation.class)); + + return typeDescribers; + } + + private TypeDescriber buildTypeDescriberWithDeclaredMethod(Class cl) { + Set memberCategories = new HashSet<>(); + memberCategories.add(MemberCategory.INVOKE_PUBLIC_METHODS); + memberCategories.add(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); + return new TypeDescriber(cl.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories); + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java index 6434b24ae43..398f5cc55f4 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java @@ -17,6 +17,7 @@ package org.apache.dubbo.registry.client.metadata; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.aot.NativeDetector; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; @@ -141,6 +142,10 @@ public static ProxyHolder referProxy(ServiceInstance instance) { url = url.setServiceModel(consumerModel); + if (NativeDetector.inNativeImage()) { + url = url.addParameter("proxy", "jdk"); + } + Invoker invoker = protocol.refer(MetadataService.class, url); ProxyFactory proxyFactory = applicationModel.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); diff --git a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar new file mode 100644 index 00000000000..cadf42109c5 --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar @@ -0,0 +1 @@ +registry=org.apache.dubbo.registry.aot.RegistryReflectionTypeDescriberRegistrar diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/aot/ZookeeperReflectionTypeDescriberRegistrar.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/aot/ZookeeperReflectionTypeDescriberRegistrar.java new file mode 100644 index 00000000000..e3baf50334d --- /dev/null +++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/aot/ZookeeperReflectionTypeDescriberRegistrar.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.registry.zookeeper.aot; + +import org.apache.dubbo.aot.api.MemberCategory; +import org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar; +import org.apache.dubbo.aot.api.TypeDescriber; +import org.apache.dubbo.registry.zookeeper.ZookeeperInstance; +import org.apache.zookeeper.ClientCnxnSocketNIO; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + + +public class ZookeeperReflectionTypeDescriberRegistrar implements ReflectionTypeDescriberRegistrar { + + @Override + public List getTypeDescribers() { + List typeDescribers = new ArrayList<>(); + typeDescribers.add(buildTypeDescriberWithDeclared(ZookeeperInstance.class)); + + return typeDescribers; + } + + private TypeDescriber buildTypeDescriberWithDeclared(Class cl) { + Set memberCategories = new HashSet<>(); + memberCategories.add(MemberCategory.INVOKE_DECLARED_METHODS); + memberCategories.add(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); + memberCategories.add(MemberCategory.DECLARED_FIELDS); + return new TypeDescriber(cl.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories); + } +} diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar b/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar new file mode 100644 index 00000000000..70b1150d77a --- /dev/null +++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar @@ -0,0 +1 @@ +zookeeper=org.apache.dubbo.registry.zookeeper.aot.ZookeeperReflectionTypeDescriberRegistrar diff --git a/dubbo-remoting/dubbo-remoting-netty4/pom.xml b/dubbo-remoting/dubbo-remoting-netty4/pom.xml index dd8b9d4eaf2..447da39ef61 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/pom.xml +++ b/dubbo-remoting/dubbo-remoting-netty4/pom.xml @@ -69,5 +69,11 @@ linux-aarch_64 runtime + + + org.apache.dubbo + dubbo-native + ${project.parent.version} + diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/aot/Netty4ReflectionTypeDescriberRegistrar.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/aot/Netty4ReflectionTypeDescriberRegistrar.java new file mode 100644 index 00000000000..051d590c2d8 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/aot/Netty4ReflectionTypeDescriberRegistrar.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.remoting.transport.netty4.aot; + +import org.apache.dubbo.aot.api.MemberCategory; +import org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar; +import org.apache.dubbo.aot.api.TypeDescriber; +import org.apache.dubbo.remoting.transport.netty4.NettyClientHandler; +import org.apache.dubbo.remoting.transport.netty4.NettyServerHandler; +import org.apache.dubbo.remoting.transport.netty4.ssl.SslClientTlsHandler; +import org.apache.dubbo.remoting.transport.netty4.ssl.SslServerTlsHandler; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + + +public class Netty4ReflectionTypeDescriberRegistrar implements ReflectionTypeDescriberRegistrar { + + @Override + public List getTypeDescribers() { + List typeDescribers = new ArrayList<>(); + typeDescribers.add(buildTypeDescriberWithDeclaredMethods(NettyServerHandler.class)); + typeDescribers.add(buildTypeDescriberWithDeclaredMethods(SslServerTlsHandler.class)); + typeDescribers.add(buildTypeDescriberWithDeclaredMethods(NettyClientHandler.class)); + typeDescribers.add(buildTypeDescriberWithDeclaredMethods(SslClientTlsHandler.class)); + return typeDescribers; + } + + private TypeDescriber buildTypeDescriberWithDeclaredMethods(Class c){ + Set memberCategories = new HashSet<>(); + memberCategories.add(MemberCategory.INVOKE_DECLARED_METHODS); + return new TypeDescriber(c.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories); + } +} diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar b/dubbo-remoting/dubbo-remoting-netty4/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar new file mode 100644 index 00000000000..be468fd9529 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar @@ -0,0 +1 @@ +netty4=org.apache.dubbo.remoting.transport.netty4.aot.Netty4ReflectionTypeDescriberRegistrar diff --git a/dubbo-remoting/dubbo-remoting-zookeeper-curator5/pom.xml b/dubbo-remoting/dubbo-remoting-zookeeper-curator5/pom.xml index 6209329bb57..fbf14dc7290 100644 --- a/dubbo-remoting/dubbo-remoting-zookeeper-curator5/pom.xml +++ b/dubbo-remoting/dubbo-remoting-zookeeper-curator5/pom.xml @@ -59,5 +59,11 @@ zookeeper ${zookeeper_version} + + + org.apache.dubbo + dubbo-native + ${project.parent.version} + diff --git a/dubbo-remoting/dubbo-remoting-zookeeper-curator5/src/main/java/org/apache/dubbo/remoting/zookeeper/curator5/aot/Curator5ZookeeperReflectionTypeDescriberRegistrar.java b/dubbo-remoting/dubbo-remoting-zookeeper-curator5/src/main/java/org/apache/dubbo/remoting/zookeeper/curator5/aot/Curator5ZookeeperReflectionTypeDescriberRegistrar.java new file mode 100644 index 00000000000..ce7fddb0afb --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-zookeeper-curator5/src/main/java/org/apache/dubbo/remoting/zookeeper/curator5/aot/Curator5ZookeeperReflectionTypeDescriberRegistrar.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.remoting.zookeeper.curator5.aot; + +import org.apache.dubbo.aot.api.MemberCategory; +import org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar; +import org.apache.dubbo.aot.api.TypeDescriber; +import org.apache.zookeeper.ClientCnxnSocketNIO; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + + +public class Curator5ZookeeperReflectionTypeDescriberRegistrar implements ReflectionTypeDescriberRegistrar { + + @Override + public List getTypeDescribers() { + List typeDescribers = new ArrayList<>(); + typeDescribers.add(buildTypeDescriberWithDeclaredConstructors(ClientCnxnSocketNIO.class)); + typeDescribers.add(buildTypeDescriberWithDeclared("org.apache.curator.x.discovery.ServiceInstance")); + typeDescribers.add(buildTypeDescriberWithDeclared("org.apache.curator.x.discovery.details.OldServiceInstance")); + return typeDescribers; + } + + private TypeDescriber buildTypeDescriberWithDeclared(String className){ + Set memberCategories = new HashSet<>(); + memberCategories.add(MemberCategory.INVOKE_DECLARED_METHODS); + memberCategories.add(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); + memberCategories.add(MemberCategory.DECLARED_FIELDS); + return new TypeDescriber(className, null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories); + } + + private TypeDescriber buildTypeDescriberWithDeclaredConstructors(Class c){ + Set memberCategories = new HashSet<>(); + memberCategories.add(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); + return new TypeDescriber(c.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories); + } +} diff --git a/dubbo-remoting/dubbo-remoting-zookeeper-curator5/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar b/dubbo-remoting/dubbo-remoting-zookeeper-curator5/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar new file mode 100644 index 00000000000..ed05e185646 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-zookeeper-curator5/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar @@ -0,0 +1 @@ +curator5Zookeeper=org.apache.dubbo.remoting.zookeeper.curator5.aot.Curator5ZookeeperReflectionTypeDescriberRegistrar diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/pom.xml b/dubbo-remoting/dubbo-remoting-zookeeper/pom.xml index 9e40b3dbc37..7442d5a4f95 100644 --- a/dubbo-remoting/dubbo-remoting-zookeeper/pom.xml +++ b/dubbo-remoting/dubbo-remoting-zookeeper/pom.xml @@ -57,6 +57,13 @@ curator-x-discovery ${curator_version} + + + org.apache.dubbo + dubbo-native + ${project.parent.version} + + org.apache.zookeeper zookeeper diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/aot/CuratorZookeeperReflectionTypeDescriberRegistrar.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/aot/CuratorZookeeperReflectionTypeDescriberRegistrar.java new file mode 100644 index 00000000000..cc6068a1de8 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/aot/CuratorZookeeperReflectionTypeDescriberRegistrar.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.remoting.zookeeper.curator.aot; + +import org.apache.dubbo.aot.api.MemberCategory; +import org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar; +import org.apache.dubbo.aot.api.TypeDescriber; +import org.apache.zookeeper.ClientCnxnSocketNIO; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + + +public class CuratorZookeeperReflectionTypeDescriberRegistrar implements ReflectionTypeDescriberRegistrar { + + @Override + public List getTypeDescribers() { + List typeDescribers = new ArrayList<>(); + typeDescribers.add(buildTypeDescriberWithDeclaredConstructors(ClientCnxnSocketNIO.class)); + return typeDescribers; + } + + private TypeDescriber buildTypeDescriberWithDeclaredMethods(Class c){ + Set memberCategories = new HashSet<>(); + memberCategories.add(MemberCategory.INVOKE_DECLARED_METHODS); + return new TypeDescriber(c.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories); + } + + private TypeDescriber buildTypeDescriberWithDeclaredConstructors(Class c){ + Set memberCategories = new HashSet<>(); + memberCategories.add(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); + return new TypeDescriber(c.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories); + } +} diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar new file mode 100644 index 00000000000..5312e63a093 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar @@ -0,0 +1 @@ +curatorZookeeper=org.apache.dubbo.remoting.zookeeper.curator.aot.CuratorZookeeperReflectionTypeDescriberRegistrar diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java index 05ed8ffdf63..030e81d3e76 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java @@ -22,6 +22,7 @@ import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig; +import org.apache.dubbo.config.spring.util.SpringCompatUtils; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -30,6 +31,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import java.lang.reflect.InvocationTargetException; +import java.util.Collection; import java.util.Set; import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME; @@ -63,8 +66,14 @@ public class DubboAutoConfiguration { @ConditionalOnBean(name = BASE_PACKAGES_BEAN_NAME) @Bean public ServiceAnnotationPostProcessor serviceAnnotationBeanProcessor(@Qualifier(BASE_PACKAGES_BEAN_NAME) - Set packagesToScan) { - return new ServiceAnnotationPostProcessor(packagesToScan); + Set packagesToScan) { + ServiceAnnotationPostProcessor serviceAnnotationPostProcessor; + try { + serviceAnnotationPostProcessor = (ServiceAnnotationPostProcessor) SpringCompatUtils.serviceAnnotationPostProcessor().getDeclaredConstructor(packagesToScan.getClass()).newInstance(packagesToScan); + } catch (Exception e) { + throw new RuntimeException(e); + } + return serviceAnnotationPostProcessor; } } diff --git a/pom.xml b/pom.xml index 9754a83ef77..5234a73364d 100644 --- a/pom.xml +++ b/pom.xml @@ -335,8 +335,8 @@ **/org/apache/dubbo/maven/plugin/aot/RunArguments.java, **/org/apache/dubbo/maven/plugin/aot/RunProcess.java, **/org/apache/dubbo/aot/generate/BasicJsonWriter.java, - **/org/apache/dubbo/aot/generate/ExecutableMode.java, - **/org/apache/dubbo/aot/generate/MemberCategory.java, + **/org/apache/dubbo/aot/api/ExecutableMode.java, + **/org/apache/dubbo/aot/api/MemberCategory.java, **/org/apache/dubbo/common/threadpool/serial/SerializingExecutor.java, **/org/apache/dubbo/common/threadlocal/InternalThreadLocal.java, **/org/apache/dubbo/common/threadlocal/InternalThreadLocalMap.java, From d0fd8b453328075b1faedd8dbc03c8ad4a70b61f Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Mon, 10 Apr 2023 13:05:27 +0800 Subject: [PATCH 02/17] fix checkstyle Signed-off-by: crazyhzm --- .../dubbo/config/AbstractInterfaceConfig.java | 1 - dubbo-config/dubbo-config-spring6/pom.xml | 24 +++++++++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java index 7a9e72fb8d9..0fce460a477 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java @@ -48,7 +48,6 @@ import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY; import static org.apache.dubbo.common.constants.CommonConstants.INVOKER_LISTENER_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.NATIVE; import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY; import static org.apache.dubbo.common.constants.CommonConstants.REFERENCE_FILTER_KEY; import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY; diff --git a/dubbo-config/dubbo-config-spring6/pom.xml b/dubbo-config/dubbo-config-spring6/pom.xml index b674b8116c9..f79701daeb6 100644 --- a/dubbo-config/dubbo-config-spring6/pom.xml +++ b/dubbo-config/dubbo-config-spring6/pom.xml @@ -1,7 +1,20 @@ - - + + 4.0.0 org.apache.dubbo @@ -76,9 +89,6 @@ - - - From 0f92d0aab604c1a178a7b8dbce12bcfa590ac132 Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Mon, 10 Apr 2023 13:12:08 +0800 Subject: [PATCH 03/17] remove useless imports Signed-off-by: crazyhzm --- .../zookeeper/aot/ZookeeperReflectionTypeDescriberRegistrar.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/aot/ZookeeperReflectionTypeDescriberRegistrar.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/aot/ZookeeperReflectionTypeDescriberRegistrar.java index e3baf50334d..2e0b5520cae 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/aot/ZookeeperReflectionTypeDescriberRegistrar.java +++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/aot/ZookeeperReflectionTypeDescriberRegistrar.java @@ -20,7 +20,6 @@ import org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar; import org.apache.dubbo.aot.api.TypeDescriber; import org.apache.dubbo.registry.zookeeper.ZookeeperInstance; -import org.apache.zookeeper.ClientCnxnSocketNIO; import java.util.ArrayList; import java.util.HashSet; From aceafa26d8a35846fa13c9fd94a1078ab42c3a83 Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Mon, 10 Apr 2023 13:48:37 +0800 Subject: [PATCH 04/17] remove useless imports Signed-off-by: crazyhzm --- .../DubboInfraBeanRegisterPostProcessor.java | 9 - ...ServiceAnnotationWithAotPostProcessor.java | 4 - .../aot/ReferencedFieldValueResolver.java | 298 +++++++++--------- .../ReferencedMethodArgumentsResolver.java | 1 - .../autoconfigure/DubboAutoConfiguration.java | 3 - 5 files changed, 152 insertions(+), 163 deletions(-) diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java index 68e76ba0b0a..731d273b630 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java @@ -16,23 +16,14 @@ */ package org.apache.dubbo.config.spring.context; -import org.apache.dubbo.config.context.ConfigManager; import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; -import org.apache.dubbo.config.spring.extension.SpringExtensionInjector; import org.apache.dubbo.config.spring.util.DubboBeanUtils; -import org.apache.dubbo.config.spring.util.EnvironmentUtils; -import org.apache.dubbo.rpc.model.ApplicationModel; -import org.apache.dubbo.rpc.model.ModuleModel; - import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; -import org.springframework.core.env.ConfigurableEnvironment; - -import java.util.SortedMap; /** diff --git a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java index 6254c702ae0..384754803ad 100644 --- a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java +++ b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java @@ -35,10 +35,6 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser; import java.util.Collection; -import java.util.Set; -import java.util.stream.Collectors; - -import static java.util.Arrays.asList; /** * A {@link BeanFactoryPostProcessor} used for processing of {@link Service @Service} annotated classes and annotated bean in java config classes. diff --git a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedFieldValueResolver.java b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedFieldValueResolver.java index d89e7ddbabe..fd8bcfa5188 100644 --- a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedFieldValueResolver.java +++ b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedFieldValueResolver.java @@ -47,164 +47,170 @@ * invocation} hints are only required if the * {@link #resolveAndSet(RegisteredBean, Object)} method of this class is being * used (typically to support private fields). - * */ public final class ReferencedFieldValueResolver extends AutowiredElementResolver { - private final String fieldName; + private final String fieldName; - private final boolean required; + private final boolean required; - @Nullable - private final String shortcut; + @Nullable + private final String shortcut; - private ReferencedFieldValueResolver(String fieldName, boolean required, + private ReferencedFieldValueResolver(String fieldName, boolean required, @Nullable String shortcut) { - Assert.hasText(fieldName, "'fieldName' must not be empty"); - this.fieldName = fieldName; - this.required = required; - this.shortcut = shortcut; - } - - - /** - * Create a new {@link ReferencedFieldValueResolver} for the specified field - * where injection is optional. - * @param fieldName the field name - * @return a new {@link ReferencedFieldValueResolver} instance - */ - public static ReferencedFieldValueResolver forField(String fieldName) { - return new ReferencedFieldValueResolver(fieldName, false, null); - } - - /** - * Create a new {@link ReferencedFieldValueResolver} for the specified field - * where injection is required. - * @param fieldName the field name - * @return a new {@link ReferencedFieldValueResolver} instance - */ - public static ReferencedFieldValueResolver forRequiredField(String fieldName) { - return new ReferencedFieldValueResolver(fieldName, true, null); - } - - - /** - * Return a new {@link ReferencedFieldValueResolver} instance that uses a - * direct bean name injection shortcut. - * @param beanName the bean name to use as a shortcut - * @return a new {@link ReferencedFieldValueResolver} instance that uses the - * shortcuts - */ - public ReferencedFieldValueResolver withShortcut(String beanName) { - return new ReferencedFieldValueResolver(this.fieldName, this.required, beanName); - } - - /** - * Resolve the field for the specified registered bean and provide it to the - * given action. - * @param registeredBean the registered bean - * @param action the action to execute with the resolved field value - */ - public void resolve(RegisteredBean registeredBean, ThrowingConsumer action) { - Assert.notNull(registeredBean, "'registeredBean' must not be null"); - Assert.notNull(action, "'action' must not be null"); - T resolved = resolve(registeredBean); - if (resolved != null) { - action.accept(resolved); - } - } - - /** - * Resolve the field value for the specified registered bean. - * @param registeredBean the registered bean - * @param requiredType the required type - * @return the resolved field value - */ - @Nullable - @SuppressWarnings("unchecked") - public T resolve(RegisteredBean registeredBean, Class requiredType) { - Object value = resolveObject(registeredBean); - Assert.isInstanceOf(requiredType, value); - return (T) value; - } - - /** - * Resolve the field value for the specified registered bean. - * @param registeredBean the registered bean - * @return the resolved field value - */ - @Nullable - @SuppressWarnings("unchecked") - public T resolve(RegisteredBean registeredBean) { - return (T) resolveObject(registeredBean); - } - - /** - * Resolve the field value for the specified registered bean. - * @param registeredBean the registered bean - * @return the resolved field value - */ - @Nullable - public Object resolveObject(RegisteredBean registeredBean) { - Assert.notNull(registeredBean, "'registeredBean' must not be null"); - return resolveValue(registeredBean, getField(registeredBean)); - } - - /** - * Resolve the field value for the specified registered bean and set it - * using reflection. - * @param registeredBean the registered bean - * @param instance the bean instance - */ - public void resolveAndSet(RegisteredBean registeredBean, Object instance) { - Assert.notNull(registeredBean, "'registeredBean' must not be null"); - Assert.notNull(instance, "'instance' must not be null"); - Field field = getField(registeredBean); - Object resolved = resolveValue(registeredBean, field); - if (resolved != null) { - ReflectionUtils.makeAccessible(field); - ReflectionUtils.setField(field, instance, resolved); - } - } - - @Nullable - private Object resolveValue(RegisteredBean registeredBean, Field field) { - String beanName = registeredBean.getBeanName(); - Class beanClass = registeredBean.getBeanClass(); - ConfigurableBeanFactory beanFactory = registeredBean.getBeanFactory(); - DependencyDescriptor descriptor = new DependencyDescriptor(field, this.required); - descriptor.setContainingClass(beanClass); - if (this.shortcut != null) { - descriptor = new ShortcutDependencyDescriptor(descriptor, this.shortcut, - field.getType()); - } - Set autowiredBeanNames = new LinkedHashSet<>(1); - TypeConverter typeConverter = beanFactory.getTypeConverter(); - try { - Assert.isInstanceOf(AutowireCapableBeanFactory.class, beanFactory); + Assert.hasText(fieldName, "'fieldName' must not be empty"); + this.fieldName = fieldName; + this.required = required; + this.shortcut = shortcut; + } + + + /** + * Create a new {@link ReferencedFieldValueResolver} for the specified field + * where injection is optional. + * + * @param fieldName the field name + * @return a new {@link ReferencedFieldValueResolver} instance + */ + public static ReferencedFieldValueResolver forField(String fieldName) { + return new ReferencedFieldValueResolver(fieldName, false, null); + } + + /** + * Create a new {@link ReferencedFieldValueResolver} for the specified field + * where injection is required. + * + * @param fieldName the field name + * @return a new {@link ReferencedFieldValueResolver} instance + */ + public static ReferencedFieldValueResolver forRequiredField(String fieldName) { + return new ReferencedFieldValueResolver(fieldName, true, null); + } + + + /** + * Return a new {@link ReferencedFieldValueResolver} instance that uses a + * direct bean name injection shortcut. + * + * @param beanName the bean name to use as a shortcut + * @return a new {@link ReferencedFieldValueResolver} instance that uses the + * shortcuts + */ + public ReferencedFieldValueResolver withShortcut(String beanName) { + return new ReferencedFieldValueResolver(this.fieldName, this.required, beanName); + } + + /** + * Resolve the field for the specified registered bean and provide it to the + * given action. + * + * @param registeredBean the registered bean + * @param action the action to execute with the resolved field value + */ + public void resolve(RegisteredBean registeredBean, ThrowingConsumer action) { + Assert.notNull(registeredBean, "'registeredBean' must not be null"); + Assert.notNull(action, "'action' must not be null"); + T resolved = resolve(registeredBean); + if (resolved != null) { + action.accept(resolved); + } + } + + /** + * Resolve the field value for the specified registered bean. + * + * @param registeredBean the registered bean + * @param requiredType the required type + * @return the resolved field value + */ + @Nullable + @SuppressWarnings("unchecked") + public T resolve(RegisteredBean registeredBean, Class requiredType) { + Object value = resolveObject(registeredBean); + Assert.isInstanceOf(requiredType, value); + return (T) value; + } + + /** + * Resolve the field value for the specified registered bean. + * + * @param registeredBean the registered bean + * @return the resolved field value + */ + @Nullable + @SuppressWarnings("unchecked") + public T resolve(RegisteredBean registeredBean) { + return (T) resolveObject(registeredBean); + } + + /** + * Resolve the field value for the specified registered bean. + * + * @param registeredBean the registered bean + * @return the resolved field value + */ + @Nullable + public Object resolveObject(RegisteredBean registeredBean) { + Assert.notNull(registeredBean, "'registeredBean' must not be null"); + return resolveValue(registeredBean, getField(registeredBean)); + } + + /** + * Resolve the field value for the specified registered bean and set it + * using reflection. + * + * @param registeredBean the registered bean + * @param instance the bean instance + */ + public void resolveAndSet(RegisteredBean registeredBean, Object instance) { + Assert.notNull(registeredBean, "'registeredBean' must not be null"); + Assert.notNull(instance, "'instance' must not be null"); + Field field = getField(registeredBean); + Object resolved = resolveValue(registeredBean, field); + if (resolved != null) { + ReflectionUtils.makeAccessible(field); + ReflectionUtils.setField(field, instance, resolved); + } + } + + @Nullable + private Object resolveValue(RegisteredBean registeredBean, Field field) { + String beanName = registeredBean.getBeanName(); + Class beanClass = registeredBean.getBeanClass(); + ConfigurableBeanFactory beanFactory = registeredBean.getBeanFactory(); + DependencyDescriptor descriptor = new DependencyDescriptor(field, this.required); + descriptor.setContainingClass(beanClass); + if (this.shortcut != null) { + descriptor = new ShortcutDependencyDescriptor(descriptor, this.shortcut, + field.getType()); + } + Set autowiredBeanNames = new LinkedHashSet<>(1); + TypeConverter typeConverter = beanFactory.getTypeConverter(); + try { + Assert.isInstanceOf(AutowireCapableBeanFactory.class, beanFactory); Object injectedObject = beanFactory.getBean(shortcut); - Object value = ((AutowireCapableBeanFactory) beanFactory).resolveDependency( - descriptor, beanName, autowiredBeanNames, typeConverter); - registerDependentBeans(beanFactory, beanName, autowiredBeanNames); - return injectedObject; - } - catch (BeansException ex) { - throw new UnsatisfiedDependencyException(null, beanName, - new InjectionPoint(field), ex); - } - } - - private Field getField(RegisteredBean registeredBean) { - Field field = ReflectionUtils.findField(registeredBean.getBeanClass(), - this.fieldName); - Assert.notNull(field, () -> "No field '" + this.fieldName + "' found on " - + registeredBean.getBeanClass().getName()); - return field; - } + Object value = ((AutowireCapableBeanFactory) beanFactory).resolveDependency( + descriptor, beanName, autowiredBeanNames, typeConverter); + registerDependentBeans(beanFactory, beanName, autowiredBeanNames); + return injectedObject; + } catch (BeansException ex) { + throw new UnsatisfiedDependencyException(null, beanName, + new InjectionPoint(field), ex); + } + } + + private Field getField(RegisteredBean registeredBean) { + Field field = ReflectionUtils.findField(registeredBean.getBeanClass(), + this.fieldName); + Assert.notNull(field, () -> "No field '" + this.fieldName + "' found on " + + registeredBean.getBeanClass().getName()); + return field; + } } diff --git a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedMethodArgumentsResolver.java b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedMethodArgumentsResolver.java index 32fdd9e1a9c..a051dedba1b 100644 --- a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedMethodArgumentsResolver.java +++ b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/aot/ReferencedMethodArgumentsResolver.java @@ -53,7 +53,6 @@ * invocation} hints are only required if the * {@link #resolveAndInvoke(RegisteredBean, Object)} method of this class is * being used (typically to support private methods). - * */ public final class ReferencedMethodArgumentsResolver extends AutowiredElementResolver { diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java index 030e81d3e76..c0dc0509be2 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java @@ -21,7 +21,6 @@ import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig; - import org.apache.dubbo.config.spring.util.SpringCompatUtils; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -31,8 +30,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.lang.reflect.InvocationTargetException; -import java.util.Collection; import java.util.Set; import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME; From 83421d70d0fc182d47374dbede83301ed935ebb5 Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Mon, 10 Apr 2023 14:23:59 +0800 Subject: [PATCH 05/17] change java version of build-source actions to jdk17 Signed-off-by: crazyhzm --- .github/workflows/build-and-test-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-and-test-pr.yml b/.github/workflows/build-and-test-pr.yml index 72c5fef4cae..6681440ded4 100644 --- a/.github/workflows/build-and-test-pr.yml +++ b/.github/workflows/build-and-test-pr.yml @@ -54,7 +54,7 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'zulu' - java-version: 8 + java-version: 17 - uses: actions/cache@v3 name: "Cache local Maven repository" with: From d392c87531f9b322a89a4127c36b6afeb83f89bb Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Mon, 10 Apr 2023 15:19:58 +0800 Subject: [PATCH 06/17] dubbo-serialization-fastjson2 support native Signed-off-by: crazyhzm --- .../fastjson2/Fastjson2CreatorManager.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/Fastjson2CreatorManager.java b/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/Fastjson2CreatorManager.java index 8168aee13fa..e112f892260 100644 --- a/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/Fastjson2CreatorManager.java +++ b/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/Fastjson2CreatorManager.java @@ -16,6 +16,9 @@ */ package org.apache.dubbo.common.serialize.fastjson2; +import com.alibaba.fastjson2.reader.ObjectReaderCreator; +import com.alibaba.fastjson2.writer.ObjectWriterCreator; +import org.apache.dubbo.common.aot.NativeDetector; import org.apache.dubbo.rpc.model.FrameworkModel; import org.apache.dubbo.rpc.model.ScopeClassLoaderListener; @@ -31,10 +34,11 @@ public class Fastjson2CreatorManager implements ScopeClassLoaderListener readerMap = new ConcurrentHashMap<>(); - private final Map writerMap = new ConcurrentHashMap<>(); + private final Map readerMap = new ConcurrentHashMap<>(); + private final Map writerMap = new ConcurrentHashMap<>(); public Fastjson2CreatorManager(FrameworkModel frameworkModel) { frameworkModel.addClassLoaderListener(this); @@ -44,8 +48,13 @@ public void setCreator(ClassLoader classLoader) { if (classLoader == null) { classLoader = SYSTEM_CLASSLOADER_KEY; } - JSONFactory.setContextReaderCreator(readerMap.computeIfAbsent(classLoader, ObjectReaderCreatorASM::new)); - JSONFactory.setContextWriterCreator(writerMap.computeIfAbsent(classLoader, ObjectWriterCreatorASM::new)); + if (NativeDetector.inNativeImage()) { + JSONFactory.setContextReaderCreator(readerMap.putIfAbsent(classLoader, ObjectReaderCreator.INSTANCE)); + JSONFactory.setContextWriterCreator(writerMap.putIfAbsent(classLoader, ObjectWriterCreator.INSTANCE)); + } else { + JSONFactory.setContextReaderCreator(readerMap.computeIfAbsent(classLoader, ObjectReaderCreatorASM::new)); + JSONFactory.setContextWriterCreator(writerMap.computeIfAbsent(classLoader, ObjectWriterCreatorASM::new)); + } } @Override From 7f4e29aed31e9bb1861f731bd27ab40a9f2724d0 Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Mon, 10 Apr 2023 19:28:04 +0800 Subject: [PATCH 07/17] fix xml config Signed-off-by: crazyhzm --- .../annotation/ReferenceAnnotationBeanPostProcessor.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java index bc6ddabfbbe..b5dde4b9151 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java @@ -94,7 +94,7 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean /** * The bean name of {@link ReferenceAnnotationBeanPostProcessor} */ - public static final String BEAN_NAME = "referenceAnnotationBeanPostProcessor"; + public static final String BEAN_NAME = ReferenceAnnotationBeanPostProcessor.class.getName(); /** * Cache size @@ -314,6 +314,7 @@ public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, C * Alternatives to the {@link #postProcessProperties(PropertyValues, Object, String)}, that removed as of Spring * Framework 6.0.0, and in favor of {@link #postProcessProperties(PropertyValues, Object, String)}. *

In order to be compatible with the lower version of Spring, it is still retained. + * * @see #postProcessProperties */ public PropertyValues postProcessPropertyValues( @@ -323,6 +324,7 @@ public PropertyValues postProcessPropertyValues( /** * Alternatives to the {@link #postProcessPropertyValues(PropertyValues, PropertyDescriptor[], Object, String)}. + * * @see #postProcessPropertyValues */ @Override @@ -417,7 +419,7 @@ public String registerReferenceBean(String propertyName, Class injectedType, boolean isContains; if ((isContains = beanDefinitionRegistry.containsBeanDefinition(referenceBeanName)) || beanDefinitionRegistry.isAlias(referenceBeanName)) { String preReferenceBeanName = referenceBeanName; - if (!isContains){ + if (!isContains) { // Look in the alias for the origin bean name String[] aliases = beanDefinitionRegistry.getAliases(referenceBeanName); if (ArrayUtils.isNotEmpty(aliases)) { From ea28e7ab26269cc0ce54021a548ed9e6915a0230 Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Tue, 11 Apr 2023 10:01:51 +0800 Subject: [PATCH 08/17] fix singleton bean Signed-off-by: crazyhzm --- .../spring/context/DubboSpringInitializer.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java index 6f4f2fc63a7..104ea4571d5 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java @@ -166,9 +166,15 @@ private static ConfigurableListableBeanFactory findBeanFactory(BeanDefinitionReg private static void registerContextBeans(ConfigurableListableBeanFactory beanFactory, DubboSpringInitContext context) { // register singleton - registerSingleton(beanFactory, context); - registerSingleton(beanFactory, context.getApplicationModel()); - registerSingleton(beanFactory, context.getModuleModel()); + if (!beanFactory.containsSingleton(DubboSpringInitContext.class.getName())){ + registerSingleton(beanFactory, context); + } + if (!beanFactory.containsSingleton(context.getApplicationModel().getClass().getName())){ + registerSingleton(beanFactory, context.getApplicationModel()); + } + if (!beanFactory.containsSingleton(context.getModuleModel().getClass().getName())){ + registerSingleton(beanFactory, context.getModuleModel()); + } } private static void registerSingleton(ConfigurableListableBeanFactory beanFactory, Object bean) { From 18ef0e70cd5ce12c1ebc5ba5c25fb54c9624539f Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Tue, 11 Apr 2023 20:14:04 +0800 Subject: [PATCH 09/17] ignore test Signed-off-by: crazyhzm --- .../spring/boot/autoconfigure/DubboAutoConfiguration.java | 3 ++- .../autoconfigure/CompatibleDubboAutoConfigurationTest.java | 2 ++ .../CompatibleDubboAutoConfigurationTestWithoutProperties.java | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java index c0dc0509be2..b4628c2a26c 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java @@ -30,6 +30,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import java.util.Collection; import java.util.Set; import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME; @@ -66,7 +67,7 @@ public ServiceAnnotationPostProcessor serviceAnnotationBeanProcessor(@Qualifier( Set packagesToScan) { ServiceAnnotationPostProcessor serviceAnnotationPostProcessor; try { - serviceAnnotationPostProcessor = (ServiceAnnotationPostProcessor) SpringCompatUtils.serviceAnnotationPostProcessor().getDeclaredConstructor(packagesToScan.getClass()).newInstance(packagesToScan); + serviceAnnotationPostProcessor = (ServiceAnnotationPostProcessor) SpringCompatUtils.serviceAnnotationPostProcessor().getDeclaredConstructor(Collection.class).newInstance(packagesToScan); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java index ac7ab815824..f50d1350f35 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java @@ -21,6 +21,7 @@ import org.apache.dubbo.config.spring.util.DubboBeanUtils; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.ObjectProvider; @@ -35,6 +36,7 @@ * {@link DubboAutoConfiguration} Test * @see DubboAutoConfiguration */ +@Ignore @RunWith(SpringRunner.class) @SpringBootTest(classes = { CompatibleDubboAutoConfigurationTest.class diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java index c0d3e6282f4..ef2941fcae4 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java @@ -24,6 +24,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -37,6 +38,7 @@ * * @see DubboAutoConfiguration */ +@Ignore @RunWith(SpringRunner.class) @SpringBootTest(classes = CompatibleDubboAutoConfigurationTestWithoutProperties.class, properties = { "dubbo.application.name=demo" From c1c3bd2167f8ce659fa287ede0470bc60a22bf67 Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Tue, 11 Apr 2023 22:44:34 +0800 Subject: [PATCH 10/17] ignore dubbo-config-spring6 module in dubbo all Signed-off-by: crazyhzm --- .../src/test/java/org/apache/dubbo/dependency/FileTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java b/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java index c8038141a93..276d2dbcd45 100644 --- a/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java +++ b/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java @@ -61,6 +61,7 @@ class FileTest { ignoredModulesInDubboAll.add(Pattern.compile("dubbo-distribution")); ignoredModulesInDubboAll.add(Pattern.compile("dubbo-metadata-processor")); ignoredModulesInDubboAll.add(Pattern.compile("dubbo-native.*")); + ignoredModulesInDubboAll.add(Pattern.compile("dubbo-config-spring6.*")); ignoredModulesInDubboAll.add(Pattern.compile("dubbo-spring-boot.*")); ignoredModulesInDubboAll.add(Pattern.compile("dubbo-maven-plugin")); } From 654d462e15513eb7bdf0d9c8051303bbc211c82b Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Tue, 11 Apr 2023 22:52:25 +0800 Subject: [PATCH 11/17] remove @ignore Signed-off-by: crazyhzm --- .../autoconfigure/CompatibleDubboAutoConfigurationTest.java | 3 --- .../CompatibleDubboAutoConfigurationTestWithoutProperties.java | 3 --- 2 files changed, 6 deletions(-) diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java index f50d1350f35..6d1330c7b5d 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java @@ -19,9 +19,7 @@ import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; import org.apache.dubbo.config.spring.util.DubboBeanUtils; - import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.ObjectProvider; @@ -36,7 +34,6 @@ * {@link DubboAutoConfiguration} Test * @see DubboAutoConfiguration */ -@Ignore @RunWith(SpringRunner.class) @SpringBootTest(classes = { CompatibleDubboAutoConfigurationTest.class diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java index ef2941fcae4..15ead545ec2 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java @@ -20,11 +20,9 @@ import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; import org.apache.dubbo.config.spring.util.DubboBeanUtils; - import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -38,7 +36,6 @@ * * @see DubboAutoConfiguration */ -@Ignore @RunWith(SpringRunner.class) @SpringBootTest(classes = CompatibleDubboAutoConfigurationTestWithoutProperties.class, properties = { "dubbo.application.name=demo" From defc8b42994f8f7a486a6eeccf82c1a4da91cfbf Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Wed, 12 Apr 2023 10:45:44 +0800 Subject: [PATCH 12/17] add dubbo-config-spring6 to dubbo-bom Signed-off-by: crazyhzm --- dubbo-distribution/dubbo-bom/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dubbo-distribution/dubbo-bom/pom.xml b/dubbo-distribution/dubbo-bom/pom.xml index ccf5cc07b05..73fc53cbe2e 100644 --- a/dubbo-distribution/dubbo-bom/pom.xml +++ b/dubbo-distribution/dubbo-bom/pom.xml @@ -78,6 +78,12 @@ ${project.version} + + org.apache.dubbo + dubbo-config-spring6 + ${project.version} + + org.apache.dubbo From 48cc37501a87ce1cdb801566f557a277b727b00b Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Wed, 12 Apr 2023 13:06:23 +0800 Subject: [PATCH 13/17] add dubbo-config-spring6 to dubbo-test Signed-off-by: crazyhzm --- dubbo-test/dubbo-dependencies-all/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dubbo-test/dubbo-dependencies-all/pom.xml b/dubbo-test/dubbo-dependencies-all/pom.xml index e085b0bd8c3..2e0ec4eaad9 100644 --- a/dubbo-test/dubbo-dependencies-all/pom.xml +++ b/dubbo-test/dubbo-dependencies-all/pom.xml @@ -66,6 +66,10 @@ org.apache.dubbo dubbo-config-spring + + org.apache.dubbo + dubbo-config-spring6 + From 85027a2283c837c22423d64a7b8a701f0a6ae646 Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Wed, 12 Apr 2023 18:38:08 +0800 Subject: [PATCH 14/17] add transformer Signed-off-by: crazyhzm --- dubbo-distribution/dubbo-all/pom.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml index 8c86ea543b4..f5464ae99c1 100644 --- a/dubbo-distribution/dubbo-all/pom.xml +++ b/dubbo-distribution/dubbo-all/pom.xml @@ -1329,6 +1329,20 @@ + + + META-INF/dubbo/internal/org.apache.dubbo.aot.api.ResourceDescriberRegistrar + + + + + + META-INF/dubbo/internal/org.apache.dubbo.common.json.JsonUtil + + + From 3963487c49921c2ad7a3e7d901acdcfd90b50b2b Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Wed, 12 Apr 2023 20:47:51 +0800 Subject: [PATCH 15/17] ignore dubbo-config-spring6 Signed-off-by: crazyhzm --- .../src/test/java/org/apache/dubbo/dependency/FileTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java b/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java index 276d2dbcd45..164ce60f9c1 100644 --- a/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java +++ b/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java @@ -53,6 +53,7 @@ class FileTest { ignoredArtifacts.add(Pattern.compile("dubbo-demo.*")); ignoredArtifacts.add(Pattern.compile("dubbo-test.*")); + ignoredArtifacts.add(Pattern.compile("dubbo-config-spring6.*")); ignoredModulesInDubboAll.add(Pattern.compile("dubbo")); ignoredModulesInDubboAll.add(Pattern.compile("dubbo-bom")); From 3ed9ab086b9b91f2029c916cf3e68e508cf70d54 Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Fri, 14 Apr 2023 14:52:55 +0800 Subject: [PATCH 16/17] fix JsonUtilsTest Signed-off-by: crazyhzm --- .../java/org/apache/dubbo/common/utils/JsonUtilsTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java index 528ff023065..4eecfdae95c 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java @@ -16,7 +16,7 @@ */ package org.apache.dubbo.common.utils; -import org.apache.dubbo.common.json.JSON; +import org.apache.dubbo.common.json.JsonUtil; import org.apache.dubbo.common.json.impl.FastJson2Impl; import org.apache.dubbo.common.json.impl.FastJsonImpl; import org.apache.dubbo.common.json.impl.GsonImpl; @@ -319,7 +319,7 @@ void testGetJson2() { private static Field jsonFieldCache; - private static void setJson(JSON json) { + private static void setJson(JsonUtil json) { try { if (jsonFieldCache == null) { jsonFieldCache = JsonUtils.class.getDeclaredField("json"); From e4a6f75e57e997bcfbf8b6b351552aeb99ddc71b Mon Sep 17 00:00:00 2001 From: crazyhzm Date: Fri, 14 Apr 2023 15:27:53 +0800 Subject: [PATCH 17/17] fix JsonUtilsTest Signed-off-by: crazyhzm --- .../test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java index 4eecfdae95c..4cdfa212d9c 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java @@ -322,7 +322,7 @@ void testGetJson2() { private static void setJson(JsonUtil json) { try { if (jsonFieldCache == null) { - jsonFieldCache = JsonUtils.class.getDeclaredField("json"); + jsonFieldCache = JsonUtils.class.getDeclaredField("jsonUtil"); jsonFieldCache.setAccessible(true); }