This annotation and the related processor allows to
register reflection hints for data binding purpose
(class, fields, properties, record components for
the whole type hierarchy)
Closes gh-28979
This commit provides an alternative
java.beans.Introspector#findCustomizerClass implementation
via a GraalVM substitution that avoids to include thousands
of unused AWT classes in the native image.
Closes gh-29060
Since Spring no longer adds the SynthesizedAnnotation interface to the
JDK dynamic proxy used to synthesize an annotation, this commit
officially deprecates SynthesizedAnnotation and related methods in
RuntimeHintsUtils.
See gh-29041, gh-29054
Closes gh-29053
SynthesizedAnnotation was originally introduced as a convenience for
easily detecting if an annotation had been synthesized by Spring via a
simple `if (myAnnotation instanceof SynthesizedAnnotation)` check.
However, the introduction of SynthesizedAnnotation in the JDK dynamic
proxy for a synthesized annotation results in a separate proxy class
for each annotation synthesized by Spring, and this causes issues with
GraalVM native images since users and framework developers must always
ensure that the additional proxy classes are registered.
This commit completely removes the use of SynthesizedAnnotation in
synthesized annotation proxies. This change allows the proxy class for
an annotation to be reused for a synthesized annotation of the same
annotation type.
Consequently:
- Extra proxy classes are not generated on the JVM or in a native image.
- Extra proxy classes are not required to be registered for a native image.
Closes gh-29041
Add `MemberCategory` and `FieldMode` shortcuts for type registration.
Helper `builtWith` methods have also been extracted to the Hint types
to allow general reuse (for example with `registerTypes`).
See gh-29011
Add a `FieldMode` enum analogous to `ExecutableHint` and update
`FieldHint` to ensure that registration cannot downgrade `WRITE`
to `READ`.
Fixes gh-29055
Reduce the visibility of hint factory methods that return a `Builder`.
Since the `build()` method of the `Builder` is package-private the
factory methods can also be package-private.
Since SynthesizedAnnotation will be deprecated (and potentially
completely removed) in Spring Framework 6.0, this commit introduces
AnnotationUtils.isSynthesizedAnnotation(Annotation) in 5.3.x to allow
people to migrate away from relying on SynthesizedAnnotation.
Closes gh-29054
Prior to this commit, the `ConcurrentLruCache` implementation would not
perform well under certain conditions. As long as the cache capacity was
not reached, the cache would avoid maintaining an eviction queue
(reordering entries depending with least/most recently read). When the
cache capacity was reached, the LRU queue was updated for each
read/write operation. This decreased performance significantly under
contention when the capacity was reached.
This commit completely rewrites the internals of `ConcurrentLruCache`.
`ConcurrentLruCache` is now a specialized version of the
`ConcurrentLinkedHashMap` [1]. This change focuses on buferring read and
write operations, only processing them at certain times to avoid
contention.
When a cached entry is read, a read operation is queued and buffered
operations are drained if the buffer reached a fixed limit. When a new
cache entry is added or removed, a write operation is queued and
triggers a drain attempt. When the capacity is outgrown, the cache polls
items from the eviction queue, which maintains elements with the
least recently used ones first. Entries are removed until the capacity
is under control.
The behavior described here and the buffer sizes are optimized with the
number of available processors in mind. Work is localized as much as
possible on a per-thread basis to avoid contention on the eviction queue.
The new implementation has been tested with the JMH benchmark provided
here, comparing the former `COncurrentLruCache`, the new implementation
as well as the `ConcurrentLinkedHashMap` [1].
When testing with a cache reaching capacity, under contention, with a
10% cache miss, we're seeing a 40x improvement compared to the previous
implementation and performance on par with the reference.
See [2] for how to replicate the benchmark.
[1] https://github.com/ben-manes/concurrentlinkedhashmap
[2] https://github.com/spring-projects/spring-framework/wiki/Micro-Benchmarks
Closes gh-26320
This commit introduces support for Netty 5's Buffer, in the form of
Netty5DataBuffer. Because of the new API offered by Buffer, several
changes have been made to the DataBuffer API:
- CloseableDataBuffer is a simpler alternative to PooledDataBuffer, and
implemented by Netty5DataBuffer. DataBufferUtils::release can now
handle CloseableDataBuffer as well as PooledDataBuffer.
- PooledDataBuffer::touch has been moved into a separate interface:
TouchableDataBuffer, which is implemented by Netty5DataBuffer.
- The capacity of DataBuffers can no longer be reduced, they can only
grow larger. As a consequence, DataBuffer::capacity(int) has been
deprecated, but ensureWritable (formally ensureCapacity) still exists.
- DataBuffer::slice and retainedSlice have been deprecated in favor of
split, a new method that ensures that memory regions do not overlap.
- DataBuffer::asByteBuffer has been deprecated in favor of toByteBuffer,
a new method that returns a copy, instead of shared data.
- DataBufferFactory::allocateBuffer has been deprecated in favor of
allocateBuffer(int).
Closes gh-28874
This commit adapts the registration of fields, constructors, and methods
to provide the same convenience than the reflection-based one available
in ReflectionHints.
See gh-29011
This commit harmonizes the registration of an executable so that
the default method and the method that takes an empty customizer
produces the same hint. The same applies to the readable flag of
a field hint.
Rather than returning a list of executable modes, the "highest" mode
is retained.
See gh-29011
Prior to this commit, if infrastructure code working directly with an
instance of DefaultGenerationContext invoked withName() on that
instance, the new GenerationContext had to be cast from
GenerationContext to DefaultGenerationContext in order for the
infrastructure to continue working with the DefaultGenerationContext
API -- for example, the writeGeneratedContent() method which is not
defined in the GenerationContext API.
This commit makes use of a covariant return type by declaring that
DefaultGenerationContext.withName() returns a DefaultGenerationContext.
Prior to this commit, it was possible to create a DefaultGenerationContext
based on a ClassNameGenerator and GeneratedFiles; however, there was no way
to create a DefaultGenerationContext that reused an existing RuntimeHints
instance which is necessary in certain use cases -- for example, in the
TestContext framework where multiple GenerationContexts are created
based on shared instances of GeneratedFiles and RuntimeHints.
This commit addresses this by introducing a public
DefaultGenerationContext(ClassNameGenerator,GeneratedFiles,RuntimeHints)
constructor.
Based on the feedback in #28977 an easy way to create a list of
type references based on a vararg of classes is helpful when
registering the same hints for several types.
This commit updates RuntimeHintsUtils to focus on registering a JDK
proxy only as annotations of annotated elements that have at least
an introspection hints are visible out-of-the-box.
This commit also removes unnecessary hints and adapt `@Reflective` to
detect if a hint is required using the introduced
MergedAnnotation#isSynthesizable.
See gh-28967
This commit adds the ability to check if a the annotation managed by
a MergedAnnotation is synthesizable. This makes it easier to register
a JDK proxy hint if necessary
See gh-28967
The DefaultGenerationContext constructor which accepts an instance of
GeneratedClasses is now package private since GeneratedClasses can only
be created within the `org.springframework.aot.generate` package.
This commit updates ApplicationContextAotGenerator to register a
handler that process Cglib generated classes. The handler registers
such classes to the GeneratedFiles and provide a hint so that it
can be instantiated using reflection.
Closes gh-28954