Prior to this commit, MethodIntrospector failed to properly detect
bridge methods for subsequent invocations of selectMethods() with the
same targetType and MetadataLookup, if such subsequent invocations
occurred after the ApplicationContext had been refreshed.
The reason this occurs is due to the following.
- Class#getDeclaredMethods() always returns "child copies" of the
underlying Method instances -- which means that `equals()` should be
used instead of `==` whenever the compared Method instances can come
from different sources (such as the static caches mentioned below).
- BridgeMethodResolver caches resolved bridge methods in a static cache
-- which is never cleared.
- ReflectionUtils caches declared methods in a static cache
-- which gets cleared when an ApplicationContext is refreshed.
Consequently, if you attempt to load an ApplicationContext twice in the
same ClassLoader, the second attempt uses the existing, populated cache
for bridged methods but a cleared, empty cache for declared methods.
This results in new invocations of Class#getDeclaredMethods(), and
identity checks with `==` then fail to detect equivalent bridge methods.
This commit addresses this by additionally comparing bridge methods
using `equals()` in MethodIntrospector.selectMethods().
Note that the `==` checks remain in place as an optimization for when
`equals()` is unnecessary.
Closes gh-32586
KClass instantiation in CoroutinesUtils is suboptimal, and should be
replaced by KTypes#isSubtypeOf checks using pre-instantiated types for
Flow, Mono and Publisher.
This commit impact on performances is significant since a throughput
increase between 2x and 3x has been measured on basic endpoints.
Closes gh-32390
This commit fixes a performance regression caused by gh-31698,
and more specifically by KClass#isValue invocations which are slow since
they load the whole module to find the class to get the descriptor.
After discussing with the Kotlin team, it has been decided that only
checking for the presence of `@JvmInline` annotation is enough for
Spring use case.
As a consequence, this commit introduces a new
KotlinDetector#isInlineClass method that performs such check, and
BeanUtils, CoroutinesUtils and WebMVC/WebFlux InvocableHandlerMethod
have been refined to leverage it.
Closes gh-32334
This commit introduces composite collections (i.e. Collection, Set, Map)
and uses these composites in request predicates, where before new
collections were instantiated.
Closes gh-32245
This commit removes the previous implementation in favor of the new
PlaceholderParser. The only noticeable side effect is that the exception
is no longer an IllegalArgumentException, but rather the dedicated
PlaceholderResolutionException.
See gh-9628
This commit provides a rewrite of the parser for properties containing
potentially placeholders.
Assuming a source where `firstName` = `John` and `lastName` = `Smith`,
the "${firstName}-${lastName}" property is evaluated as "John-Smith".
Compared with the existing implementation in PropertyPlaceholderHelper,
the new implementation offers the following extra features:
1. Placeholder can be escaped using a configurable escape character.
When a placeholder is escaped it is rendered as is. This does apply to
any nested placeholder that wouldn't be escaped. For instance,
"\${firstName}" is evaluated as "${firstName}".
2. The default separator can also be escaped the same way. When the
separator is escaped, the left and right parts are not considered as
the key and the default value respectively. Rather the two parts
combined, including the separator (but not the escape separator) are
used for resolution. For instance, ${java\:comp/env/test} is looking
for a "java:comp/env/test" property.
3. Placeholders are resolved lazily. Previously, all nested placeholders
were resolved before considering if a separator was present. This
implementation only attempts the resolution of the default value if the
key does not provide a value.
4. Failure to resolve a placeholder are more rich, with a dedicated
PlaceholderResolutionException that contains the resolution chain.
See gh-9628
See gh-26268
Prior to this commit, the `SimpleCommandLineArgsParser` would reject
"--" arguments as invalid. As reported by the community, the POSIX
utility conventions (Guideline 10) state that
> The first -- argument that is not an option-argument should be
> accepted as a delimiter indicating the end of options.
> Any following arguments should be treated as operands, even if they
> begin with the '-' character.
This commit updates `SimpleCommandLineArgsParser` to not reject "--"
arguments and instead to consider remaining arguments as non-optional.
See gh-31513
This notably enables Jackson to reflectively call a user-provided
builder class and invoke its declared methods (setters and build) in
a native app.
Closes gh-32238
To improve consistency and avoid confusion regarding primitive types
and their wrapper types, this commit ensures that we always use class
literals for primitive types.
For example, instead of using the `Void.TYPE` constant, we now
consistently use `void.class`.
Prior to this commit, the alias resolution error message in
SimpleAliasRegistry was misleading.
When a resolution conflict is detected, the IllegalStateException
thrown by resolveAliases(...) now states that the resolved alias is
already registered for an `existingName` instead of the `registeredName`.
See gh-31353
Closes gh-32025
This commit improves SimpleAliasRegistryTests in the following ways.
- Some existing methods have been split up into smaller test methods
which focus on a single use case.
- The use of Mockito mocks has been replaced by a hand-crafted
StubStringValueResolver which ensures that existing aliases and names
are not accidentally replaced by null thereby removing their removing
there mappings inadvertently.
- Several test methods now include inline comments that document the
current state of the aliasMap in order to clarify what is happening
behind the scenes in the ConcurrentHashMap.
- Several test methods warn that the current expectations are based on
ConcurrentHashMap iteration order!
- New @ParameterizedTest which is currently @Disabled but
demonstrates that complex use cases involving placeholder replacement
can be supported consistently -- regardless of the values of the
aliases involved -- but only if alias registration order is honored.
Closes gh-31353