Merge branch '6.0.x'
This commit is contained in:
commit
c504ac5a47
|
|
@ -90,8 +90,7 @@ class BeanDefinitionMethodGenerator {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the method that returns the {@link BeanDefinition} to be
|
* Generate the method that returns the {@link BeanDefinition} to be registered.
|
||||||
* registered.
|
|
||||||
* @param generationContext the generation context
|
* @param generationContext the generation context
|
||||||
* @param beanRegistrationsCode the bean registrations code
|
* @param beanRegistrationsCode the bean registrations code
|
||||||
* @return a reference to the generated method.
|
* @return a reference to the generated method.
|
||||||
|
|
@ -100,8 +99,7 @@ class BeanDefinitionMethodGenerator {
|
||||||
BeanRegistrationsCode beanRegistrationsCode) {
|
BeanRegistrationsCode beanRegistrationsCode) {
|
||||||
|
|
||||||
registerRuntimeHintsIfNecessary(generationContext.getRuntimeHints());
|
registerRuntimeHintsIfNecessary(generationContext.getRuntimeHints());
|
||||||
BeanRegistrationCodeFragments codeFragments = getCodeFragments(generationContext,
|
BeanRegistrationCodeFragments codeFragments = getCodeFragments(generationContext, beanRegistrationsCode);
|
||||||
beanRegistrationsCode);
|
|
||||||
ClassName target = codeFragments.getTarget(this.registeredBean, this.constructorOrFactoryMethod);
|
ClassName target = codeFragments.getTarget(this.registeredBean, this.constructorOrFactoryMethod);
|
||||||
if (isWritablePackageName(target)) {
|
if (isWritablePackageName(target)) {
|
||||||
GeneratedClass generatedClass = lookupGeneratedClass(generationContext, target);
|
GeneratedClass generatedClass = lookupGeneratedClass(generationContext, target);
|
||||||
|
|
@ -187,7 +185,7 @@ class BeanDefinitionMethodGenerator {
|
||||||
|
|
||||||
return generatedMethods.add("getBeanDefinition", method -> {
|
return generatedMethods.add("getBeanDefinition", method -> {
|
||||||
method.addJavadoc("Get the $L definition for '$L'.",
|
method.addJavadoc("Get the $L definition for '$L'.",
|
||||||
(!this.registeredBean.isInnerBean()) ? "bean" : "inner-bean",
|
(this.registeredBean.isInnerBean() ? "inner-bean" : "bean"),
|
||||||
getName());
|
getName());
|
||||||
method.addModifiers(modifier, Modifier.STATIC);
|
method.addModifiers(modifier, Modifier.STATIC);
|
||||||
method.returns(BeanDefinition.class);
|
method.returns(BeanDefinition.class);
|
||||||
|
|
@ -214,9 +212,9 @@ class BeanDefinitionMethodGenerator {
|
||||||
|
|
||||||
private String getSimpleBeanName(String beanName) {
|
private String getSimpleBeanName(String beanName) {
|
||||||
int lastDot = beanName.lastIndexOf('.');
|
int lastDot = beanName.lastIndexOf('.');
|
||||||
beanName = (lastDot != -1) ? beanName.substring(lastDot + 1) : beanName;
|
beanName = (lastDot != -1 ? beanName.substring(lastDot + 1) : beanName);
|
||||||
int lastDollar = beanName.lastIndexOf('$');
|
int lastDollar = beanName.lastIndexOf('$');
|
||||||
beanName = (lastDollar != -1) ? beanName.substring(lastDollar + 1) : beanName;
|
beanName = (lastDollar != -1 ? beanName.substring(lastDollar + 1) : beanName);
|
||||||
return StringUtils.uncapitalize(beanName);
|
return StringUtils.uncapitalize(beanName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -975,19 +975,19 @@ class ConstructorResolver {
|
||||||
Assert.state(isCompatible, () -> String.format(
|
Assert.state(isCompatible, () -> String.format(
|
||||||
"Incompatible target type '%s' for factory bean '%s'",
|
"Incompatible target type '%s' for factory bean '%s'",
|
||||||
resolvableType.toClass().getName(), factoryBeanClass.getName()));
|
resolvableType.toClass().getName(), factoryBeanClass.getName()));
|
||||||
Executable executable = resolveConstructor(beanName, mbd,
|
Constructor<?> constructor = resolveConstructor(beanName, mbd,
|
||||||
() -> ResolvableType.forClass(factoryBeanClass), valueTypes);
|
() -> ResolvableType.forClass(factoryBeanClass), valueTypes);
|
||||||
if (executable != null) {
|
if (constructor != null) {
|
||||||
return executable;
|
return constructor;
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("No suitable FactoryBean constructor found for " +
|
throw new IllegalStateException("No suitable FactoryBean constructor found for " +
|
||||||
mbd + " and argument types " + valueTypes);
|
mbd + " and argument types " + valueTypes);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Executable resolvedConstructor = resolveConstructor(beanName, mbd, beanType, valueTypes);
|
Constructor<?> constructor = resolveConstructor(beanName, mbd, beanType, valueTypes);
|
||||||
if (resolvedConstructor != null) {
|
if (constructor != null) {
|
||||||
return resolvedConstructor;
|
return constructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalStateException("No constructor or factory method candidate found for " +
|
throw new IllegalStateException("No constructor or factory method candidate found for " +
|
||||||
|
|
@ -1030,7 +1030,7 @@ class ConstructorResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Executable resolveConstructor(String beanName, RootBeanDefinition mbd,
|
private Constructor<?> resolveConstructor(String beanName, RootBeanDefinition mbd,
|
||||||
Supplier<ResolvableType> beanType, List<ResolvableType> valueTypes) {
|
Supplier<ResolvableType> beanType, List<ResolvableType> valueTypes) {
|
||||||
|
|
||||||
Class<?> type = ClassUtils.getUserClass(beanType.get().toClass());
|
Class<?> type = ClassUtils.getUserClass(beanType.get().toClass());
|
||||||
|
|
@ -1054,14 +1054,14 @@ class ConstructorResolver {
|
||||||
}
|
}
|
||||||
return types;
|
return types;
|
||||||
};
|
};
|
||||||
List<? extends Executable> matches = Arrays.stream(ctors)
|
List<Constructor<?>> matches = Arrays.stream(ctors)
|
||||||
.filter(executable -> match(parameterTypesFactory.apply(executable),
|
.filter(executable -> match(parameterTypesFactory.apply(executable),
|
||||||
valueTypes, FallbackMode.NONE))
|
valueTypes, FallbackMode.NONE))
|
||||||
.toList();
|
.toList();
|
||||||
if (matches.size() == 1) {
|
if (matches.size() == 1) {
|
||||||
return matches.get(0);
|
return matches.get(0);
|
||||||
}
|
}
|
||||||
List<? extends Executable> assignableElementFallbackMatches = Arrays
|
List<Constructor<?>> assignableElementFallbackMatches = Arrays
|
||||||
.stream(ctors)
|
.stream(ctors)
|
||||||
.filter(executable -> match(parameterTypesFactory.apply(executable),
|
.filter(executable -> match(parameterTypesFactory.apply(executable),
|
||||||
valueTypes, FallbackMode.ASSIGNABLE_ELEMENT))
|
valueTypes, FallbackMode.ASSIGNABLE_ELEMENT))
|
||||||
|
|
@ -1069,7 +1069,7 @@ class ConstructorResolver {
|
||||||
if (assignableElementFallbackMatches.size() == 1) {
|
if (assignableElementFallbackMatches.size() == 1) {
|
||||||
return assignableElementFallbackMatches.get(0);
|
return assignableElementFallbackMatches.get(0);
|
||||||
}
|
}
|
||||||
List<? extends Executable> typeConversionFallbackMatches = Arrays
|
List<Constructor<?>> typeConversionFallbackMatches = Arrays
|
||||||
.stream(ctors)
|
.stream(ctors)
|
||||||
.filter(executable -> match(parameterTypesFactory.apply(executable),
|
.filter(executable -> match(parameterTypesFactory.apply(executable),
|
||||||
valueTypes, FallbackMode.TYPE_CONVERSION))
|
valueTypes, FallbackMode.TYPE_CONVERSION))
|
||||||
|
|
@ -1121,7 +1121,7 @@ class ConstructorResolver {
|
||||||
}
|
}
|
||||||
return types;
|
return types;
|
||||||
};
|
};
|
||||||
result = (Method) resolveFactoryMethod(candidates, parameterTypesFactory, valueTypes);
|
result = resolveFactoryMethod(candidates, parameterTypesFactory, valueTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
|
|
@ -1138,24 +1138,24 @@ class ConstructorResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Executable resolveFactoryMethod(List<Method> executables,
|
private Method resolveFactoryMethod(List<Method> executables,
|
||||||
Function<Method, List<ResolvableType>> parameterTypesFactory,
|
Function<Method, List<ResolvableType>> parameterTypesFactory,
|
||||||
List<ResolvableType> valueTypes) {
|
List<ResolvableType> valueTypes) {
|
||||||
|
|
||||||
List<? extends Executable> matches = executables.stream()
|
List<Method> matches = executables.stream()
|
||||||
.filter(executable -> match(parameterTypesFactory.apply(executable), valueTypes, FallbackMode.NONE))
|
.filter(executable -> match(parameterTypesFactory.apply(executable), valueTypes, FallbackMode.NONE))
|
||||||
.toList();
|
.toList();
|
||||||
if (matches.size() == 1) {
|
if (matches.size() == 1) {
|
||||||
return matches.get(0);
|
return matches.get(0);
|
||||||
}
|
}
|
||||||
List<? extends Executable> assignableElementFallbackMatches = executables.stream()
|
List<Method> assignableElementFallbackMatches = executables.stream()
|
||||||
.filter(executable -> match(parameterTypesFactory.apply(executable),
|
.filter(executable -> match(parameterTypesFactory.apply(executable),
|
||||||
valueTypes, FallbackMode.ASSIGNABLE_ELEMENT))
|
valueTypes, FallbackMode.ASSIGNABLE_ELEMENT))
|
||||||
.toList();
|
.toList();
|
||||||
if (assignableElementFallbackMatches.size() == 1) {
|
if (assignableElementFallbackMatches.size() == 1) {
|
||||||
return assignableElementFallbackMatches.get(0);
|
return assignableElementFallbackMatches.get(0);
|
||||||
}
|
}
|
||||||
List<? extends Executable> typeConversionFallbackMatches = executables.stream()
|
List<Method> typeConversionFallbackMatches = executables.stream()
|
||||||
.filter(executable -> match(parameterTypesFactory.apply(executable),
|
.filter(executable -> match(parameterTypesFactory.apply(executable),
|
||||||
valueTypes, FallbackMode.TYPE_CONVERSION))
|
valueTypes, FallbackMode.TYPE_CONVERSION))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
|
||||||
|
|
@ -517,7 +517,6 @@ class AnnotationDrivenEventListenerTests {
|
||||||
ReplyEventListener replyEventListener = this.context.getBean(ReplyEventListener.class);
|
ReplyEventListener replyEventListener = this.context.getBean(ReplyEventListener.class);
|
||||||
TestEventListener listener = this.context.getBean(TestEventListener.class);
|
TestEventListener listener = this.context.getBean(TestEventListener.class);
|
||||||
|
|
||||||
|
|
||||||
this.eventCollector.assertNoEventReceived(listener);
|
this.eventCollector.assertNoEventReceived(listener);
|
||||||
this.eventCollector.assertNoEventReceived(replyEventListener);
|
this.eventCollector.assertNoEventReceived(replyEventListener);
|
||||||
this.context.publishEvent(event);
|
this.context.publishEvent(event);
|
||||||
|
|
@ -634,6 +633,17 @@ class AnnotationDrivenEventListenerTests {
|
||||||
assertThat(listener.order).contains("first", "second", "third");
|
assertThat(listener.order).contains("first", "second", "third");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void publicSubclassWithInheritedEventListener() {
|
||||||
|
load(PublicSubclassWithInheritedEventListener.class);
|
||||||
|
TestEventListener listener = this.context.getBean(PublicSubclassWithInheritedEventListener.class);
|
||||||
|
|
||||||
|
this.eventCollector.assertNoEventReceived(listener);
|
||||||
|
this.context.publishEvent("test");
|
||||||
|
this.eventCollector.assertEvent(listener, "test");
|
||||||
|
this.eventCollector.assertTotalEventsCount(1);
|
||||||
|
}
|
||||||
|
|
||||||
@Test @Disabled // SPR-15122
|
@Test @Disabled // SPR-15122
|
||||||
void listenersReceiveEarlyEvents() {
|
void listenersReceiveEarlyEvents() {
|
||||||
load(EventOnPostConstruct.class, OrderedTestListener.class);
|
load(EventOnPostConstruct.class, OrderedTestListener.class);
|
||||||
|
|
@ -646,7 +656,7 @@ class AnnotationDrivenEventListenerTests {
|
||||||
void missingListenerBeanIgnored() {
|
void missingListenerBeanIgnored() {
|
||||||
load(MissingEventListener.class);
|
load(MissingEventListener.class);
|
||||||
context.getBean(UseMissingEventListener.class);
|
context.getBean(UseMissingEventListener.class);
|
||||||
context.getBean(ApplicationEventMulticaster.class).multicastEvent(new TestEvent(this));
|
context.publishEvent(new TestEvent(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -753,7 +763,6 @@ class AnnotationDrivenEventListenerTests {
|
||||||
public void handleContextEvent(ApplicationContextEvent event) {
|
public void handleContextEvent(ApplicationContextEvent event) {
|
||||||
collectEvent(event);
|
collectEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -979,7 +988,6 @@ class AnnotationDrivenEventListenerTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@EventListener
|
@EventListener
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface ConditionalEvent {
|
public @interface ConditionalEvent {
|
||||||
|
|
@ -1031,7 +1039,7 @@ class AnnotationDrivenEventListenerTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
@Component
|
||||||
static class OrderedTestListener extends TestEventListener {
|
static class OrderedTestListener extends TestEventListener {
|
||||||
|
|
||||||
public final List<String> order = new ArrayList<>();
|
public final List<String> order = new ArrayList<>();
|
||||||
|
|
@ -1055,6 +1063,11 @@ class AnnotationDrivenEventListenerTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public static class PublicSubclassWithInheritedEventListener extends TestEventListener {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static class EventOnPostConstruct {
|
static class EventOnPostConstruct {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -74,7 +74,8 @@ public final class MethodIntrospector {
|
||||||
T result = metadataLookup.inspect(specificMethod);
|
T result = metadataLookup.inspect(specificMethod);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
|
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
|
||||||
if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) {
|
if (bridgedMethod == specificMethod || bridgedMethod == method ||
|
||||||
|
metadataLookup.inspect(bridgedMethod) == null) {
|
||||||
methodMap.put(specificMethod, result);
|
methodMap.put(specificMethod, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue