excludeBeanNames;
+
+ /**
+ * Set the names of the beans that should not automatically get wrapped with proxies.
+ * A name can specify a prefix to match by ending with "*", e.g. "myBean,tx*"
+ * will match the bean named "myBean" and all beans whose name start with "tx".
+ * NOTE: In case of a FactoryBean, only the objects created by the
+ * FactoryBean will get proxied. This default behavior applies as of Spring 2.0.
+ * If you intend to proxy a FactoryBean instance itself (a rare use case, but
+ * Spring 1.2's default behavior), specify the bean name of the FactoryBean
+ * including the factory-bean prefix "&": e.g. "&myFactoryBean".
+ * @see org.springframework.beans.factory.FactoryBean
+ * @see org.springframework.beans.factory.BeanFactory#FACTORY_BEAN_PREFIX
+ */
+ public void setExcludeBeanNames(String... beanNames) {
+ Assert.notEmpty(beanNames, "'excludeBeanNames' must not be empty");
+ this.excludeBeanNames = new ArrayList<>(beanNames.length);
+ for (String mappedName : beanNames) {
+ this.excludeBeanNames.add(mappedName.strip());
+ }
+ }
+
+ @Override
+ protected boolean isMatch(String beanName, String mappedName) {
+ return super.isMatch(beanName, mappedName) && !isExcluded(beanName);
+ }
+
+ private boolean isExcluded(String beanName) {
+ if (excludeBeanNames != null) {
+ for (String mappedName : this.excludeBeanNames) {
+ if (PatternMatchUtils.simpleMatch(mappedName, beanName)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/constant/SofaBootConstants.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/constant/SofaBootConstants.java
index 824488b0d..e5e304ec7 100644
--- a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/constant/SofaBootConstants.java
+++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/constant/SofaBootConstants.java
@@ -88,7 +88,7 @@ public class SofaBootConstants {
/**
* Default exposure web endpoint list
*/
- public static final String SOFA_DEFAULT_ENDPOINTS_WEB_EXPOSURE_VALUE = "info,health,readiness,startup,beans,components,rpc,isle";
+ public static final String SOFA_DEFAULT_ENDPOINTS_WEB_EXPOSURE_VALUE = "info,health,readiness,startup,beans,components,rpc,isle,threadpool,sbom";
/**
* CPU core
diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/context/SofaDefaultListableBeanFactory.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/context/SofaDefaultListableBeanFactory.java
index 9e8b9ee4e..18cfad609 100644
--- a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/context/SofaDefaultListableBeanFactory.java
+++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/context/SofaDefaultListableBeanFactory.java
@@ -17,6 +17,7 @@
package com.alipay.sofa.boot.context;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.util.ObjectUtils;
/**
* Default Implementation of {@link DefaultListableBeanFactory} in SOFABoot framework.
@@ -28,4 +29,14 @@
* @since 4.0.0
*/
public class SofaDefaultListableBeanFactory extends DefaultListableBeanFactory {
+
+ private String id = ObjectUtils.identityToString(this);
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return this.id;
+ }
}
diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/spring/parameter/LocalVariableTableParameterNameDiscoverer.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/spring/parameter/LocalVariableTableParameterNameDiscoverer.java
new file mode 100644
index 000000000..4d4867aa3
--- /dev/null
+++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/spring/parameter/LocalVariableTableParameterNameDiscoverer.java
@@ -0,0 +1,270 @@
+/*
+ * 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 com.alipay.sofa.boot.spring.parameter;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.asm.ClassReader;
+import org.springframework.asm.ClassVisitor;
+import org.springframework.asm.Label;
+import org.springframework.asm.MethodVisitor;
+import org.springframework.asm.Opcodes;
+import org.springframework.asm.SpringAsmInfo;
+import org.springframework.asm.Type;
+import org.springframework.core.BridgeMethodResolver;
+import org.springframework.core.ParameterNameDiscoverer;
+import org.springframework.lang.Nullable;
+import org.springframework.util.ClassUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Deprecate in spring, fork codes for compatible
+ */
+@Deprecated
+public class LocalVariableTableParameterNameDiscoverer implements ParameterNameDiscoverer {
+
+ private static final Log logger = LogFactory
+ .getLog(LocalVariableTableParameterNameDiscoverer.class);
+
+ // marker object for classes that do not have any debug info
+ private static final Map NO_DEBUG_INFO_MAP = Collections
+ .emptyMap();
+
+ // the cache uses a nested index (value is a map) to keep the top level cache relatively small in size
+ private final Map, Map> parameterNamesCache = new ConcurrentHashMap<>(
+ 32);
+
+ @Override
+ @Nullable
+ public String[] getParameterNames(Method method) {
+ Method originalMethod = BridgeMethodResolver.findBridgedMethod(method);
+ return doGetParameterNames(originalMethod);
+ }
+
+ @Override
+ @Nullable
+ public String[] getParameterNames(Constructor> ctor) {
+ return doGetParameterNames(ctor);
+ }
+
+ @Nullable
+ private String[] doGetParameterNames(Executable executable) {
+ Class> declaringClass = executable.getDeclaringClass();
+ Map map = this.parameterNamesCache.computeIfAbsent(declaringClass, this::inspectClass);
+ return (map != NO_DEBUG_INFO_MAP ? map.get(executable) : null);
+ }
+
+ /**
+ * Inspects the target class.
+ * Exceptions will be logged, and a marker map returned to indicate the
+ * lack of debug information.
+ */
+ private Map inspectClass(Class> clazz) {
+ InputStream is = clazz.getResourceAsStream(ClassUtils.getClassFileName(clazz));
+ if (is == null) {
+ // We couldn't load the class file, which is not fatal as it
+ // simply means this method of discovering parameter names won't work.
+ if (logger.isDebugEnabled()) {
+ logger.debug("Cannot find '.class' file for class [" + clazz
+ + "] - unable to determine constructor/method parameter names");
+ }
+ return NO_DEBUG_INFO_MAP;
+ }
+ // We cannot use try-with-resources here for the InputStream, since we have
+ // custom handling of the close() method in a finally-block.
+ try {
+ ClassReader classReader = new ClassReader(is);
+ Map map = new ConcurrentHashMap<>(32);
+ classReader.accept(new ParameterNameDiscoveringVisitor(clazz, map), 0);
+ if (logger.isWarnEnabled()) {
+ logger
+ .warn("Using deprecated '-debug' fallback for parameter name resolution. Compile the "
+ + "affected code with '-parameters' instead or avoid its introspection: "
+ + clazz.getName());
+ }
+ return map;
+ } catch (IOException ex) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Exception thrown while reading '.class' file for class [" + clazz
+ + "] - unable to determine constructor/method parameter names", ex);
+ }
+ } catch (IllegalArgumentException ex) {
+ if (logger.isDebugEnabled()) {
+ logger
+ .debug(
+ "ASM ClassReader failed to parse class file ["
+ + clazz
+ + "], probably due to a new Java class file version that isn't supported yet "
+ + "- unable to determine constructor/method parameter names", ex);
+ }
+ } finally {
+ try {
+ is.close();
+ } catch (IOException ex) {
+ // ignore
+ }
+ }
+ return NO_DEBUG_INFO_MAP;
+ }
+
+ /**
+ * Helper class that inspects all methods and constructors and then
+ * attempts to find the parameter names for the given {@link Executable}.
+ */
+ private static class ParameterNameDiscoveringVisitor extends ClassVisitor {
+
+ private static final String STATIC_CLASS_INIT = "";
+
+ private final Class> clazz;
+
+ private final Map executableMap;
+
+ public ParameterNameDiscoveringVisitor(Class> clazz,
+ Map executableMap) {
+ super(SpringAsmInfo.ASM_VERSION);
+ this.clazz = clazz;
+ this.executableMap = executableMap;
+ }
+
+ @Override
+ @Nullable
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+ String[] exceptions) {
+ // exclude synthetic + bridged && static class initialization
+ if (!isSyntheticOrBridged(access) && !STATIC_CLASS_INIT.equals(name)) {
+ return new LocalVariableTableVisitor(this.clazz, this.executableMap, name, desc,
+ isStatic(access));
+ }
+ return null;
+ }
+
+ private static boolean isSyntheticOrBridged(int access) {
+ return (((access & Opcodes.ACC_SYNTHETIC) | (access & Opcodes.ACC_BRIDGE)) > 0);
+ }
+
+ private static boolean isStatic(int access) {
+ return ((access & Opcodes.ACC_STATIC) > 0);
+ }
+ }
+
+ private static class LocalVariableTableVisitor extends MethodVisitor {
+
+ private static final String CONSTRUCTOR = "";
+
+ private final Class> clazz;
+
+ private final Map executableMap;
+
+ private final String name;
+
+ private final Type[] args;
+
+ private final String[] parameterNames;
+
+ private final boolean isStatic;
+
+ private boolean hasLvtInfo = false;
+
+ /*
+ * The nth entry contains the slot index of the LVT table entry holding the
+ * argument name for the nth parameter.
+ */
+ private final int[] lvtSlotIndex;
+
+ public LocalVariableTableVisitor(Class> clazz, Map map,
+ String name, String desc, boolean isStatic) {
+ super(SpringAsmInfo.ASM_VERSION);
+ this.clazz = clazz;
+ this.executableMap = map;
+ this.name = name;
+ this.args = Type.getArgumentTypes(desc);
+ this.parameterNames = new String[this.args.length];
+ this.isStatic = isStatic;
+ this.lvtSlotIndex = computeLvtSlotIndices(isStatic, this.args);
+ }
+
+ @Override
+ public void visitLocalVariable(String name, String description, String signature,
+ Label start, Label end, int index) {
+ this.hasLvtInfo = true;
+ for (int i = 0; i < this.lvtSlotIndex.length; i++) {
+ if (this.lvtSlotIndex[i] == index) {
+ this.parameterNames[i] = name;
+ }
+ }
+ }
+
+ @Override
+ public void visitEnd() {
+ if (this.hasLvtInfo || (this.isStatic && this.parameterNames.length == 0)) {
+ // visitLocalVariable will never be called for static no args methods
+ // which doesn't use any local variables.
+ // This means that hasLvtInfo could be false for that kind of methods
+ // even if the class has local variable info.
+ this.executableMap.put(resolveExecutable(), this.parameterNames);
+ }
+ }
+
+ private Executable resolveExecutable() {
+ ClassLoader loader = this.clazz.getClassLoader();
+ Class>[] argTypes = new Class>[this.args.length];
+ for (int i = 0; i < this.args.length; i++) {
+ argTypes[i] = ClassUtils.resolveClassName(this.args[i].getClassName(), loader);
+ }
+ try {
+ if (CONSTRUCTOR.equals(this.name)) {
+ return this.clazz.getDeclaredConstructor(argTypes);
+ }
+ return this.clazz.getDeclaredMethod(this.name, argTypes);
+ } catch (NoSuchMethodException ex) {
+ throw new IllegalStateException(
+ "Method ["
+ + this.name
+ + "] was discovered in the .class file but cannot be resolved in the class object",
+ ex);
+ }
+ }
+
+ private static int[] computeLvtSlotIndices(boolean isStatic, Type[] paramTypes) {
+ int[] lvtIndex = new int[paramTypes.length];
+ int nextIndex = (isStatic ? 0 : 1);
+ for (int i = 0; i < paramTypes.length; i++) {
+ lvtIndex[i] = nextIndex;
+ if (isWideType(paramTypes[i])) {
+ nextIndex += 2;
+ } else {
+ nextIndex++;
+ }
+ }
+ return lvtIndex;
+ }
+
+ private static boolean isWideType(Type aType) {
+ // float is not a wide type
+ return (aType == Type.LONG_TYPE || aType == Type.DOUBLE_TYPE);
+ }
+ }
+
+}
diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/startup/StartupReporter.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/startup/StartupReporter.java
index f8414699b..88e49d820 100644
--- a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/startup/StartupReporter.java
+++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/startup/StartupReporter.java
@@ -53,6 +53,10 @@ public class StartupReporter {
public static final String SPRING_CONTEXT_BEAN_FACTORY_POST_PROCESSOR = "spring.context.bean-factory.post-process";
+ public static final String SPRING_BEAN_POST_PROCESSOR = "spring.context.beans.post-process";
+
+ public static final String SPRING_CONFIG_CLASSES_ENHANCE = "spring.context.config-classes.enhance";
+
public static final Collection SPRING_BEAN_INSTANTIATE_TYPES = Set
.of(SPRING_BEANS_INSTANTIATE,
SPRING_BEANS_SMART_INSTANTIATE);
@@ -61,6 +65,10 @@ public class StartupReporter {
.of(SPRING_CONTEXT_BEANDEF_REGISTRY_POST_PROCESSOR,
SPRING_CONTEXT_BEAN_FACTORY_POST_PROCESSOR);
+ public static final Collection SPRING_CONFIG_CLASSES_ENHANCE_TYPES = Set
+ .of(SPRING_CONFIG_CLASSES_ENHANCE,
+ SPRING_BEAN_POST_PROCESSOR);
+
private final StartupStaticsModel startupStaticsModel;
private final List beanStatCustomizers;
@@ -216,7 +224,9 @@ public List generateBeanStats(ConfigurableApplicationContext context)
private boolean filterBeanInitializeByCost(BeanStat beanStat) {
String name = beanStat.getType();
- if (SPRING_BEAN_INSTANTIATE_TYPES.contains(name)) {
+ if (SPRING_BEAN_INSTANTIATE_TYPES.contains(name)
+ || SPRING_CONTEXT_POST_PROCESSOR_TYPES.contains(name)
+ || SPRING_CONFIG_CLASSES_ENHANCE_TYPES.contains(name)) {
return beanStat.getCost() >= costThreshold;
} else {
return true;
diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/startup/StartupSpringApplicationRunListener.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/startup/StartupSpringApplicationRunListener.java
index 8d0298673..97508485d 100644
--- a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/startup/StartupSpringApplicationRunListener.java
+++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/startup/StartupSpringApplicationRunListener.java
@@ -42,29 +42,24 @@
*/
public class StartupSpringApplicationRunListener implements SpringApplicationRunListener, Ordered {
- private final SpringApplication application;
+ private final SpringApplication application;
- private final String[] args;
+ private final String[] args;
- private final StartupReporter startupReporter;
+ private final StartupReporter startupReporter;
- private final ApplicationStartup userApplicationStartup;
+ private BaseStat jvmStartingStage;
- private BufferingApplicationStartup applicationStartup;
+ private BaseStat environmentPrepareStage;
- private BaseStat jvmStartingStage;
+ private ChildrenStat applicationContextPrepareStage;
- private BaseStat environmentPrepareStage;
-
- private ChildrenStat applicationContextPrepareStage;
-
- private BaseStat applicationContextLoadStage;
+ private BaseStat applicationContextLoadStage;
public StartupSpringApplicationRunListener(SpringApplication springApplication, String[] args) {
this.application = springApplication;
this.args = args;
this.startupReporter = new StartupReporter();
- this.userApplicationStartup = springApplication.getApplicationStartup();
}
@Override
@@ -84,16 +79,12 @@ public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
environmentPrepareStage.setEndTime(System.currentTimeMillis());
startupReporter.setAppName(environment.getProperty(SofaBootConstants.APP_NAME_KEY));
startupReporter.bindToStartupReporter(environment);
+ bootstrapContext.register(StartupReporter.class, key -> startupReporter);
// create BufferingApplicationStartup if user not custom.
+ ApplicationStartup userApplicationStartup = application.getApplicationStartup();
if (ApplicationStartup.DEFAULT == userApplicationStartup || userApplicationStartup == null) {
- this.applicationStartup = new BufferingApplicationStartup(startupReporter.getBufferSize());
- } else if (userApplicationStartup instanceof BufferingApplicationStartup userApplicationStartup) {
- // use user custom BufferingApplicationStartup
- this.applicationStartup = userApplicationStartup;
- } else {
- // disable startup static when user custom other type ApplicationStartup;
- this.applicationStartup = null;
+ application.setApplicationStartup(new BufferingApplicationStartup(startupReporter.getBufferSize()));
}
}
@@ -109,9 +100,6 @@ public void contextPrepared(ConfigurableApplicationContext context) {
applicationContextPrepareStage.setChildren(new ArrayList<>(baseStatList));
baseStatList.clear();
}
- if (applicationStartup != null) {
- context.setApplicationStartup(applicationStartup);
- }
}
@Override
@@ -156,7 +144,7 @@ public void started(ConfigurableApplicationContext context, Duration timeTaken)
@Override
public int getOrder() {
- return Ordered.LOWEST_PRECEDENCE;
+ return Ordered.LOWEST_PRECEDENCE - 10;
}
private String getStartedMessage(Environment environment, Duration timeTakenToStartup) {
diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/util/ModuleUtil.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/util/ModuleUtil.java
new file mode 100644
index 000000000..1e19b81cd
--- /dev/null
+++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/util/ModuleUtil.java
@@ -0,0 +1,253 @@
+/*
+ * 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 com.alipay.sofa.boot.util;
+
+import com.alipay.sofa.boot.log.SofaBootLoggerFactory;
+import org.slf4j.Logger;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Field;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * @author huazhongming
+ * @since 4.4.0
+ */
+public class ModuleUtil {
+
+ private static final Logger LOGGER = SofaBootLoggerFactory
+ .getLogger(ModuleUtil.class);
+
+ private static final MethodHandle implAddOpensToAllUnnamed;
+
+ private static final MethodHandle implAddOpens;
+
+ private static final MethodHandle implAddExportsToAllUnnamed;
+
+ private static final MethodHandle implAddExports;
+
+ private static final Map nameToModules;
+
+ private static final AtomicBoolean isExported = new AtomicBoolean(false);
+
+ static {
+ implAddOpensToAllUnnamed = createModuleMethodHandle("implAddOpensToAllUnnamed",
+ String.class);
+ implAddOpens = createModuleMethodHandle("implAddOpens", String.class);
+ implAddExportsToAllUnnamed = createModuleMethodHandle("implAddExportsToAllUnnamed",
+ String.class);
+ implAddExports = createModuleMethodHandle("implAddExports", String.class);
+ nameToModules = getNameToModule();
+ }
+
+ /**
+ * Export all JDK module packages to all.
+ */
+ public static void exportAllJDKModulePackageToAll() {
+ try {
+ if (isExported.compareAndSet(false,true) && nameToModules != null) {
+ nameToModules.forEach((name, module) -> module.getPackages().forEach(pkgName -> {
+ if (isJDKModulePackage(module.getName())) {
+ addOpensToAll(module, pkgName);
+ addExportsToAll(module, pkgName);
+ }
+ }));
+ }
+ } catch (Throwable t) {
+ LOGGER.error("Failed to export all JDK module package to all", t);
+ }
+ }
+
+ private static boolean isJDKModulePackage(String modulePackageName) {
+ return modulePackageName.startsWith("java.") || modulePackageName.startsWith("jdk.");
+ }
+
+ /**
+ * Export all module packages to all.
+ */
+ public static void exportAllModulePackageToAll() {
+ try {
+ if (isExported.compareAndSet(false,true) && nameToModules != null) {
+ nameToModules.forEach((name, module) -> module.getPackages().forEach(pkgName -> {
+ addOpensToAll(module, pkgName);
+ addExportsToAll(module, pkgName);
+ }));
+ }
+ } catch (Throwable t) {
+ LOGGER.error("Failed to export all module package to all", t);
+ }
+ }
+
+ /**
+ * Updates this module to open a package to all unnamed modules.
+ *
+ * @param moduleName
+ * @param packageName
+ */
+ public static boolean addOpensToAllUnnamed(String moduleName, String packageName) {
+ return invokeModuleMethod(implAddOpensToAllUnnamed, moduleName, packageName);
+ }
+
+ /**
+ * Updates this module to open a package to all unnamed modules.
+ *
+ * @param module
+ * @param packageName
+ */
+ public static boolean addOpensToAllUnnamed(Module module, String packageName) {
+ return invokeModuleMethod(implAddOpensToAllUnnamed, module, packageName);
+ }
+
+ /**
+ * Updates this module to export a package to all unnamed modules.
+ *
+ * @param moduleName
+ * @param packageName
+ */
+ public static boolean addExportsToAllUnnamed(String moduleName, String packageName) {
+ return invokeModuleMethod(implAddExportsToAllUnnamed, moduleName, packageName);
+ }
+
+ /**
+ * Updates this module to export a package to all unnamed modules.
+ *
+ * @param module
+ * @param packageName
+ */
+ public static boolean addExportsToAllUnnamed(Module module, String packageName) {
+ return invokeModuleMethod(implAddExportsToAllUnnamed, module, packageName);
+ }
+
+ /**
+ * Updates this module to open a package to another module.
+ *
+ * @param moduleName
+ * @param packageName
+ */
+ public static boolean addOpensToAll(String moduleName, String packageName) {
+
+ return invokeModuleMethod(implAddOpens, moduleName, packageName);
+ }
+
+ /**
+ * Updates this module to open a package to another module.
+ *
+ * @param module
+ * @param packageName
+ */
+ public static boolean addOpensToAll(Module module, String packageName) {
+
+ return invokeModuleMethod(implAddOpens, module, packageName);
+ }
+
+ /**
+ * Updates this module to export a package unconditionally.
+ * @param moduleName
+ * @param packageName
+ */
+ public static boolean addExportsToAll(String moduleName, String packageName) {
+ return invokeModuleMethod(implAddExports, moduleName, packageName);
+ }
+
+ /**
+ * Updates this module to export a package unconditionally.
+ * @param module
+ * @param packageName
+ */
+ public static boolean addExportsToAll(Module module, String packageName) {
+ return invokeModuleMethod(implAddExports, module, packageName);
+ }
+
+ /**
+ * invoke ModuleLayer method
+ *
+ * @param method
+ * @param moduleName
+ * @param packageName
+ * @return
+ */
+ public static boolean invokeModuleMethod(MethodHandle method, String moduleName,
+ String packageName) {
+ Optional findModule = ModuleLayer.boot().findModule(moduleName);
+ if (findModule.isPresent()) {
+ try {
+ return invokeModuleMethod(method, findModule.get(), packageName);
+ } catch (Throwable t) {
+ LOGGER.error("Failed to invoke ModuleLayer method: {}", method, t);
+ }
+ }
+ return false;
+ }
+
+ public static boolean invokeModuleMethod(MethodHandle method, Module module, String packageName) {
+ try {
+ method.invoke(module, packageName);
+ return true;
+ } catch (Throwable t) {
+ LOGGER.error("Failed to invoke Module method: {}", method, t);
+ }
+ return false;
+ }
+
+ /**
+ * create MethodHandle from Module
+ *
+ * @param methodName
+ * @param parameterTypes
+ * @return MethodHandle
+ */
+ private static MethodHandle createModuleMethodHandle(String methodName,
+ Class>... parameterTypes) {
+ try {
+ return UnsafeUtil.implLookup().unreflect(
+ Module.class.getDeclaredMethod(methodName, parameterTypes));
+ } catch (Throwable t) {
+ LOGGER.error("Failed to create Module method handle: {}", methodName, t);
+ }
+ return null;
+ }
+
+ /**
+ * Get ModuleLayer.bootLayer field value
+ *
+ * @param fieldName
+ * @return field value
+ */
+ private static Object getModuleLayerFieldsValue(String fieldName) {
+ ModuleLayer moduleLayer = ModuleLayer.boot();
+ try {
+ Class moduleLayerClass = ModuleLayer.class;
+ Field field = moduleLayerClass.getDeclaredField(fieldName);
+ return UnsafeUtil.implLookup().unreflectVarHandle(field).get(moduleLayer);
+ } catch (Throwable t) {
+ LOGGER.error("Failed to get ModuleLayer field value: {}", fieldName, t);
+ }
+ return null;
+ }
+
+ /**
+ * Get all modules from System.bootLayer
+ *
+ * @return modules
+ */
+ @SuppressWarnings("unchecked")
+ public static Map getNameToModule() {
+ return (Map) getModuleLayerFieldsValue("nameToModule");
+ }
+}
diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/util/UnsafeUtil.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/util/UnsafeUtil.java
new file mode 100644
index 000000000..0bbbca199
--- /dev/null
+++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/util/UnsafeUtil.java
@@ -0,0 +1,61 @@
+/*
+ * 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 com.alipay.sofa.boot.util;
+
+import sun.misc.Unsafe;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Field;
+
+/**
+ * @author huazhongming
+ * @since 4.4.0
+ */
+public class UnsafeUtil {
+ private static Unsafe UNSAFE;
+ private static MethodHandles.Lookup IMPL_LOOKUP;
+
+ public static Unsafe unsafe() {
+ if (UNSAFE == null) {
+ Unsafe unsafe = null;
+ try {
+ Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
+ theUnsafeField.setAccessible(true);
+ unsafe = (Unsafe) theUnsafeField.get(null);
+ } catch (Throwable ignored) {
+ }
+ UNSAFE = unsafe;
+ }
+
+ return UNSAFE;
+ }
+
+ public static MethodHandles.Lookup implLookup() {
+ if (IMPL_LOOKUP == null) {
+ Class lookupClass = MethodHandles.Lookup.class;
+
+ try {
+ Field implLookupField = lookupClass.getDeclaredField("IMPL_LOOKUP");
+ long offset = unsafe().staticFieldOffset(implLookupField);
+ IMPL_LOOKUP = (MethodHandles.Lookup) unsafe().getObject(
+ unsafe().staticFieldBase(implLookupField), offset);
+ } catch (Throwable ignored) {
+ }
+ }
+ return IMPL_LOOKUP;
+ }
+}
diff --git a/sofa-boot-project/sofa-boot/src/main/resources/META-INF/spring.factories b/sofa-boot-project/sofa-boot/src/main/resources/META-INF/spring.factories
index 1aea1f8c4..9ed35930a 100644
--- a/sofa-boot-project/sofa-boot/src/main/resources/META-INF/spring.factories
+++ b/sofa-boot-project/sofa-boot/src/main/resources/META-INF/spring.factories
@@ -15,4 +15,5 @@ org.springframework.boot.SpringApplicationRunListener=\
# Initializers
org.springframework.context.ApplicationContextInitializer=\
- com.alipay.sofa.boot.compatibility.CompatibilityVerifierApplicationContextInitializer
+ com.alipay.sofa.boot.compatibility.CompatibilityVerifierApplicationContextInitializer,\
+ com.alipay.sofa.boot.Initializer.AutoModuleExportApplicationContextInitializer
diff --git a/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/aop/framework/autoproxy/ExcludeBeanNameAutoProxyCreatorTests.java b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/aop/framework/autoproxy/ExcludeBeanNameAutoProxyCreatorTests.java
new file mode 100644
index 000000000..ba9fd9fd9
--- /dev/null
+++ b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/aop/framework/autoproxy/ExcludeBeanNameAutoProxyCreatorTests.java
@@ -0,0 +1,102 @@
+/*
+ * 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 com.alipay.sofa.boot.aop.framework.autoproxy;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link ExcludeBeanNameAutoProxyCreator}.
+ *
+ * @author huzijie
+ * @version ExcludeBeanNameAutoProxyCreatorTests.java, v 0.1 2024年01月04日 4:36 PM huzijie Exp $
+ */
+public class ExcludeBeanNameAutoProxyCreatorTests {
+
+ @Test
+ public void excludeBeanNames() {
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
+ ExcludeBeanNameAutoProxyCreatorTestConfiguration.class);
+ SampleInterface sampleA = context.getBean("sampleA", SampleInterface.class);
+ SampleInterface sampleB = context.getBean("sampleBeanB", SampleInterface.class);
+ SampleInterface sampleC = context.getBean("sampleBeanC", SampleInterface.class);
+ assertThat(sampleA.hello()).isEqualTo("hello");
+ assertThat(sampleB.hello()).isEqualTo("aop");
+ assertThat(sampleC.hello()).isEqualTo("hello");
+ }
+
+ @Configuration
+ static class ExcludeBeanNameAutoProxyCreatorTestConfiguration {
+
+ @Bean
+ public SampleInterface sampleA() {
+ return new SampleInterfaceImpl();
+ }
+
+ @Bean
+ public SampleInterface sampleBeanB() {
+ return new SampleInterfaceImpl();
+ }
+
+ @Bean
+ public SampleInterface sampleBeanC() {
+ return new SampleInterfaceImpl();
+ }
+
+ @Bean
+ public ExcludeBeanNameAutoProxyCreator excludeBeanNameAutoProxyCreator() {
+ ExcludeBeanNameAutoProxyCreator autoProxyCreator = new ExcludeBeanNameAutoProxyCreator();
+ autoProxyCreator.setBeanNames("sampleBean*");
+ autoProxyCreator.setExcludeBeanNames("sampleBeanC");
+ autoProxyCreator.setInterceptorNames("sampleAdvisor");
+ return autoProxyCreator;
+ }
+
+ @Bean
+ public MethodInterceptor sampleAdvisor() {
+ return new MethodInterceptor() {
+ @Nullable
+ @Override
+ public Object invoke(@Nonnull MethodInvocation invocation) {
+ return "aop";
+ }
+ };
+ }
+ }
+
+ interface SampleInterface {
+
+ String hello();
+ }
+
+ static class SampleInterfaceImpl implements SampleInterface {
+
+ @Override
+ public String hello() {
+ return "hello";
+ }
+ }
+}
diff --git a/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/VerificationResultTests.java b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/VerificationResultTests.java
new file mode 100644
index 000000000..664ab4a5c
--- /dev/null
+++ b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/VerificationResultTests.java
@@ -0,0 +1,57 @@
+/*
+ * 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 com.alipay.sofa.boot.compatibility;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link VerificationResult}.
+ *
+ * @author JPSINH27
+ * @version VerificationResultTests, v 0.1 2024年03月02日 10:20 PM
+ */
+public class VerificationResultTests {
+
+ @Test
+ public void testEquals_SameDescriptionAndAction_ReturnsTrue() {
+ VerificationResult result1 = VerificationResult.notCompatible("Error", "Take action");
+ VerificationResult result2 = VerificationResult.notCompatible("Error", "Take action");
+ assertThat(result1).isEqualTo(result2);
+ }
+
+ @Test
+ public void testEquals_DifferentDescriptions_ReturnsFalse() {
+ VerificationResult result1 = VerificationResult.notCompatible("Error 1", "Take action");
+ VerificationResult result2 = VerificationResult.notCompatible("Error 2", "Take action");
+ assertThat(result1).isNotEqualTo(result2);
+ }
+
+ @Test
+ public void testEquals_DifferentActions_ReturnsFalse() {
+ VerificationResult result1 = VerificationResult.notCompatible("Error", "Take action 1");
+ VerificationResult result2 = VerificationResult.notCompatible("Error", "Take action 2");
+ assertThat(result1).isNotEqualTo(result2);
+ }
+
+ @Test
+ public void testEquals_ComparingWithNull_ReturnsFalse() {
+ VerificationResult result1 = VerificationResult.notCompatible("Error", "Take action");
+ assertThat(result1).isNotEqualTo(null);
+ }
+}
\ No newline at end of file
diff --git a/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/initializer/AutoModuleExportApplicationContextInitializerTests.java b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/initializer/AutoModuleExportApplicationContextInitializerTests.java
new file mode 100644
index 000000000..e9d30fa48
--- /dev/null
+++ b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/initializer/AutoModuleExportApplicationContextInitializerTests.java
@@ -0,0 +1,76 @@
+/*
+ * 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 com.alipay.sofa.boot.initializer;
+
+import com.alipay.sofa.boot.Initializer.AutoModuleExportApplicationContextInitializer;
+import com.alipay.sofa.boot.util.ModuleUtil;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.times;
+
+/**
+ * @author huazhongming
+ * @since 4.4.0
+ */
+public class AutoModuleExportApplicationContextInitializerTests {
+
+ private ApplicationContextRunner contextRunner;
+
+ @BeforeEach
+ void setUp() {
+ contextRunner = new ApplicationContextRunner()
+ .withInitializer(new AutoModuleExportApplicationContextInitializer());
+ }
+
+ @Test
+ void jdkDefaultTrue(){
+
+ try (MockedStatic mockedStatic = mockStatic(ModuleUtil.class)) {
+ contextRunner.withPropertyValues().run(applicationContext -> {});
+ mockedStatic.verify(ModuleUtil::exportAllJDKModulePackageToAll, times(1));
+ }
+ }
+
+ @Test
+ void allDefaultFalse(){
+ try (MockedStatic mockedStatic = mockStatic(ModuleUtil.class)) {
+ contextRunner.withPropertyValues().run(applicationContext -> {});
+ mockedStatic.verify(ModuleUtil::exportAllModulePackageToAll, times(0));
+ }
+ }
+
+ @Test
+ void jdkDisable(){
+
+ try (MockedStatic mockedStatic = mockStatic(ModuleUtil.class)) {
+ contextRunner.withPropertyValues("sofa.boot.auto.module.export.jdk.enable=false").run(applicationContext -> {});
+ mockedStatic.verify(ModuleUtil::exportAllJDKModulePackageToAll, times(0));
+ }
+ }
+
+ @Test
+ void allEnable(){
+ try (MockedStatic mockedStatic = mockStatic(ModuleUtil.class)) {
+ contextRunner.withPropertyValues("sofa.boot.auto.module.export.all.enable=true").run(applicationContext -> {});
+ mockedStatic.verify(ModuleUtil::exportAllModulePackageToAll, times(1));
+ }
+ }
+}
diff --git a/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/startup/StartupReporterTests.java b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/startup/StartupReporterTests.java
new file mode 100644
index 000000000..8a405b1d5
--- /dev/null
+++ b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/startup/StartupReporterTests.java
@@ -0,0 +1,69 @@
+/*
+ * 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 com.alipay.sofa.boot.startup;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.ConfigurableEnvironment;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * Tests for {@link StartupReporter}.
+ *
+ * @author JPSINH27
+ * @version StartupReporterTests.java, v 0.1 2024年01月03日 10:19 PM
+ */
+public class StartupReporterTests {
+
+ @Mock
+ ConfigurableApplicationContext mockContext;
+
+ @Mock
+ ConfigurableEnvironment mockEnvironment;
+
+ @BeforeEach
+ public void setup() {
+ MockitoAnnotations.openMocks(this);
+ }
+
+ @Test
+ public void testApplicationBootFinish() {
+ StartupReporter startupReporter = new StartupReporter();
+ assertDoesNotThrow(startupReporter::applicationBootFinish);
+ }
+
+ @Test
+ public void testAddCommonStartupStat() {
+ StartupReporter startupReporter = new StartupReporter();
+ BaseStat baseStat = new BaseStat();
+ assertDoesNotThrow(() -> {
+ startupReporter.addCommonStartupStat(baseStat);
+ });
+ }
+
+ @Test
+ public void testDrainStartupStaticsModel() {
+ StartupReporter startupReporter = new StartupReporter();
+ assertNotNull(startupReporter.drainStartupStaticsModel());
+ }
+
+}
\ No newline at end of file
diff --git a/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/util/ModuleUtilTests.java b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/util/ModuleUtilTests.java
new file mode 100644
index 000000000..d574a05ff
--- /dev/null
+++ b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/util/ModuleUtilTests.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alipay.sofa.boot.util;
+
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.InaccessibleObjectException;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * @author huazhongming
+ * @since 4.4.0
+ */
+public class ModuleUtilTests {
+
+ @Test
+ public void testExportAllJDKModulePackageToAll() throws NoSuchMethodException {
+
+ Exception exception = assertThrows(InaccessibleObjectException.class,() -> {
+ Method newByteChannel0Method = Files.class.getDeclaredMethod("provider", Path.class);
+ newByteChannel0Method.setAccessible(true);
+ });
+
+ assertTrue(exception.getMessage().contains("module java.base does not \"opens java.nio.file\" to unnamed module"));
+
+ ModuleUtil.exportAllJDKModulePackageToAll();
+
+ Method newByteChannel0Method = Files.class.getDeclaredMethod("provider", Path.class);
+ newByteChannel0Method.setAccessible(true);
+ }
+}
diff --git a/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/util/SofaBootEnvUtilsTests.java b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/util/SofaBootEnvUtilsTests.java
index 8e8d8aad1..29b8e84e3 100644
--- a/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/util/SofaBootEnvUtilsTests.java
+++ b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/util/SofaBootEnvUtilsTests.java
@@ -19,6 +19,8 @@
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
/**
* Tests for {@link SofaBootEnvUtils}.
@@ -49,4 +51,38 @@ public void testEnv() {
public void arkEnv() {
assertThat(SofaBootEnvUtils.isArkEnv()).isFalse();
}
+
+ @Test
+ void testIsSpringCloudBootstrapEnvironment_NullEnvironment() {
+ assertFalse(SofaBootEnvUtils.isSpringCloudBootstrapEnvironment(null));
+ }
+
+ @Test
+ public void testInitSpringTestEnv() {
+
+ boolean expectedTestEnv = true;
+
+ boolean actualTestEnv = isInitSpringTestEnv();
+
+ assertEquals(expectedTestEnv, actualTestEnv);
+ }
+
+ private boolean isInitSpringTestEnv() {
+ StackTraceElement[] stackTrace = new StackTraceElement[] {
+ new StackTraceElement("SomeClass", "someMethod", "SomeClass.java", 10),
+ new StackTraceElement("AnotherClass", "loadContext", "AnotherClass.java", 20),
+ new StackTraceElement(
+ "org.springframework.boot.test.context.SpringBootContextLoader", "loadContext",
+ "SpringBootContextLoader.java", 30) };
+ boolean TEST_ENV = false;
+ for (StackTraceElement stackTraceElement : stackTrace) {
+ if ("loadContext".equals(stackTraceElement.getMethodName())
+ && "org.springframework.boot.test.context.SpringBootContextLoader"
+ .equals(stackTraceElement.getClassName())) {
+ TEST_ENV = true;
+ break;
+ }
+ }
+ return TEST_ENV;
+ }
}
diff --git a/sofa-boot-project/sofaboot-dependencies/pom.xml b/sofa-boot-project/sofaboot-dependencies/pom.xml
index 7f335ef48..7bac50f75 100644
--- a/sofa-boot-project/sofaboot-dependencies/pom.xml
+++ b/sofa-boot-project/sofaboot-dependencies/pom.xml
@@ -10,6 +10,7 @@
${revision}
+ SOFABoot Dependencies
sofaboot-dependencies
pom
@@ -19,20 +20,20 @@
0.4
3.19.0
3.1.2
- 0.8.9
+ 0.8.13
3.0.0
6.1.8
- 4.0.0
- 5.11.0
- 2.0.1
- 1.6.6
- 3.5.1
- 2.2.3
+ 4.0.2
+ 5.13.4
+ 2.1.1
+ 1.6.10
+ 3.5.5
+ 2.2.7
1.6.1
- 2022.0.3
- 9.4
+ 2025.0.0
+ 9.8
1.2.83
3.29.2-GA
3.22.2
@@ -537,18 +538,6 @@
${commons.io.version}