Polishing

This commit is contained in:
Juergen Hoeller 2022-10-06 12:03:25 +02:00
parent aedef9321a
commit b45a48461f
12 changed files with 71 additions and 100 deletions

View File

@ -44,6 +44,7 @@ public interface BeanRegistrationAotContribution {
*/ */
default BeanRegistrationCodeFragments customizeBeanRegistrationCodeFragments( default BeanRegistrationCodeFragments customizeBeanRegistrationCodeFragments(
GenerationContext generationContext, BeanRegistrationCodeFragments codeFragments) { GenerationContext generationContext, BeanRegistrationCodeFragments codeFragments) {
return codeFragments; return codeFragments;
} }
@ -52,8 +53,7 @@ public interface BeanRegistrationAotContribution {
* @param generationContext the generation context * @param generationContext the generation context
* @param beanRegistrationCode the generated registration * @param beanRegistrationCode the generated registration
*/ */
void applyTo(GenerationContext generationContext, void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode);
BeanRegistrationCode beanRegistrationCode);
/** /**
* Create a {@link BeanRegistrationAotContribution} that customizes * Create a {@link BeanRegistrationAotContribution} that customizes
@ -66,20 +66,19 @@ public interface BeanRegistrationAotContribution {
*/ */
static BeanRegistrationAotContribution withCustomCodeFragments( static BeanRegistrationAotContribution withCustomCodeFragments(
UnaryOperator<BeanRegistrationCodeFragments> defaultCodeFragments) { UnaryOperator<BeanRegistrationCodeFragments> defaultCodeFragments) {
Assert.notNull(defaultCodeFragments, "'defaultCodeFragments' must not be null");
return new BeanRegistrationAotContribution() {
Assert.notNull(defaultCodeFragments, "'defaultCodeFragments' must not be null");
return new BeanRegistrationAotContribution() {
@Override @Override
public BeanRegistrationCodeFragments customizeBeanRegistrationCodeFragments( public BeanRegistrationCodeFragments customizeBeanRegistrationCodeFragments(
GenerationContext generationContext, BeanRegistrationCodeFragments codeFragments) { GenerationContext generationContext, BeanRegistrationCodeFragments codeFragments) {
return defaultCodeFragments.apply(codeFragments); return defaultCodeFragments.apply(codeFragments);
} }
@Override @Override
public void applyTo(GenerationContext generationContext, public void applyTo(GenerationContext generationContext,
BeanRegistrationCode beanRegistrationCode) { BeanRegistrationCode beanRegistrationCode) {
} }
}; };
} }

View File

@ -94,8 +94,7 @@ public class BeanRegistrationCodeFragmentsDecorator implements BeanRegistrationC
Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut) { Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut) {
return this.delegate.generateInstanceSupplierCode(generationContext, return this.delegate.generateInstanceSupplierCode(generationContext,
beanRegistrationCode, constructorOrFactoryMethod, beanRegistrationCode, constructorOrFactoryMethod, allowDirectSupplierShortcut);
allowDirectSupplierShortcut);
} }
@Override @Override

View File

@ -202,8 +202,7 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme
Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut) { Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut) {
return new InstanceSupplierCodeGenerator(generationContext, return new InstanceSupplierCodeGenerator(generationContext,
beanRegistrationCode.getClassName(), beanRegistrationCode.getClassName(), beanRegistrationCode.getMethods(), allowDirectSupplierShortcut)
beanRegistrationCode.getMethods(), allowDirectSupplierShortcut)
.generateCode(this.registeredBean, constructorOrFactoryMethod); .generateCode(this.registeredBean, constructorOrFactoryMethod);
} }

View File

@ -81,8 +81,7 @@ class InstanceSupplierCodeGenerator {
InstanceSupplierCodeGenerator(GenerationContext generationContext, InstanceSupplierCodeGenerator(GenerationContext generationContext,
ClassName className, GeneratedMethods generatedMethods, ClassName className, GeneratedMethods generatedMethods, boolean allowDirectSupplierShortcut) {
boolean allowDirectSupplierShortcut) {
this.generationContext = generationContext; this.generationContext = generationContext;
this.className = className; this.className = className;
@ -104,9 +103,7 @@ class InstanceSupplierCodeGenerator {
"No suitable executor found for " + registeredBean.getBeanName()); "No suitable executor found for " + registeredBean.getBeanName());
} }
private CodeBlock generateCodeForConstructor(RegisteredBean registeredBean, private CodeBlock generateCodeForConstructor(RegisteredBean registeredBean, Constructor<?> constructor) {
Constructor<?> constructor) {
String beanName = registeredBean.getBeanName(); String beanName = registeredBean.getBeanName();
Class<?> beanClass = registeredBean.getBeanClass(); Class<?> beanClass = registeredBean.getBeanClass();
Class<?> declaringClass = constructor.getDeclaringClass(); Class<?> declaringClass = constructor.getDeclaringClass();
@ -122,18 +119,16 @@ class InstanceSupplierCodeGenerator {
private CodeBlock generateCodeForAccessibleConstructor(String beanName, Class<?> beanClass, private CodeBlock generateCodeForAccessibleConstructor(String beanName, Class<?> beanClass,
Constructor<?> constructor, boolean dependsOnBean, Class<?> declaringClass) { Constructor<?> constructor, boolean dependsOnBean, Class<?> declaringClass) {
this.generationContext.getRuntimeHints().reflection() this.generationContext.getRuntimeHints().reflection().registerConstructor(
.registerConstructor(constructor, ExecutableMode.INTROSPECT); constructor, ExecutableMode.INTROSPECT);
if (!dependsOnBean && constructor.getParameterCount() == 0) { if (!dependsOnBean && constructor.getParameterCount() == 0) {
if (!this.allowDirectSupplierShortcut) { if (!this.allowDirectSupplierShortcut) {
return CodeBlock.of("$T.using($T::new)", InstanceSupplier.class, return CodeBlock.of("$T.using($T::new)", InstanceSupplier.class, declaringClass);
declaringClass);
} }
if (!isThrowingCheckedException(constructor)) { if (!isThrowingCheckedException(constructor)) {
return CodeBlock.of("$T::new", declaringClass); return CodeBlock.of("$T::new", declaringClass);
} }
return CodeBlock.of("$T.of($T::new)", ThrowingSupplier.class, return CodeBlock.of("$T.of($T::new)", ThrowingSupplier.class, declaringClass);
declaringClass);
} }
GeneratedMethod generatedMethod = generateGetInstanceSupplierMethod(method -> GeneratedMethod generatedMethod = generateGetInstanceSupplierMethod(method ->
buildGetInstanceMethodForConstructor(method, beanName, beanClass, constructor, buildGetInstanceMethodForConstructor(method, beanName, beanClass, constructor,
@ -167,12 +162,11 @@ class InstanceSupplierCodeGenerator {
CodeBlock.Builder code = CodeBlock.builder(); CodeBlock.Builder code = CodeBlock.builder();
code.add(generateResolverForConstructor(beanClass, constructor, parameterOffset)); code.add(generateResolverForConstructor(beanClass, constructor, parameterOffset));
boolean hasArguments = constructor.getParameterCount() > 0; boolean hasArguments = constructor.getParameterCount() > 0;
CodeBlock arguments = hasArguments CodeBlock arguments = hasArguments ?
? new AutowiredArgumentsCodeGenerator(declaringClass, constructor) new AutowiredArgumentsCodeGenerator(declaringClass, constructor)
.generateCode(constructor.getParameterTypes(), parameterOffset) .generateCode(constructor.getParameterTypes(), parameterOffset)
: NO_ARGS; : NO_ARGS;
CodeBlock newInstance = generateNewInstanceCodeForConstructor(dependsOnBean, CodeBlock newInstance = generateNewInstanceCodeForConstructor(dependsOnBean, declaringClass, arguments);
declaringClass, arguments);
code.add(generateWithGeneratorCode(hasArguments, newInstance)); code.add(generateWithGeneratorCode(hasArguments, newInstance));
method.addStatement(code.build()); method.addStatement(code.build());
} }
@ -180,10 +174,8 @@ class InstanceSupplierCodeGenerator {
private CodeBlock generateResolverForConstructor(Class<?> beanClass, private CodeBlock generateResolverForConstructor(Class<?> beanClass,
Constructor<?> constructor, int parameterOffset) { Constructor<?> constructor, int parameterOffset) {
CodeBlock parameterTypes = generateParameterTypesCode( CodeBlock parameterTypes = generateParameterTypesCode(constructor.getParameterTypes(), parameterOffset);
constructor.getParameterTypes(), parameterOffset); return CodeBlock.of("return $T.<$T>forConstructor($L)", BeanInstanceSupplier.class, beanClass, parameterTypes);
return CodeBlock.of("return $T.<$T>forConstructor($L)",
BeanInstanceSupplier.class, beanClass, parameterTypes);
} }
private CodeBlock generateNewInstanceCodeForConstructor(boolean dependsOnBean, private CodeBlock generateNewInstanceCodeForConstructor(boolean dependsOnBean,
@ -207,18 +199,17 @@ class InstanceSupplierCodeGenerator {
boolean dependsOnBean = !Modifier.isStatic(factoryMethod.getModifiers()); boolean dependsOnBean = !Modifier.isStatic(factoryMethod.getModifiers());
Visibility accessVisibility = getAccessVisibility(registeredBean, factoryMethod); Visibility accessVisibility = getAccessVisibility(registeredBean, factoryMethod);
if (accessVisibility != Visibility.PRIVATE) { if (accessVisibility != Visibility.PRIVATE) {
return generateCodeForAccessibleFactoryMethod(beanName, beanClass, factoryMethod, return generateCodeForAccessibleFactoryMethod(
declaringClass, dependsOnBean); beanName, beanClass, factoryMethod, declaringClass, dependsOnBean);
} }
return generateCodeForInaccessibleFactoryMethod(beanName, beanClass, factoryMethod, return generateCodeForInaccessibleFactoryMethod(beanName, beanClass, factoryMethod, declaringClass);
declaringClass);
} }
private CodeBlock generateCodeForAccessibleFactoryMethod(String beanName, private CodeBlock generateCodeForAccessibleFactoryMethod(String beanName,
Class<?> beanClass, Method factoryMethod, Class<?> declaringClass, boolean dependsOnBean) { Class<?> beanClass, Method factoryMethod, Class<?> declaringClass, boolean dependsOnBean) {
this.generationContext.getRuntimeHints().reflection() this.generationContext.getRuntimeHints().reflection().registerMethod(
.registerMethod(factoryMethod, ExecutableMode.INTROSPECT); factoryMethod, ExecutableMode.INTROSPECT);
if (!dependsOnBean && factoryMethod.getParameterCount() == 0) { if (!dependsOnBean && factoryMethod.getParameterCount() == 0) {
CodeBlock.Builder code = CodeBlock.builder(); CodeBlock.Builder code = CodeBlock.builder();
code.add("$T.<$T>forFactoryMethod($T.class, $S)", BeanInstanceSupplier.class, code.add("$T.<$T>forFactoryMethod($T.class, $S)", BeanInstanceSupplier.class,
@ -235,14 +226,13 @@ class InstanceSupplierCodeGenerator {
private CodeBlock generateCodeForInaccessibleFactoryMethod(String beanName, Class<?> beanClass, private CodeBlock generateCodeForInaccessibleFactoryMethod(String beanName, Class<?> beanClass,
Method factoryMethod, Class<?> declaringClass) { Method factoryMethod, Class<?> declaringClass) {
this.generationContext.getRuntimeHints().reflection() this.generationContext.getRuntimeHints().reflection().registerMethod(factoryMethod, ExecutableMode.INVOKE);
.registerMethod(factoryMethod, ExecutableMode.INVOKE);
GeneratedMethod getInstanceMethod = generateGetInstanceSupplierMethod(method -> { GeneratedMethod getInstanceMethod = generateGetInstanceSupplierMethod(method -> {
method.addJavadoc("Get the bean instance supplier for '$L'.", beanName); method.addJavadoc("Get the bean instance supplier for '$L'.", beanName);
method.addModifiers(PRIVATE_STATIC); method.addModifiers(PRIVATE_STATIC);
method.returns(ParameterizedTypeName.get(BeanInstanceSupplier.class, beanClass)); method.returns(ParameterizedTypeName.get(BeanInstanceSupplier.class, beanClass));
method.addStatement(generateInstanceSupplierForFactoryMethod(beanClass, factoryMethod, method.addStatement(generateInstanceSupplierForFactoryMethod(
declaringClass, factoryMethod.getName())); beanClass, factoryMethod, declaringClass, factoryMethod.getName()));
}); });
return generateReturnStatement(getInstanceMethod); return generateReturnStatement(getInstanceMethod);
} }
@ -256,14 +246,15 @@ class InstanceSupplierCodeGenerator {
method.addModifiers(modifiers); method.addModifiers(modifiers);
method.returns(ParameterizedTypeName.get(BeanInstanceSupplier.class, beanClass)); method.returns(ParameterizedTypeName.get(BeanInstanceSupplier.class, beanClass));
CodeBlock.Builder code = CodeBlock.builder(); CodeBlock.Builder code = CodeBlock.builder();
code.add(generateInstanceSupplierForFactoryMethod(beanClass, factoryMethod, declaringClass, factoryMethodName)); code.add(generateInstanceSupplierForFactoryMethod(
beanClass, factoryMethod, declaringClass, factoryMethodName));
boolean hasArguments = factoryMethod.getParameterCount() > 0; boolean hasArguments = factoryMethod.getParameterCount() > 0;
CodeBlock arguments = hasArguments CodeBlock arguments = hasArguments ?
? new AutowiredArgumentsCodeGenerator(declaringClass, factoryMethod) new AutowiredArgumentsCodeGenerator(declaringClass, factoryMethod)
.generateCode(factoryMethod.getParameterTypes()) .generateCode(factoryMethod.getParameterTypes())
: NO_ARGS; : NO_ARGS;
CodeBlock newInstance = generateNewInstanceCodeForMethod(dependsOnBean, CodeBlock newInstance = generateNewInstanceCodeForMethod(
declaringClass, factoryMethodName, arguments); dependsOnBean, declaringClass, factoryMethodName, arguments);
code.add(generateWithGeneratorCode(hasArguments, newInstance)); code.add(generateWithGeneratorCode(hasArguments, newInstance));
method.addStatement(code.build()); method.addStatement(code.build());
} }
@ -276,11 +267,9 @@ class InstanceSupplierCodeGenerator {
BeanInstanceSupplier.class, beanClass, declaringClass, BeanInstanceSupplier.class, beanClass, declaringClass,
factoryMethodName); factoryMethodName);
} }
CodeBlock parameterTypes = generateParameterTypesCode( CodeBlock parameterTypes = generateParameterTypesCode(factoryMethod.getParameterTypes(), 0);
factoryMethod.getParameterTypes(), 0);
return CodeBlock.of("return $T.<$T>forFactoryMethod($T.class, $S, $L)", return CodeBlock.of("return $T.<$T>forFactoryMethod($T.class, $S, $L)",
BeanInstanceSupplier.class, beanClass, declaringClass, BeanInstanceSupplier.class, beanClass, declaringClass, factoryMethodName, parameterTypes);
factoryMethodName, parameterTypes);
} }
private CodeBlock generateNewInstanceCodeForMethod(boolean dependsOnBean, private CodeBlock generateNewInstanceCodeForMethod(boolean dependsOnBean,
@ -310,11 +299,8 @@ class InstanceSupplierCodeGenerator {
return code.build(); return code.build();
} }
private Visibility getAccessVisibility(RegisteredBean registeredBean, private Visibility getAccessVisibility(RegisteredBean registeredBean, Member member) {
Member member) { AccessControl beanTypeAccessControl = AccessControl.forResolvableType(registeredBean.getBeanType());
AccessControl beanTypeAccessControl = AccessControl
.forResolvableType(registeredBean.getBeanType());
AccessControl memberAccessControl = AccessControl.forMember(member); AccessControl memberAccessControl = AccessControl.forMember(member);
return AccessControl.lowest(beanTypeAccessControl, memberAccessControl).getVisibility(); return AccessControl.lowest(beanTypeAccessControl, memberAccessControl).getVisibility();
} }

View File

@ -1351,7 +1351,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
* @param mbd the bean definition for the bean * @param mbd the bean definition for the bean
* @param bw the BeanWrapper with bean instance * @param bw the BeanWrapper with bean instance
*/ */
@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) { if (bw == null) {
if (mbd.hasPropertyValues()) { if (mbd.hasPropertyValues()) {

View File

@ -256,10 +256,11 @@ public class BeanDefinitionValueResolver {
*/ */
public <T> T resolveInnerBean(@Nullable String innerBeanName, BeanDefinition innerBd, public <T> T resolveInnerBean(@Nullable String innerBeanName, BeanDefinition innerBd,
BiFunction<String, RootBeanDefinition, T> resolver) { BiFunction<String, RootBeanDefinition, T> resolver) {
String nameToUse = (innerBeanName != null ? innerBeanName : "(inner bean)"
+ BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(innerBd)); String nameToUse = (innerBeanName != null ? innerBeanName : "(inner bean)" +
return resolver.apply(nameToUse, this.beanFactory.getMergedBeanDefinition( BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(innerBd));
nameToUse, innerBd, this.beanDefinition)); return resolver.apply(nameToUse,
this.beanFactory.getMergedBeanDefinition(nameToUse, innerBd, this.beanDefinition));
} }
/** /**

View File

@ -208,8 +208,7 @@ class ConfigurationClassEnhancer {
* Also exposes the application ClassLoader as thread context ClassLoader for the time of * Also exposes the application ClassLoader as thread context ClassLoader for the time of
* class generation (in order for ASM to pick it up when doing common superclass resolution). * class generation (in order for ASM to pick it up when doing common superclass resolution).
*/ */
private static class BeanFactoryAwareGeneratorStrategy extends private static class BeanFactoryAwareGeneratorStrategy extends ClassLoaderAwareGeneratorStrategy {
ClassLoaderAwareGeneratorStrategy {
public BeanFactoryAwareGeneratorStrategy(@Nullable ClassLoader classLoader) { public BeanFactoryAwareGeneratorStrategy(@Nullable ClassLoader classLoader) {
super(classLoader); super(classLoader);

View File

@ -61,8 +61,7 @@ public abstract class AotProcessor {
private final String artifactId; private final String artifactId;
/** /**
* Create a new instance. * Create a new processor instance.
*
* @param application the application entry point * @param application the application entry point
* @param sourceOutput the location of generated sources * @param sourceOutput the location of generated sources
* @param resourceOutput the location of generated resources * @param resourceOutput the location of generated resources
@ -74,6 +73,7 @@ public abstract class AotProcessor {
*/ */
protected AotProcessor(Class<?> application, Path sourceOutput, Path resourceOutput, protected AotProcessor(Class<?> application, Path sourceOutput, Path resourceOutput,
Path classOutput, String groupId, String artifactId) { Path classOutput, String groupId, String artifactId) {
this.application = application; this.application = application;
this.sourceOutput = sourceOutput; this.sourceOutput = sourceOutput;
this.resourceOutput = resourceOutput; this.resourceOutput = resourceOutput;
@ -158,6 +158,7 @@ public abstract class AotProcessor {
private void registerEntryPointHint(DefaultGenerationContext generationContext, private void registerEntryPointHint(DefaultGenerationContext generationContext,
ClassName generatedInitializerClassName) { ClassName generatedInitializerClassName) {
TypeReference generatedType = TypeReference.of(generatedInitializerClassName.canonicalName()); TypeReference generatedType = TypeReference.of(generatedInitializerClassName.canonicalName());
TypeReference applicationType = TypeReference.of(this.application); TypeReference applicationType = TypeReference.of(this.application);
ReflectionHints reflection = generationContext.getRuntimeHints().reflection(); ReflectionHints reflection = generationContext.getRuntimeHints().reflection();

View File

@ -430,6 +430,10 @@ public class ReflectUtils {
} }
// SPRING PATCH BEGIN // SPRING PATCH BEGIN
public static void setGeneratedClassHandler(BiConsumer<String, byte[]> handler) {
generatedClassHandler = handler;
}
public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception { public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception {
return defineClass(className, b, loader, null, null); return defineClass(className, b, loader, null, null);
} }
@ -440,10 +444,6 @@ public class ReflectUtils {
return defineClass(className, b, loader, protectionDomain, null); return defineClass(className, b, loader, protectionDomain, null);
} }
public static void setGeneratedClassHandler(BiConsumer<String, byte[]> handler) {
generatedClassHandler = handler;
}
@SuppressWarnings({"deprecation", "serial"}) @SuppressWarnings({"deprecation", "serial"})
public static Class defineClass(String className, byte[] b, ClassLoader loader, public static Class defineClass(String className, byte[] b, ClassLoader loader,
ProtectionDomain protectionDomain, Class<?> contextClass) throws Exception { ProtectionDomain protectionDomain, Class<?> contextClass) throws Exception {

View File

@ -97,10 +97,6 @@ public class SpringFactoriesLoader {
*/ */
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
private static final ArgumentResolver NO_ARGUMENT_RESOLVER = null;
private static final FailureHandler NO_FAILURE_HANDLER = null;
private static final FailureHandler THROWING_FAILURE_HANDLER = FailureHandler.throwing(); private static final FailureHandler THROWING_FAILURE_HANDLER = FailureHandler.throwing();
private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class); private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);
@ -143,7 +139,7 @@ public class SpringFactoriesLoader {
* @since 6.0 * @since 6.0
*/ */
public <T> List<T> load(Class<T> factoryType) { public <T> List<T> load(Class<T> factoryType) {
return load(factoryType, NO_ARGUMENT_RESOLVER, NO_FAILURE_HANDLER); return load(factoryType, null, null);
} }
/** /**
@ -161,7 +157,7 @@ public class SpringFactoriesLoader {
* @since 6.0 * @since 6.0
*/ */
public <T> List<T> load(Class<T> factoryType, @Nullable ArgumentResolver argumentResolver) { public <T> List<T> load(Class<T> factoryType, @Nullable ArgumentResolver argumentResolver) {
return load(factoryType, argumentResolver, NO_FAILURE_HANDLER); return load(factoryType, argumentResolver, null);
} }
/** /**
@ -179,7 +175,7 @@ public class SpringFactoriesLoader {
* @since 6.0 * @since 6.0
*/ */
public <T> List<T> load(Class<T> factoryType, @Nullable FailureHandler failureHandler) { public <T> List<T> load(Class<T> factoryType, @Nullable FailureHandler failureHandler) {
return load(factoryType, NO_ARGUMENT_RESOLVER, failureHandler); return load(factoryType, null, failureHandler);
} }
/** /**
@ -198,7 +194,9 @@ public class SpringFactoriesLoader {
* @param failureHandler strategy used to handle factory instantiation failures * @param failureHandler strategy used to handle factory instantiation failures
* @since 6.0 * @since 6.0
*/ */
public <T> List<T> load(Class<T> factoryType, @Nullable ArgumentResolver argumentResolver, @Nullable FailureHandler failureHandler) { public <T> List<T> load(Class<T> factoryType, @Nullable ArgumentResolver argumentResolver,
@Nullable FailureHandler failureHandler) {
Assert.notNull(factoryType, "'factoryType' must not be null"); Assert.notNull(factoryType, "'factoryType' must not be null");
List<String> implementationNames = loadFactoryNames(factoryType); List<String> implementationNames = loadFactoryNames(factoryType);
logger.trace(LogMessage.format("Loaded [%s] names: %s", factoryType.getName(), implementationNames)); logger.trace(LogMessage.format("Loaded [%s] names: %s", factoryType.getName(), implementationNames));
@ -224,8 +222,8 @@ public class SpringFactoriesLoader {
try { try {
Class<?> factoryImplementationClass = ClassUtils.forName(implementationName, this.classLoader); Class<?> factoryImplementationClass = ClassUtils.forName(implementationName, this.classLoader);
Assert.isTrue(type.isAssignableFrom(factoryImplementationClass), Assert.isTrue(type.isAssignableFrom(factoryImplementationClass), () ->
() -> "Class [%s] is not assignable to factory type [%s]".formatted(implementationName, type.getName())); "Class [%s] is not assignable to factory type [%s]".formatted(implementationName, type.getName()));
FactoryInstantiator<T> factoryInstantiator = FactoryInstantiator.forClass(factoryImplementationClass); FactoryInstantiator<T> factoryInstantiator = FactoryInstantiator.forClass(factoryImplementationClass);
return factoryInstantiator.instantiate(argumentResolver); return factoryInstantiator.instantiate(argumentResolver);
} }
@ -303,8 +301,8 @@ public class SpringFactoriesLoader {
/** /**
* Create a {@link SpringFactoriesLoader} instance that will load and * Create a {@link SpringFactoriesLoader} instance that will load and
* instantiate the factory implementations from the given location, using * instantiate the factory implementations from the given location,
* the default class loader. * using the default class loader.
* @param resourceLocation the resource location to look for factories * @param resourceLocation the resource location to look for factories
* @return a {@link SpringFactoriesLoader} instance * @return a {@link SpringFactoriesLoader} instance
* @since 6.0 * @since 6.0
@ -316,11 +314,11 @@ public class SpringFactoriesLoader {
/** /**
* Create a {@link SpringFactoriesLoader} instance that will load and * Create a {@link SpringFactoriesLoader} instance that will load and
* instantiate the factory implementations from the given location, using * instantiate the factory implementations from the given location,
* the given class loader. * using the given class loader.
* @param resourceLocation the resource location to look for factories * @param resourceLocation the resource location to look for factories
* @param classLoader the ClassLoader to use for loading resources; can be * @param classLoader the ClassLoader to use for loading resources;
* {@code null} to use the default * can be {@code null} to use the default
* @return a {@link SpringFactoriesLoader} instance * @return a {@link SpringFactoriesLoader} instance
* @since 6.0 * @since 6.0
* @see #forResourceLocation(String) * @see #forResourceLocation(String)
@ -329,7 +327,7 @@ public class SpringFactoriesLoader {
Assert.hasText(resourceLocation, "'resourceLocation' must not be empty"); Assert.hasText(resourceLocation, "'resourceLocation' must not be empty");
ClassLoader resourceClassLoader = (classLoader != null ? classLoader : ClassLoader resourceClassLoader = (classLoader != null ? classLoader :
SpringFactoriesLoader.class.getClassLoader()); SpringFactoriesLoader.class.getClassLoader());
Map<String, SpringFactoriesLoader> loaders = SpringFactoriesLoader.cache.computeIfAbsent( Map<String, SpringFactoriesLoader> loaders = cache.computeIfAbsent(
resourceClassLoader, key -> new ConcurrentReferenceHashMap<>()); resourceClassLoader, key -> new ConcurrentReferenceHashMap<>());
return loaders.computeIfAbsent(resourceLocation, key -> return loaders.computeIfAbsent(resourceLocation, key ->
new SpringFactoriesLoader(classLoader, loadFactoriesResource(resourceClassLoader, resourceLocation))); new SpringFactoriesLoader(classLoader, loadFactoriesResource(resourceClassLoader, resourceLocation)));
@ -345,7 +343,7 @@ public class SpringFactoriesLoader {
properties.forEach((name, value) -> { properties.forEach((name, value) -> {
List<String> implementations = result.computeIfAbsent(((String) name).trim(), key -> new ArrayList<>()); List<String> implementations = result.computeIfAbsent(((String) name).trim(), key -> new ArrayList<>());
Arrays.stream(StringUtils.commaDelimitedListToStringArray((String) value)) Arrays.stream(StringUtils.commaDelimitedListToStringArray((String) value))
.map(String::trim).forEach(implementations::add); .map(String::trim).forEach(implementations::add);
}); });
} }
result.replaceAll(SpringFactoriesLoader::toDistinctUnmodifiableList); result.replaceAll(SpringFactoriesLoader::toDistinctUnmodifiableList);
@ -370,13 +368,11 @@ public class SpringFactoriesLoader {
private final Constructor<T> constructor; private final Constructor<T> constructor;
private FactoryInstantiator(Constructor<T> constructor) { private FactoryInstantiator(Constructor<T> constructor) {
ReflectionUtils.makeAccessible(constructor); ReflectionUtils.makeAccessible(constructor);
this.constructor = constructor; this.constructor = constructor;
} }
T instantiate(@Nullable ArgumentResolver argumentResolver) throws Exception { T instantiate(@Nullable ArgumentResolver argumentResolver) throws Exception {
Object[] args = resolveArgs(argumentResolver); Object[] args = resolveArgs(argumentResolver);
if (isKotlinType(this.constructor.getDeclaringClass())) { if (isKotlinType(this.constructor.getDeclaringClass())) {
@ -437,7 +433,6 @@ public class SpringFactoriesLoader {
return null; return null;
} }
} }
} }
@ -497,7 +492,6 @@ public class SpringFactoriesLoader {
private static <T> T instantiate(KFunction<T> kotlinConstructor, Map<KParameter, Object> args) { private static <T> T instantiate(KFunction<T> kotlinConstructor, Map<KParameter, Object> args) {
return kotlinConstructor.callBy(args); return kotlinConstructor.callBy(args);
} }
} }
@ -609,7 +603,6 @@ public class SpringFactoriesLoader {
}; };
} }
} }
@ -681,7 +674,6 @@ public class SpringFactoriesLoader {
messageHandler.accept(messageSupplier, failure); messageHandler.accept(messageSupplier, failure);
}; };
} }
} }
} }

View File

@ -47,9 +47,9 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
class PathMatchingResourcePatternResolverTests { class PathMatchingResourcePatternResolverTests {
private static final String[] CLASSES_IN_CORE_IO_SUPPORT = { "EncodedResource.class", private static final String[] CLASSES_IN_CORE_IO_SUPPORT = { "EncodedResource.class",
"LocalizedResourceHelper.class", "PathMatchingResourcePatternResolver.class", "PropertiesLoaderSupport.class", "LocalizedResourceHelper.class", "PathMatchingResourcePatternResolver.class", "PropertiesLoaderSupport.class",
"PropertiesLoaderUtils.class", "ResourceArrayPropertyEditor.class", "ResourcePatternResolver.class", "PropertiesLoaderUtils.class", "ResourceArrayPropertyEditor.class", "ResourcePatternResolver.class",
"ResourcePatternUtils.class", "SpringFactoriesLoader.class" }; "ResourcePatternUtils.class", "SpringFactoriesLoader.class" };
private static final String[] TEST_CLASSES_IN_CORE_IO_SUPPORT = { "PathMatchingResourcePatternResolverTests.class" }; private static final String[] TEST_CLASSES_IN_CORE_IO_SUPPORT = { "PathMatchingResourcePatternResolverTests.class" };
@ -99,7 +99,7 @@ class PathMatchingResourcePatternResolverTests {
} }
@Test @Test
void usingFilePrototol() { void usingFileProtocol() {
Path testResourcesDir = Path.of("src/test/resources").toAbsolutePath(); Path testResourcesDir = Path.of("src/test/resources").toAbsolutePath();
String pattern = "file:%s/scanned-resources/**".formatted(testResourcesDir); String pattern = "file:%s/scanned-resources/**".formatted(testResourcesDir);
String pathPrefix = ".+scanned-resources/"; String pathPrefix = ".+scanned-resources/";
@ -107,9 +107,7 @@ class PathMatchingResourcePatternResolverTests {
assertExactFilenames(pattern, "resource#test1.txt", "resource#test2.txt"); assertExactFilenames(pattern, "resource#test1.txt", "resource#test2.txt");
assertExactSubPaths(pattern, pathPrefix, "resource#test1.txt", "resource#test2.txt"); assertExactSubPaths(pattern, pathPrefix, "resource#test1.txt", "resource#test2.txt");
} }
} }
} }
@ -147,7 +145,6 @@ class PathMatchingResourcePatternResolverTests {
.as("Could not find aspectj_1_5_0.dtd in the root of the aspectjweaver jar") .as("Could not find aspectj_1_5_0.dtd in the root of the aspectjweaver jar")
.containsExactly("aspectj_1_5_0.dtd"); .containsExactly("aspectj_1_5_0.dtd");
} }
} }

View File

@ -67,7 +67,6 @@ public class TestAotProcessor {
/** /**
* Create a new processor for the specified test classpath roots and * Create a new processor for the specified test classpath roots and
* general settings. * general settings.
*
* @param classpathRoots the classpath roots to scan for test classes * @param classpathRoots the classpath roots to scan for test classes
* @param sourceOutput the location of generated sources * @param sourceOutput the location of generated sources
* @param resourceOutput the location of generated resources * @param resourceOutput the location of generated resources