Native Support Springboot3 (#12072)
* Support native with springboot3 Signed-off-by: crazyhzm <crazyhzm@gmail.com> * fix checkstyle Signed-off-by: crazyhzm <crazyhzm@gmail.com> * remove useless imports Signed-off-by: crazyhzm <crazyhzm@gmail.com> * remove useless imports Signed-off-by: crazyhzm <crazyhzm@gmail.com> * change java version of build-source actions to jdk17 Signed-off-by: crazyhzm <crazyhzm@gmail.com> * dubbo-serialization-fastjson2 support native Signed-off-by: crazyhzm <crazyhzm@gmail.com> * fix xml config Signed-off-by: crazyhzm <crazyhzm@gmail.com> * fix singleton bean Signed-off-by: crazyhzm <crazyhzm@gmail.com> * ignore test Signed-off-by: crazyhzm <crazyhzm@gmail.com> * ignore dubbo-config-spring6 module in dubbo all Signed-off-by: crazyhzm <crazyhzm@gmail.com> * remove @ignore Signed-off-by: crazyhzm <crazyhzm@gmail.com> * add dubbo-config-spring6 to dubbo-bom Signed-off-by: crazyhzm <crazyhzm@gmail.com> * add dubbo-config-spring6 to dubbo-test Signed-off-by: crazyhzm <crazyhzm@gmail.com> * add transformer Signed-off-by: crazyhzm <crazyhzm@gmail.com> * ignore dubbo-config-spring6 Signed-off-by: crazyhzm <crazyhzm@gmail.com> * fix JsonUtilsTest Signed-off-by: crazyhzm <crazyhzm@gmail.com> * fix JsonUtilsTest Signed-off-by: crazyhzm <crazyhzm@gmail.com> --------- Signed-off-by: crazyhzm <crazyhzm@gmail.com>
This commit is contained in:
parent
2997fa6a2e
commit
6c8f79c889
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
- 'dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/**'
|
||||
|
||||
comment: on-failure
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ package org.apache.dubbo.common.extension;
|
|||
|
||||
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.CollectionUtils;
|
|||
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<T> {
|
|||
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<Class<?>, Object> extensionInstances = new ConcurrentHashMap<>(64);
|
||||
|
||||
|
|
@ -120,17 +120,17 @@ public class ExtensionLoader<T> {
|
|||
|
||||
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();
|
||||
|
||||
private final Map<String, Object> cachedActivates = Collections.synchronizedMap(
|
||||
private final Map<String, Object> cachedActivates = Collections.synchronizedMap(
|
||||
new LinkedHashMap<>());
|
||||
private final Map<String, Set<String>> cachedActivateGroups = Collections.synchronizedMap(
|
||||
private final Map<String, Set<String>> cachedActivateGroups = Collections.synchronizedMap(
|
||||
new LinkedHashMap<>());
|
||||
private final Map<String, String[][]> cachedActivateValues = Collections.synchronizedMap(
|
||||
private final Map<String, String[][]> cachedActivateValues = Collections.synchronizedMap(
|
||||
new LinkedHashMap<>());
|
||||
private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();
|
||||
private final Holder<Object> cachedAdaptiveInstance = new Holder<>();
|
||||
private volatile Class<?> cachedAdaptiveClass = null;
|
||||
private String cachedDefaultName;
|
||||
private volatile Throwable createAdaptiveInstanceError;
|
||||
private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();
|
||||
private final Holder<Object> cachedAdaptiveInstance = new Holder<>();
|
||||
private volatile Class<?> cachedAdaptiveClass = null;
|
||||
private String cachedDefaultName;
|
||||
private volatile Throwable createAdaptiveInstanceError;
|
||||
|
||||
private Set<Class<?>> cachedWrapperClasses;
|
||||
|
||||
|
|
@ -148,13 +148,13 @@ public class ExtensionLoader<T> {
|
|||
/**
|
||||
* Record all unacceptable exceptions when using SPI
|
||||
*/
|
||||
private final Set<String> unacceptableExceptions = new ConcurrentHashSet<>();
|
||||
private final ExtensionDirector extensionDirector;
|
||||
private final Set<String> unacceptableExceptions = new ConcurrentHashSet<>();
|
||||
private final ExtensionDirector extensionDirector;
|
||||
private final List<ExtensionPostProcessor> 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 @@ public class ExtensionLoader<T> {
|
|||
// 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) {
|
||||
|
|
|
|||
|
|
@ -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> T toJavaObject(String json, Type type);
|
||||
|
|
@ -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.LinkedList;
|
|||
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 {
|
||||
|
|
@ -21,7 +21,7 @@ import com.alibaba.fastjson2.JSONWriter;
|
|||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
|
||||
public class FastJson2Impl extends AbstractJSONImpl {
|
||||
public class FastJson2Impl extends AbstractJsonUtilImpl {
|
||||
@Override
|
||||
public <T> T toJavaObject(String json, Type type) {
|
||||
return com.alibaba.fastjson2.JSON.parseObject(json, type);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import com.alibaba.fastjson.serializer.SerializerFeature;
|
|||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
|
||||
public class FastJsonImpl extends AbstractJSONImpl {
|
||||
public class FastJsonImpl extends AbstractJsonUtilImpl {
|
||||
|
||||
@Override
|
||||
public <T> T toJavaObject(String json, Type type) {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import com.google.gson.reflect.TypeToken;
|
|||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
|||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
|
||||
public class JacksonImpl extends AbstractJSONImpl {
|
||||
public class JacksonImpl extends AbstractJsonUtilImpl {
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private volatile Object jacksonCache = null;
|
||||
|
|
|
|||
|
|
@ -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 class ClassLoaderResourceLoader {
|
|||
Enumeration<URL> urls;
|
||||
try {
|
||||
urls = currentClassLoader.getResources(fileName);
|
||||
boolean isNative = NativeUtils.isNative();
|
||||
boolean isNative = NativeDetector.inNativeImage();
|
||||
if (urls != null) {
|
||||
while (urls.hasMoreElements()) {
|
||||
URL url = urls.nextElement();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -29,17 +29,16 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
public class JsonUtils {
|
||||
private static volatile JsonUtil jsonUtil;
|
||||
|
||||
private static volatile JSON json;
|
||||
|
||||
protected static JSON getJson() {
|
||||
if (json == null) {
|
||||
protected 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();
|
||||
|
|
@ -55,23 +54,23 @@ public class JsonUtils {
|
|||
break;
|
||||
}
|
||||
if (instance != null && instance.isSupport()) {
|
||||
json = instance;
|
||||
jsonUtil = instance;
|
||||
}
|
||||
} catch (Throwable ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
if (json == null) {
|
||||
List<Class<? extends JSON>> jsonClasses = Arrays.asList(
|
||||
if (jsonUtil == null) {
|
||||
List<Class<? extends JsonUtil>> jsonClasses = Arrays.asList(
|
||||
FastJson2Impl.class,
|
||||
FastJsonImpl.class,
|
||||
GsonImpl.class,
|
||||
JacksonImpl.class);
|
||||
for (Class<? extends JSON> jsonClass : jsonClasses) {
|
||||
for (Class<? extends JsonUtil> jsonClass : jsonClasses) {
|
||||
try {
|
||||
JSON instance = jsonClass.getConstructor().newInstance();
|
||||
JsonUtil instance = jsonClass.getConstructor().newInstance();
|
||||
if (instance.isSupport()) {
|
||||
json = instance;
|
||||
jsonUtil = instance;
|
||||
break;
|
||||
}
|
||||
} catch (Throwable ignore) {
|
||||
|
|
@ -79,22 +78,22 @@ public class JsonUtils {
|
|||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
public static <T> T toJavaObject(String json, Type type) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.apache.dubbo.config;
|
|||
|
||||
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;
|
||||
|
|
@ -47,7 +48,6 @@ import java.util.stream.Collectors;
|
|||
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;
|
||||
|
|
@ -292,8 +292,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
|
|||
* @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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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,10 +319,10 @@ class JsonUtilsTest {
|
|||
|
||||
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");
|
||||
jsonFieldCache = JsonUtils.class.getDeclaredField("jsonUtil");
|
||||
jsonFieldCache.setAccessible(true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ 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.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 @@ import java.util.Map;
|
|||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* Or register ReferenceBean in xml:
|
||||
* <pre class="code">
|
||||
* <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"/>
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* Step 2: Inject ReferenceBean by @Autowired
|
||||
* <pre class="code">
|
||||
* public class FooController {
|
||||
|
|
@ -93,12 +94,11 @@ import java.util.Map;
|
|||
* }
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @see org.apache.dubbo.config.annotation.DubboReference
|
||||
* @see org.apache.dubbo.config.spring.reference.ReferenceBeanBuilder
|
||||
*/
|
||||
public class ReferenceBean<T> implements FactoryBean<T>,
|
||||
ApplicationContextAware, BeanClassLoaderAware, BeanNameAware, InitializingBean, DisposableBean {
|
||||
ApplicationContextAware, BeanClassLoaderAware, BeanNameAware, InitializingBean, DisposableBean {
|
||||
|
||||
private transient ApplicationContext applicationContext;
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ public class ReferenceBean<T> implements FactoryBean<T>,
|
|||
private ReferenceConfig referenceConfig;
|
||||
|
||||
// Registration sources of this reference, may be xml file or annotation location
|
||||
private List<Map<String,Object>> sources = new ArrayList<>();
|
||||
private List<Map<String, Object>> sources = new ArrayList<>();
|
||||
|
||||
public ReferenceBean() {
|
||||
super();
|
||||
|
|
@ -164,24 +164,23 @@ public class ReferenceBean<T> implements FactoryBean<T>,
|
|||
*
|
||||
* <p></p>
|
||||
* Why we need a lazy proxy?
|
||||
*
|
||||
* <p>
|
||||
* <p/>
|
||||
* 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.
|
||||
* <br/>
|
||||
* (This has already been resolved by decorating the BeanDefinition: {@link DubboBeanDefinitionParser#configReferenceBean})
|
||||
*
|
||||
* <p>
|
||||
* <p/>
|
||||
* 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.
|
||||
*
|
||||
* <p>
|
||||
* <p/>
|
||||
* When it is initialized, only a lazy proxy object will be created,
|
||||
* and dubbo reference-related resources will not be initialized.
|
||||
* <br/>
|
||||
* 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 class ReferenceBean<T> implements FactoryBean<T>,
|
|||
// 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 class ReferenceBean<T> implements FactoryBean<T>,
|
|||
|
||||
/**
|
||||
* The interface of this ReferenceBean, for injection purpose
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Class<?> getInterfaceClass() {
|
||||
|
|
@ -347,7 +353,7 @@ public class ReferenceBean<T> implements FactoryBean<T>,
|
|||
//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 class ReferenceBean<T> implements FactoryBean<T>,
|
|||
}
|
||||
}
|
||||
|
||||
public void setInterfaceClass(Class<?> interfaceClass) {
|
||||
this.interfaceClass = interfaceClass;
|
||||
}
|
||||
|
||||
public void setInterfaceName(String interfaceName) {
|
||||
this.interfaceName = interfaceName;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -368,6 +368,11 @@ public abstract class AbstractAnnotationBeanPostProcessor implements
|
|||
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 @@ public abstract class AbstractAnnotationBeanPostProcessor implements
|
|||
*/
|
||||
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 abstract class AbstractAnnotationBeanPostProcessor implements
|
|||
|
||||
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 @@ public abstract class AbstractAnnotationBeanPostProcessor implements
|
|||
|
||||
public class AnnotatedFieldElement extends AnnotatedInjectElement {
|
||||
|
||||
protected final Field field;
|
||||
public final Field field;
|
||||
|
||||
protected AnnotatedFieldElement(Field field, AnnotationAttributes attributes) {
|
||||
super(field, null, attributes);
|
||||
|
|
|
|||
|
|
@ -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 class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
|
|||
* 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)}.
|
||||
* <p>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 class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
|
|||
|
||||
/**
|
||||
* Alternatives to the {@link #postProcessPropertyValues(PropertyValues, PropertyDescriptor[], Object, String)}.
|
||||
*
|
||||
* @see #postProcessPropertyValues
|
||||
*/
|
||||
@Override
|
||||
|
|
@ -417,7 +419,7 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
|
|||
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)) {
|
||||
|
|
|
|||
|
|
@ -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.DubboService;
|
|||
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.List;
|
|||
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 class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPos
|
|||
this(asList(packagesToScan));
|
||||
}
|
||||
|
||||
public ServiceAnnotationPostProcessor(Collection<String> packagesToScan) {
|
||||
this(new LinkedHashSet<>(packagesToScan));
|
||||
}
|
||||
|
||||
public ServiceAnnotationPostProcessor(Set<String> packagesToScan) {
|
||||
this.packagesToScan = packagesToScan;
|
||||
public ServiceAnnotationPostProcessor(Collection<?> packagesToScan) {
|
||||
this.packagesToScan = (Set<String>) packagesToScan.stream().collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -217,6 +214,9 @@ public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPos
|
|||
continue;
|
||||
}
|
||||
|
||||
if(AotWithSpringDetector.useGeneratedArtifacts()){
|
||||
scanner.setIncludeAnnotationConfig(false);
|
||||
}
|
||||
// Registers @Service Bean first
|
||||
scanner.scan(packageToScan);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import org.apache.dubbo.config.context.AbstractConfigManager;
|
|||
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 class DubboConfigBeanInitializer implements BeanFactoryAware, Initializin
|
|||
private void init() {
|
||||
if (initialized.compareAndSet(false, true)) {
|
||||
referenceBeanManager = beanFactory.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class);
|
||||
configManager = DubboBeanUtils.getConfigManager(beanFactory);
|
||||
try {
|
||||
prepareDubboConfigBeans();
|
||||
referenceBeanManager.prepareReferenceBeans();
|
||||
|
|
|
|||
|
|
@ -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<String, String> 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -73,23 +64,6 @@ public class DubboInfraBeanRegisterPostProcessor implements BeanDefinitionRegist
|
|||
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<String, String> 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);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.apache.dubbo.config.spring.context;
|
|||
|
||||
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<BeanDefinitionRegistry, DubboSpringInitContext> contextMap = new ConcurrentHashMap<>();
|
||||
|
||||
private DubboSpringInitializer() {
|
||||
public DubboSpringInitializer() {
|
||||
}
|
||||
|
||||
public static void initialize(BeanDefinitionRegistry registry) {
|
||||
|
|
@ -140,8 +141,10 @@ public class DubboSpringInitializer {
|
|||
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) {
|
||||
|
|
@ -163,9 +166,15 @@ public class DubboSpringInitializer {
|
|||
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -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 class DubboClassPathBeanDefinitionScanner extends ClassPathBeanDefinition
|
|||
|
||||
setResourceLoader(resourceLoader);
|
||||
|
||||
registerAnnotationConfigProcessors(registry);
|
||||
if (!AotWithSpringDetector.useGeneratedArtifacts()) {
|
||||
registerAnnotationConfigProcessors(registry);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import org.apache.dubbo.config.annotation.Service;
|
|||
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 class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistra
|
|||
*/
|
||||
private void registerServiceAnnotationPostProcessor(Set<String> 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();
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import org.apache.dubbo.common.utils.StringUtils;
|
|||
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 class ReferenceBeanSupport {
|
|||
|
||||
public static String generateReferenceKey(Map<String, Object> 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);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.apache.dubbo.config.spring.schema;
|
|||
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 @@ public class AnnotationBeanDefinitionParser extends AbstractSingleBeanDefinition
|
|||
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return ServiceAnnotationPostProcessor.class;
|
||||
return SpringCompatUtils.serviceAnnotationPostProcessor();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import org.apache.dubbo.config.TracingConfig;
|
|||
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;
|
||||
|
||||
|
|
@ -94,6 +95,8 @@ public class DubboNamespaceHandler extends NamespaceHandlerSupport implements Co
|
|||
* @since 2.7.5
|
||||
*/
|
||||
private void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(registry);
|
||||
if (!AotWithSpringDetector.useGeneratedArtifacts()) {
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(registry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 @@ public interface DubboBeanUtils {
|
|||
|
||||
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 @@ public interface DubboBeanUtils {
|
|||
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 @@ public interface DubboBeanUtils {
|
|||
return null;
|
||||
}
|
||||
|
||||
static ConfigManager getConfigManager(BeanFactory beanFactory) {
|
||||
String beanName = ConfigManager.BEAN_NAME;
|
||||
if (beanFactory.containsBean(beanName)) {
|
||||
return beanFactory.getBean(beanName, ConfigManager.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ package org.apache.dubbo.config.spring.util;
|
|||
|
||||
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.ParameterizedType;
|
|||
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 class SpringCompatUtils {
|
|||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-config</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dubbo-config-spring6</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring.version>6.0.7</spring.version>
|
||||
<spring-boot.version>3.0.4</spring-boot.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-config-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-config-spring</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
</exclusion>
|
||||
<!-- Fix the bug of log4j refer:https://github.com/apache/logging-log4j2/pull/608 -->
|
||||
<exclusion>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 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}.
|
||||
* </p>
|
||||
*
|
||||
* @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<InjectionMetadata.InjectedElement, String> injectedFieldReferenceBeanCache =
|
||||
new ConcurrentHashMap<>(CACHE_SIZE);
|
||||
|
||||
private final ConcurrentMap<InjectionMetadata.InjectedElement, String> 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
|
||||
* <p>
|
||||
* {@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<BeanPostProcessor> 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
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
* public class ConsumerConfig {
|
||||
*
|
||||
* @Bean
|
||||
* @DubboReference(group="demo", version="1.2.3")
|
||||
* public ReferenceBean<DemoService> demoService() {
|
||||
* return new ReferenceBean();
|
||||
* }
|
||||
*
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @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<DemoService>
|
||||
// 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<DemoService>. Please check bean method: " + beanMethodSignature);
|
||||
}
|
||||
|
||||
// get dubbo reference annotation attributes
|
||||
Map<String, Object> annotationAttributes = null;
|
||||
// try all dubbo reference annotation types
|
||||
for (Class<? extends Annotation> 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<String, Object> 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<PropertyValue> 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<DemoService>
|
||||
//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)}.
|
||||
* <p>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<String, Object> 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<String> 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<ReferenceBean<?>> getReferenceBeans() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link ReferenceBean} {@link Map} in injected field.
|
||||
*
|
||||
* @return non-null {@link Map}
|
||||
* @since 2.5.11
|
||||
*/
|
||||
public Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> getInjectedFieldReferenceBeanMap() {
|
||||
Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> map = new HashMap<>();
|
||||
for (Map.Entry<InjectionMetadata.InjectedElement, String> 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<InjectionMetadata.InjectedElement, ReferenceBean<?>> getInjectedMethodReferenceBeanMap() {
|
||||
Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> map = new HashMap<>();
|
||||
for (Map.Entry<InjectionMetadata.InjectedElement, String> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* 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}.
|
||||
*
|
||||
* <p>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 <T> void resolve(RegisteredBean registeredBean, ThrowingConsumer<T> 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> T resolve(RegisteredBean registeredBean, Class<T> 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> 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<String> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* 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}.
|
||||
*
|
||||
* <p>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<AutowiredArguments> 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<String> 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(", "));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@
|
|||
<modules>
|
||||
<module>dubbo-config-api</module>
|
||||
<module>dubbo-config-spring</module>
|
||||
<module>dubbo-config-spring6</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
|
|
|||
|
|
@ -1315,6 +1315,34 @@
|
|||
</resource>
|
||||
</transformer>
|
||||
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar
|
||||
</resource>
|
||||
</transformer>
|
||||
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.aot.api.ProxyDescriberRegistrar
|
||||
</resource>
|
||||
</transformer>
|
||||
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.aot.api.ResourceDescriberRegistrar
|
||||
</resource>
|
||||
</transformer>
|
||||
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.common.json.JsonUtil
|
||||
</resource>
|
||||
</transformer>
|
||||
|
||||
</transformers>
|
||||
<filters>
|
||||
<filter>
|
||||
|
|
|
|||
|
|
@ -78,6 +78,12 @@
|
|||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-config-spring6</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- config-center -->
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
|
|
|
|||
|
|
@ -85,6 +85,12 @@
|
|||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-native</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -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<JdkProxyDescriber> getJdkProxyDescribers() {
|
||||
List<JdkProxyDescriber> describers = new ArrayList<>();
|
||||
describers.add(buildJdkProxyDescriber(MetadataService.class));
|
||||
return describers;
|
||||
}
|
||||
|
||||
private JdkProxyDescriber buildJdkProxyDescriber(Class<?> cl) {
|
||||
List<String> proxiedInterfaces = new ArrayList<>();
|
||||
proxiedInterfaces.add(cl.getName());
|
||||
proxiedInterfaces.add(EchoService.class.getName());
|
||||
proxiedInterfaces.add(Destroyable.class.getName());
|
||||
return new JdkProxyDescriber(proxiedInterfaces, null);
|
||||
}
|
||||
}
|
||||
|
|
@ -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<TypeDescriber> getTypeDescribers() {
|
||||
List<TypeDescriber> typeDescribers = new ArrayList<>();
|
||||
typeDescribers.add(buildTypeDescriberWithPublicMethod(MetadataService.class));
|
||||
typeDescribers.add(buildTypeDescriberWithDeclaredConstructors(MetadataInfo.class));
|
||||
return typeDescribers;
|
||||
}
|
||||
|
||||
private TypeDescriber buildTypeDescriberWithPublicMethod(Class<?> cl) {
|
||||
Set<MemberCategory> 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<MemberCategory> memberCategories = new HashSet<>();
|
||||
memberCategories.add(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
||||
return new TypeDescriber(cl.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
metadata=org.apache.dubbo.metadata.aot.MetadataProxyDescriberRegistrar
|
||||
|
|
@ -0,0 +1 @@
|
|||
metadata=org.apache.dubbo.metadata.aot.MetadataReflectionTypeDescriberRegistrar
|
||||
|
|
@ -36,6 +36,13 @@
|
|||
<artifactId>dubbo-metrics-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-native</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-test</artifactId>
|
||||
|
|
|
|||
|
|
@ -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<TypeDescriber> getTypeDescribers() {
|
||||
List<TypeDescriber> typeDescribers = new ArrayList<>();
|
||||
typeDescribers.add(buildTypeDescriberWithDeclaredConstructors(HistogramMetricsCollector.class));
|
||||
return typeDescribers;
|
||||
}
|
||||
|
||||
private TypeDescriber buildTypeDescriberWithDeclaredConstructors(Class<?> cl) {
|
||||
Set<MemberCategory> memberCategories = new HashSet<>();
|
||||
memberCategories.add(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
||||
return new TypeDescriber(cl.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
defaultMetrics=org.apache.dubbo.metrics.aot.DefaultMetricsReflectionTypeDescriberRegistrar
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -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<String> proxiedInterfaces;
|
||||
|
||||
private final String reachableType;
|
||||
|
||||
|
||||
public JdkProxyDescriber(List<String> proxiedInterfaces, String reachableType) {
|
||||
this.proxiedInterfaces = proxiedInterfaces;
|
||||
this.reachableType = reachableType;
|
||||
}
|
||||
|
||||
public List<String> 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -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<JdkProxyDescriber> getJdkProxyDescribers();
|
||||
}
|
||||
|
|
@ -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<TypeDescriber> getTypeDescribers();
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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<ResourcePatternDescriber> getResourcePatternDescribers();
|
||||
|
||||
List<ResourceBundleDescriber> getResourceBundleDescribers();
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -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 class AotProcessor {
|
|||
.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<TypeDescriber> getTypes() {
|
||||
List<TypeDescriber> typeDescribers = new ArrayList<>();
|
||||
FrameworkModel.defaultModel().defaultApplication().getExtensionLoader(ReflectionTypeDescriberRegistrar.class).getSupportedExtensionInstances().forEach(reflectionTypeDescriberRegistrar -> {
|
||||
typeDescribers.addAll(reflectionTypeDescriberRegistrar.getTypeDescribers());
|
||||
});
|
||||
|
||||
return typeDescribers;
|
||||
}
|
||||
|
||||
private static List<JdkProxyDescriber> getProxyDescribers() {
|
||||
List<JdkProxyDescriber> jdkProxyDescribers = new ArrayList<>();
|
||||
FrameworkModel.defaultModel().defaultApplication().getExtensionLoader(ProxyDescriberRegistrar.class).getSupportedExtensionInstances().forEach(reflectionTypeDescriberRegistrar -> {
|
||||
jdkProxyDescribers.addAll(reflectionTypeDescriberRegistrar.getJdkProxyDescribers());
|
||||
});
|
||||
|
||||
return jdkProxyDescribers;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -93,7 +93,6 @@ public class JarScanner {
|
|||
File[] listFiles = directory.listFiles();
|
||||
if (listFiles != null) {
|
||||
for (File file : listFiles) {
|
||||
System.out.println("scanFile: " + file.getPath());
|
||||
if (file.isDirectory()) {
|
||||
scanFile(file.getPath());
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import java.util.function.Consumer;
|
|||
* Write Write configuration metadata information in
|
||||
* {@link ResourceConfigMetadataRepository} and {@link ReflectConfigMetadataRepository}
|
||||
* as GraalVM native configuration.
|
||||
*
|
||||
* @see <a href="https://www.graalvm.org/latest/reference-manual/native-image/overview/BuildConfiguration/">Native Image Build Configuration</a>
|
||||
*/
|
||||
public class NativeConfigurationWriter {
|
||||
|
|
@ -49,8 +50,7 @@ public class NativeConfigurationWriter {
|
|||
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 @@ public class NativeConfigurationWriter {
|
|||
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 class NativeConfigurationWriter {
|
|||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<JdkProxyDescriber> jdkProxyDescribers;
|
||||
|
||||
public ProxyConfigMetadataRepository() {
|
||||
this.jdkProxyDescribers = new LinkedHashSet<>();
|
||||
}
|
||||
|
||||
public ProxyConfigMetadataRepository registerProxyDescriber(JdkProxyDescriber describer) {
|
||||
this.jdkProxyDescribers.add(describer);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProxyConfigMetadataRepository registerProxyDescribers(List<JdkProxyDescriber> describers) {
|
||||
this.jdkProxyDescribers.addAll(describers.stream().filter(Objects::nonNull).collect(Collectors.toList()));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public Set<JdkProxyDescriber> getProxyDescribers() {
|
||||
return jdkProxyDescribers;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<String, Object> toAttributes(JdkProxyDescriber describer) {
|
||||
Map<String, Object> attributes = new LinkedHashMap<>();
|
||||
handleCondition(attributes, describer);
|
||||
attributes.put("interfaces", describer.getProxiedInterfaces());
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private void handleCondition(Map<String, Object> attributes, JdkProxyDescriber describer) {
|
||||
if (describer.getReachableType() != null) {
|
||||
Map<String, Object> conditionAttributes = new LinkedHashMap<>();
|
||||
conditionAttributes.put("typeReachable", describer.getReachableType());
|
||||
attributes.put("condition", conditionAttributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Objects;
|
|||
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 class ReflectConfigMetadataRepository {
|
|||
this.types = new ArrayList<>();
|
||||
}
|
||||
|
||||
public ReflectConfigMetadataRepository registerSpiExtensionType(List<Class<?>> classes) {
|
||||
protected ReflectConfigMetadataRepository registerSpiExtensionType(List<Class<?>> classes) {
|
||||
types.addAll(classes.stream().filter(Objects::nonNull).map(this::buildTypeDescriberWithConstructor).collect(Collectors.toList()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReflectConfigMetadataRepository registerAdaptiveType(List<Class<?>> classes) {
|
||||
protected ReflectConfigMetadataRepository registerAdaptiveType(List<Class<?>> classes) {
|
||||
types.addAll(classes.stream().filter(Objects::nonNull).map(this::buildTypeDescriberWithConstructor).collect(Collectors.toList()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReflectConfigMetadataRepository registerBeanType(List<Class<?>> classes) {
|
||||
protected ReflectConfigMetadataRepository registerBeanType(List<Class<?>> classes) {
|
||||
types.addAll(classes.stream().filter(Objects::nonNull).map(this::buildTypeDescriberWithConstructor).collect(Collectors.toList()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReflectConfigMetadataRepository registerConfigType(List<Class<?>> classes) {
|
||||
protected ReflectConfigMetadataRepository registerConfigType(List<Class<?>> classes) {
|
||||
types.addAll(classes.stream().filter(Objects::nonNull).map(this::buildTypeDescriberWithConstructor).collect(Collectors.toList()));
|
||||
return this;
|
||||
}
|
||||
|
|
@ -61,6 +64,10 @@ public class ReflectConfigMetadataRepository {
|
|||
return new TypeDescriber(c.getName(), null, new HashSet<>(), constructors, new HashSet<>(), memberCategories);
|
||||
}
|
||||
|
||||
public void registerTypeDescriber(List<TypeDescriber> typeDescribers) {
|
||||
types.addAll(typeDescribers.stream().filter(Objects::nonNull).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public List<TypeDescriber> getTypes() {
|
||||
return types;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -75,5 +75,11 @@
|
|||
<artifactId>dubbo-qos-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-native</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -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<TypeDescriber> getTypeDescribers() {
|
||||
List<TypeDescriber> typeDescribers = new ArrayList<>();
|
||||
typeDescribers.add(buildTypeDescriberWithPublicMethod(SelectorProvider.class));
|
||||
return typeDescribers;
|
||||
}
|
||||
|
||||
private TypeDescriber buildTypeDescriberWithPublicMethod(Class<?> cl) {
|
||||
Set<MemberCategory> memberCategories = new HashSet<>();
|
||||
memberCategories.add(MemberCategory.INVOKE_PUBLIC_METHODS);
|
||||
return new TypeDescriber(cl.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
qos=org.apache.dubbo.qos.aot.QosReflectionTypeDescriberRegistrar
|
||||
|
|
@ -105,5 +105,11 @@
|
|||
<version>${project.parent.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-native</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -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 class RegistryScopeModelInitializer implements ScopeModelInitializer {
|
|||
public void initializeApplicationModel(ApplicationModel applicationModel) {
|
||||
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
|
||||
beanFactory.registerBean(RegistryManager.class);
|
||||
beanFactory.registerBean(MetadataServiceDelegation.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -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<TypeDescriber> getTypeDescribers() {
|
||||
List<TypeDescriber> typeDescribers = new ArrayList<>();
|
||||
typeDescribers.add(buildTypeDescriberWithDeclaredMethod(MetadataServiceDelegation.class));
|
||||
|
||||
return typeDescribers;
|
||||
}
|
||||
|
||||
private TypeDescriber buildTypeDescriberWithDeclaredMethod(Class<?> cl) {
|
||||
Set<MemberCategory> 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 class MetadataUtils {
|
|||
|
||||
url = url.setServiceModel(consumerModel);
|
||||
|
||||
if (NativeDetector.inNativeImage()) {
|
||||
url = url.addParameter("proxy", "jdk");
|
||||
}
|
||||
|
||||
Invoker<MetadataService> invoker = protocol.refer(MetadataService.class, url);
|
||||
|
||||
ProxyFactory proxyFactory = applicationModel.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
registry=org.apache.dubbo.registry.aot.RegistryReflectionTypeDescriberRegistrar
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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 java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class ZookeeperReflectionTypeDescriberRegistrar implements ReflectionTypeDescriberRegistrar {
|
||||
|
||||
@Override
|
||||
public List<TypeDescriber> getTypeDescribers() {
|
||||
List<TypeDescriber> typeDescribers = new ArrayList<>();
|
||||
typeDescribers.add(buildTypeDescriberWithDeclared(ZookeeperInstance.class));
|
||||
|
||||
return typeDescribers;
|
||||
}
|
||||
|
||||
private TypeDescriber buildTypeDescriberWithDeclared(Class<?> cl) {
|
||||
Set<MemberCategory> 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
zookeeper=org.apache.dubbo.registry.zookeeper.aot.ZookeeperReflectionTypeDescriberRegistrar
|
||||
|
|
@ -69,5 +69,11 @@
|
|||
<classifier>linux-aarch_64</classifier>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-native</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -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<TypeDescriber> getTypeDescribers() {
|
||||
List<TypeDescriber> 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<MemberCategory> memberCategories = new HashSet<>();
|
||||
memberCategories.add(MemberCategory.INVOKE_DECLARED_METHODS);
|
||||
return new TypeDescriber(c.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
netty4=org.apache.dubbo.remoting.transport.netty4.aot.Netty4ReflectionTypeDescriberRegistrar
|
||||
|
|
@ -59,5 +59,11 @@
|
|||
<artifactId>zookeeper</artifactId>
|
||||
<version>${zookeeper_version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-native</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -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<TypeDescriber> getTypeDescribers() {
|
||||
List<TypeDescriber> 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<MemberCategory> 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<MemberCategory> memberCategories = new HashSet<>();
|
||||
memberCategories.add(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
||||
return new TypeDescriber(c.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
curator5Zookeeper=org.apache.dubbo.remoting.zookeeper.curator5.aot.Curator5ZookeeperReflectionTypeDescriberRegistrar
|
||||
|
|
@ -57,6 +57,13 @@
|
|||
<artifactId>curator-x-discovery</artifactId>
|
||||
<version>${curator_version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-native</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.zookeeper</groupId>
|
||||
<artifactId>zookeeper</artifactId>
|
||||
|
|
|
|||
|
|
@ -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<TypeDescriber> getTypeDescribers() {
|
||||
List<TypeDescriber> typeDescribers = new ArrayList<>();
|
||||
typeDescribers.add(buildTypeDescriberWithDeclaredConstructors(ClientCnxnSocketNIO.class));
|
||||
return typeDescribers;
|
||||
}
|
||||
|
||||
private TypeDescriber buildTypeDescriberWithDeclaredMethods(Class<?> c){
|
||||
Set<MemberCategory> 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<MemberCategory> memberCategories = new HashSet<>();
|
||||
memberCategories.add(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
||||
return new TypeDescriber(c.getName(), null, new HashSet<>(), new HashSet<>(), new HashSet<>(), memberCategories);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
curatorZookeeper=org.apache.dubbo.remoting.zookeeper.curator.aot.CuratorZookeeperReflectionTypeDescriberRegistrar
|
||||
|
|
@ -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<Framewo
|
|||
/**
|
||||
* An empty classLoader used when classLoader is system classLoader. Prevent the NPE.
|
||||
*/
|
||||
private static final ClassLoader SYSTEM_CLASSLOADER_KEY = new ClassLoader() {};
|
||||
private static final ClassLoader SYSTEM_CLASSLOADER_KEY = new ClassLoader() {
|
||||
};
|
||||
|
||||
private final Map<ClassLoader, ObjectReaderCreatorASM> readerMap = new ConcurrentHashMap<>();
|
||||
private final Map<ClassLoader, ObjectWriterCreatorASM> writerMap = new ConcurrentHashMap<>();
|
||||
private final Map<ClassLoader, ObjectReaderCreator> readerMap = new ConcurrentHashMap<>();
|
||||
private final Map<ClassLoader, ObjectWriterCreator> writerMap = new ConcurrentHashMap<>();
|
||||
|
||||
public Fastjson2CreatorManager(FrameworkModel frameworkModel) {
|
||||
frameworkModel.addClassLoaderListener(this);
|
||||
|
|
@ -44,8 +48,13 @@ public class Fastjson2CreatorManager implements ScopeClassLoaderListener<Framewo
|
|||
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
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import org.apache.dubbo.config.annotation.DubboService;
|
|||
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;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
|
|
@ -30,6 +30,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
|||
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;
|
||||
|
|
@ -63,8 +64,14 @@ public class DubboAutoConfiguration {
|
|||
@ConditionalOnBean(name = BASE_PACKAGES_BEAN_NAME)
|
||||
@Bean
|
||||
public ServiceAnnotationPostProcessor serviceAnnotationBeanProcessor(@Qualifier(BASE_PACKAGES_BEAN_NAME)
|
||||
Set<String> packagesToScan) {
|
||||
return new ServiceAnnotationPostProcessor(packagesToScan);
|
||||
Set<String> packagesToScan) {
|
||||
ServiceAnnotationPostProcessor serviceAnnotationPostProcessor;
|
||||
try {
|
||||
serviceAnnotationPostProcessor = (ServiceAnnotationPostProcessor) SpringCompatUtils.serviceAnnotationPostProcessor().getDeclaredConstructor(Collection.class).newInstance(packagesToScan);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return serviceAnnotationPostProcessor;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ package org.apache.dubbo.spring.boot.autoconfigure;
|
|||
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.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import org.apache.dubbo.config.bootstrap.DubboBootstrap;
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -66,6 +66,10 @@
|
|||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-config-spring</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-config-spring6</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- config-center -->
|
||||
<dependency>
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ class FileTest {
|
|||
|
||||
ignoredArtifacts.add(Pattern.compile("dubbo-demo.*"));
|
||||
ignoredArtifacts.add(Pattern.compile("dubbo-test.*"));
|
||||
ignoredArtifacts.add(Pattern.compile("dubbo-config-spring6.*"));
|
||||
ignoredArtifacts.add(Pattern.compile("dubbo-annotation-processor"));
|
||||
|
||||
ignoredModulesInDubboAll.add(Pattern.compile("dubbo"));
|
||||
|
|
@ -63,6 +64,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-annotation-processor.*"));
|
||||
ignoredModulesInDubboAll.add(Pattern.compile("dubbo-maven-plugin"));
|
||||
|
|
|
|||
4
pom.xml
4
pom.xml
|
|
@ -345,8 +345,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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue