mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
207 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b19f98bfd2 | |||
| 50fad9ed05 | |||
| 2b4ffe0391 | |||
| e7eaaaded1 | |||
| f6e52900a2 | |||
| 62b5e42769 | |||
| 1631be5660 | |||
| 9ccc72a9fb | |||
| 01b2856114 | |||
| 6dca7b28cc | |||
| 864b1c95cd | |||
| 168c60c18a | |||
| 1e49334209 | |||
| 79cc0ec4aa | |||
| fdfa4284de | |||
| 49d3ec58fc | |||
| c4405104a8 | |||
| 4b0443090a | |||
| b1bf1b0c82 | |||
| 5d45b94e93 | |||
| 598c972a78 | |||
| 2593b60f2b | |||
| e6f638132c | |||
| b823c46aae | |||
| 4d11307b84 | |||
| 03b6e51225 | |||
| 785598629a | |||
| 3452354a11 | |||
| bb1cdb6b48 | |||
| 37fa82c578 | |||
| 1f2d29ee08 | |||
| cffc8835c6 | |||
| 515c654a46 | |||
| aacb7e1604 | |||
| c86642dfee | |||
| f4a9b12340 | |||
| bd66763f26 | |||
| 2d3b02a89d | |||
| 8552e149b5 | |||
| e0d6b69195 | |||
| a3532bfccc | |||
| 6697f01d05 | |||
| 01c62f86b3 | |||
| 9912a52bb8 | |||
| 419e34e571 | |||
| f0e16bd31b | |||
| 43107e7eb1 | |||
| 81bd6be1c0 | |||
| d6c84c43ec | |||
| 70247c4a94 | |||
| 87b35e7d8e | |||
| a51c22b266 | |||
| 318d460256 | |||
| d7cfdc633a | |||
| 085af10afd | |||
| a8273a3009 | |||
| 580d9f81e2 | |||
| 79b0d71514 | |||
| f6b36a689a | |||
| 4b6126c057 | |||
| a108e701bc | |||
| 0ad561d379 | |||
| 1372265bd9 | |||
| 476ef0c3ca | |||
| 534d3229fe | |||
| 07097976ef | |||
| fb4fbeab50 | |||
| b169dc50ad | |||
| 02e32baa80 | |||
| 549f6c1e80 | |||
| 16b4c25f7d | |||
| af2e13e211 | |||
| 7c9307e970 | |||
| 4f599b7396 | |||
| 2784f6008e | |||
| be9ee9112c | |||
| 19a87e968e | |||
| 207b9a14f4 | |||
| 05ebca8677 | |||
| f846d9484c | |||
| 50069ef029 | |||
| 777ff3f1a8 | |||
| 89466cb33c | |||
| bf3a478990 | |||
| efb97cca82 | |||
| b692c0ed03 | |||
| 6eed2b0aee | |||
| 7876db03c6 | |||
| ffddbb586e | |||
| a3c11fc033 | |||
| 321de9ab9b | |||
| ec5f566ba5 | |||
| 2d6b77336b | |||
| 9a1ee48d73 | |||
| e22d1efdc0 | |||
| ff8097d37c | |||
| 7d44a4dcad | |||
| fdb454b9a4 | |||
| b4174377c2 | |||
| 174eae377f | |||
| 243ec88e95 | |||
| 9f3fd103ef | |||
| 0ad3800f54 | |||
| 473efb6d4f | |||
| 153f8895cb | |||
| f5b4f7d9e8 | |||
| 989625d2d4 | |||
| 28e5468162 | |||
| b1c0b65666 | |||
| 490aaa1ed8 | |||
| c7d2d6716d | |||
| eefe65d95a | |||
| 3c5d46166e | |||
| cfa3aa001f | |||
| ea5ef098cf | |||
| adcf236a3d | |||
| 72a9864788 | |||
| a6e87b40c7 | |||
| 094479b55f | |||
| db2c532c07 | |||
| 4a450c6fab | |||
| ed1bfb8177 | |||
| a35384fd57 | |||
| 9d31537ae5 | |||
| dee1b726f9 | |||
| 7cfff4049d | |||
| 45080e3724 | |||
| c3b5f5bf90 | |||
| 7e5afc8bbb | |||
| 7474af4f09 | |||
| 28a7b6103a | |||
| 3cddb0434d | |||
| 36a72115f9 | |||
| 3c0b5459be | |||
| 088be2d017 | |||
| a155a6b3e2 | |||
| a338a16b29 | |||
| 7613bdfdf9 | |||
| 57f27fa42f | |||
| 55d9d151fb | |||
| 70f31dee45 | |||
| 699f93fed7 | |||
| 4c6ca05af5 | |||
| 75c7596259 | |||
| 17d362fa85 | |||
| a428955438 | |||
| 4afac17e58 | |||
| 8bd8c4f627 | |||
| 0390709577 | |||
| 9f2970bc5c | |||
| 232225b2aa | |||
| 5caf714ff4 | |||
| cd11219fa7 | |||
| 44c652ec98 | |||
| cd8bc2f82a | |||
| 12f6330fae | |||
| fc0ea465e1 | |||
| 459338f6fd | |||
| f0add920f5 | |||
| 33c149077a | |||
| e00a882333 | |||
| 3ed5a90b7c | |||
| 3476402a75 | |||
| b04803de99 | |||
| f443cf965a | |||
| c9292f8e09 | |||
| bd65a19d71 | |||
| 85cb6cc5fb | |||
| 5f8a031c22 | |||
| dc564f3ef2 | |||
| d7ce13c763 | |||
| 7b9037b054 | |||
| 3162afbf16 | |||
| 1bd523f6b6 | |||
| 4c0d0ba5b3 | |||
| 212346a86d | |||
| 564803f56a | |||
| df708d16e4 | |||
| 848dedb576 | |||
| 4516e0d413 | |||
| a23375c49d | |||
| 53b937976d | |||
| 12f01f9b5f | |||
| 917978cbc2 | |||
| 3f5c3b1747 | |||
| bec7210b4b | |||
| 0a94dce41d | |||
| 9b3afcdac7 | |||
| 8eb524dc4d | |||
| dee8108bbc | |||
| 045c5dc1b4 | |||
| 24f8eac12a | |||
| eaf7a28250 | |||
| 7965c1969f | |||
| d0574197ea | |||
| 63b2787da6 | |||
| 1ff683b259 | |||
| 22bf4df290 | |||
| b56fc50c27 | |||
| d2aa6a98f2 | |||
| bf0819390f | |||
| 503ccb577c | |||
| 2f7e650122 | |||
| 68931a2091 | |||
| 7f79ccbec0 | |||
| 43c2e51d6e | |||
| 66b8f369dc |
@@ -1,3 +1,3 @@
|
||||
# Enable auto-env through the sdkman_auto_env config
|
||||
# Add key=value pairs of SDKs to use below
|
||||
java=17.0.8.1-librca
|
||||
java=17.0.9-librca
|
||||
|
||||
@@ -31,7 +31,7 @@ Information regarding CI builds can be found in the [Spring Framework Concourse
|
||||
|
||||
## Stay in Touch
|
||||
|
||||
Follow [@SpringCentral](https://twitter.com/springcentral), [@SpringFramework](https://twitter.com/springframework), and its [team members](https://twitter.com/springframework/lists/team/members) on Twitter. In-depth articles can be found at [The Spring Blog](https://spring.io/blog/), and releases are announced via our [releases feed](https://spring.io/blog/category/releases).
|
||||
Follow [@SpringCentral](https://twitter.com/springcentral), [@SpringFramework](https://twitter.com/springframework), and its [team members](https://twitter.com/springframework/lists/team/members) on 𝕏. In-depth articles can be found at [The Spring Blog](https://spring.io/blog/), and releases are announced via our [releases feed](https://spring.io/blog/category/releases).
|
||||
|
||||
## License
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ plugins {
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version "${kotlinVersion}" apply false
|
||||
id 'org.jetbrains.dokka' version '1.8.20'
|
||||
id 'org.unbroken-dome.xjc' version '2.0.0' apply false
|
||||
id 'com.github.ben-manes.versions' version '0.49.0'
|
||||
id 'com.github.ben-manes.versions' version '0.50.0'
|
||||
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
|
||||
id 'de.undercouch.download' version '5.4.0'
|
||||
id 'me.champeau.jmh' version '0.7.2' apply false
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
org.gradle.caching=true
|
||||
javaFormatVersion=0.0.39
|
||||
javaFormatVersion=0.0.41
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,12 +50,12 @@ public class CheckstyleConventions {
|
||||
project.getPlugins().apply(CheckstylePlugin.class);
|
||||
project.getTasks().withType(Checkstyle.class).forEach(checkstyle -> checkstyle.getMaxHeapSize().set("1g"));
|
||||
CheckstyleExtension checkstyle = project.getExtensions().getByType(CheckstyleExtension.class);
|
||||
checkstyle.setToolVersion("10.12.5");
|
||||
checkstyle.setToolVersion("10.12.7");
|
||||
checkstyle.getConfigDirectory().set(project.getRootProject().file("src/checkstyle"));
|
||||
String version = SpringJavaFormatPlugin.class.getPackage().getImplementationVersion();
|
||||
DependencySet checkstyleDependencies = project.getConfigurations().getByName("checkstyle").getDependencies();
|
||||
checkstyleDependencies
|
||||
.add(project.getDependencies().create("io.spring.javaformat:spring-javaformat-checkstyle:" + version));
|
||||
checkstyleDependencies.add(
|
||||
project.getDependencies().create("io.spring.javaformat:spring-javaformat-checkstyle:" + version));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:jammy-20231128
|
||||
FROM ubuntu:jammy-20231211.1
|
||||
|
||||
ADD setup.sh /setup.sh
|
||||
ADD get-jdk-url.sh /get-jdk-url.sh
|
||||
|
||||
@@ -9,7 +9,7 @@ case "$1" in
|
||||
echo "https://download.bell-sw.com/java/21.0.1+12/bellsoft-jdk21.0.1+12-linux-amd64.tar.gz"
|
||||
;;
|
||||
java22)
|
||||
echo "https://download.java.net/java/early_access/jdk22/27/GPL/openjdk-22-ea+27_linux-x64_bin.tar.gz"
|
||||
echo "https://download.java.net/java/early_access/jdk22/28/GPL/openjdk-22-ea+28_linux-x64_bin.tar.gz"
|
||||
;;
|
||||
*)
|
||||
echo $"Unknown java version"
|
||||
|
||||
@@ -255,6 +255,8 @@ jobs:
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
- get: every-morning
|
||||
trigger: true
|
||||
- put: repo-status-jdk22-build
|
||||
params: { state: "pending", commit: "git-repo" }
|
||||
- do:
|
||||
|
||||
@@ -4,6 +4,6 @@ set -e
|
||||
source $(dirname $0)/common.sh
|
||||
|
||||
pushd git-repo > /dev/null
|
||||
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK21 \
|
||||
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK21,JDK22 \
|
||||
-PmainToolchain=${MAIN_TOOLCHAIN} -PtestToolchain=${TEST_TOOLCHAIN} --no-daemon --max-workers=4 check antora
|
||||
popd > /dev/null
|
||||
|
||||
@@ -28,7 +28,7 @@ javadoc {
|
||||
header = rootProject.description
|
||||
use = true
|
||||
overview = project.relativePath("$rootProject.rootDir/framework-docs/src/docs/api/overview.html")
|
||||
destinationDir = file("${project.buildDir}/docs/javadoc-api")
|
||||
destinationDir = file("$project.docsDir/javadoc-api")
|
||||
splitIndex = true
|
||||
links(rootProject.ext.javadocLinks)
|
||||
addBooleanOption('Xdoclint:syntax,reference', true) // only check syntax and reference with doclint
|
||||
@@ -52,7 +52,7 @@ rootProject.tasks.dokkaHtmlMultiModule.configure {
|
||||
tasks.named("javadoc")
|
||||
}
|
||||
moduleName.set("spring-framework")
|
||||
outputDirectory.set(project.file("$buildDir/docs/kdoc-api"))
|
||||
outputDirectory.set(file("$docsDir/kdoc-api"))
|
||||
includes.from("$rootProject.rootDir/framework-docs/src/docs/api/dokka-overview.md")
|
||||
}
|
||||
|
||||
|
||||
@@ -19,15 +19,53 @@ of the classpath -- for example, deployed within the application's JAR file.
|
||||
The following table lists all currently supported Spring properties.
|
||||
|
||||
.Supported Spring Properties
|
||||
[cols="1,1", stripes=odd]
|
||||
|===
|
||||
| Name | Description
|
||||
|
||||
| `spring.aot.enabled`
|
||||
| Indicates the application should run with AOT generated artifacts. See
|
||||
xref:core/aot.adoc[Ahead of Time Optimizations] and
|
||||
{spring-framework-api}++/aot/AotDetector.html#AOT_ENABLED++[`AotDetector`]
|
||||
for details.
|
||||
|
||||
| `spring.beaninfo.ignore`
|
||||
| Instructs Spring to use the `Introspector.IGNORE_ALL_BEANINFO` mode when calling the
|
||||
JavaBeans `Introspector`. See
|
||||
{spring-framework-api}++/beans/StandardBeanInfoFactory.html#IGNORE_BEANINFO_PROPERTY_NAME++[`CachedIntrospectionResults`]
|
||||
for details.
|
||||
|
||||
| `spring.cache.reactivestreams.ignore`
|
||||
| Instructs Spring's caching infrastructure to ignore the presence of Reactive Streams,
|
||||
in particular Reactor's `Mono`/`Flux` in `@Cacheable` method return type declarations. See
|
||||
{spring-framework-api}++/cache/interceptor/CacheAspectSupport.html#IGNORE_REACTIVESTREAMS_PROPERTY_NAME++[`CacheAspectSupport`]
|
||||
for details.
|
||||
|
||||
| `spring.classformat.ignore`
|
||||
| Instructs Spring to ignore class format exceptions during classpath scanning, in
|
||||
particular for unsupported class file versions. See
|
||||
{spring-framework-api}++/context/annotation/ClassPathScanningCandidateComponentProvider.html#IGNORE_CLASSFORMAT_PROPERTY_NAME++[`ClassPathScanningCandidateComponentProvider`]
|
||||
for details.
|
||||
|
||||
| `spring.context.checkpoint`
|
||||
| Property that specifies a common context checkpoint. See
|
||||
xref:integration/checkpoint-restore.adoc#_automatic_checkpointrestore_at_startup[Automatic
|
||||
checkpoint/restore at startup] and
|
||||
{spring-framework-api}++/context/support/DefaultLifecycleProcessor.html#CHECKPOINT_PROPERTY_NAME++[`DefaultLifecycleProcessor`]
|
||||
for details.
|
||||
|
||||
| `spring.context.exit`
|
||||
| Property for terminating the JVM when the context reaches a specific phase. See
|
||||
xref:integration/checkpoint-restore.adoc#_automatic_checkpointrestore_at_startup[Automatic
|
||||
checkpoint/restore at startup] and
|
||||
{spring-framework-api}++/context/support/DefaultLifecycleProcessor.html#EXIT_PROPERTY_NAME++[`DefaultLifecycleProcessor`]
|
||||
for details.
|
||||
|
||||
| `spring.context.expression.maxLength`
|
||||
| The maximum length for
|
||||
xref:core/expressions/evaluation.adoc#expressions-parser-configuration[Spring Expression Language]
|
||||
expressions used in XML bean definitions, `@Value`, etc.
|
||||
|
||||
| `spring.expression.compiler.mode`
|
||||
| The mode to use when compiling expressions for the
|
||||
xref:core/expressions/evaluation.adoc#expressions-compiler-configuration[Spring Expression Language].
|
||||
|
||||
@@ -291,6 +291,8 @@ to consider:
|
||||
* `final` classes cannot be proxied, because they cannot be extended.
|
||||
* `final` methods cannot be advised, because they cannot be overridden.
|
||||
* `private` methods cannot be advised, because they cannot be overridden.
|
||||
* Methods that are not visible, typically package private methods in a parent class
|
||||
from a different package, cannot be advised because they are effectively private.
|
||||
|
||||
NOTE: There is no need to add CGLIB to your classpath. CGLIB is repackaged and included
|
||||
in the `spring-core` JAR. In other words, CGLIB-based AOP works "out of the box", as do
|
||||
|
||||
@@ -168,7 +168,7 @@ Kotlin::
|
||||
======
|
||||
|
||||
NOTE: Pooling stateless service objects is not usually necessary. We do not believe it should
|
||||
be the default choice, as most stateless objects are naturally thread safe, and instance
|
||||
be the default choice, as most stateless objects are naturally thread-safe, and instance
|
||||
pooling is problematic if resources are cached.
|
||||
|
||||
Simpler pooling is available by using auto-proxying. You can set the `TargetSource` implementations
|
||||
|
||||
@@ -533,6 +533,11 @@ standard AspectJ. The following example shows the `aop.xml` file:
|
||||
</aspectj>
|
||||
----
|
||||
|
||||
NOTE: It is recommended to only weave specific classes (typically those in the
|
||||
application packages, as shown in the `aop.xml` example above) in order
|
||||
to avoid side effects such as AspectJ dump files and warnings.
|
||||
This is also a best practice from an efficiency perspective.
|
||||
|
||||
Now we can move on to the Spring-specific portion of the configuration. We need
|
||||
to configure a `LoadTimeWeaver` (explained later). This load-time weaver is the
|
||||
essential component responsible for weaving the aspect configuration in one or
|
||||
@@ -714,10 +719,29 @@ Furthermore, the compiled aspect classes need to be available on the classpath.
|
||||
|
||||
|
||||
[[aop-aj-ltw-aop_dot_xml]]
|
||||
=== 'META-INF/aop.xml'
|
||||
=== `META-INF/aop.xml`
|
||||
|
||||
The AspectJ LTW infrastructure is configured by using one or more `META-INF/aop.xml`
|
||||
files that are on the Java classpath (either directly or, more typically, in jar files).
|
||||
For example:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
----
|
||||
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd">
|
||||
<aspectj>
|
||||
|
||||
<weaver>
|
||||
<!-- only weave classes in our application-specific packages -->
|
||||
<include within="com.xyz.*"/>
|
||||
</weaver>
|
||||
|
||||
</aspectj>
|
||||
----
|
||||
|
||||
NOTE: It is recommended to only weave specific classes (typically those in the
|
||||
application packages, as shown in the `aop.xml` example above) in order
|
||||
to avoid side effects such as AspectJ dump files and warnings.
|
||||
This is also a best practice from an efficiency perspective.
|
||||
|
||||
The structure and contents of this file is detailed in the LTW part of the
|
||||
{aspectj-docs-devguide}/ltw-configuration.html[AspectJ reference
|
||||
|
||||
+2
@@ -155,6 +155,8 @@ If there is no other resolution indicator (such as a qualifier or a primary mark
|
||||
for a non-unique dependency situation, Spring matches the injection point name
|
||||
(that is, the field name or parameter name) against the target bean names and chooses the
|
||||
same-named candidate, if any.
|
||||
|
||||
Since version 6.1, this requires the `-parameters` Java compiler flag to be present.
|
||||
====
|
||||
|
||||
That said, if you intend to express annotation-driven injection by name, do not
|
||||
|
||||
@@ -592,6 +592,40 @@ Kotlin::
|
||||
|
||||
|
||||
|
||||
[[beans-factory-thread-safety]]
|
||||
=== Thread Safety and Visibility
|
||||
|
||||
The Spring core container publishes created singleton instances in a thread-safe manner,
|
||||
guarding access through a singleton lock and guaranteeing visibility in other threads.
|
||||
|
||||
As a consequence, application-provided bean classes do not have to be concerned about the
|
||||
visibility of their initialization state. Regular configuration fields do not have to be
|
||||
marked as `volatile` as long as they are only mutated during the initialization phase,
|
||||
providing visibility guarantees similar to `final` even for setter-based configuration
|
||||
state that is mutable during that initial phase. If such fields get changed after the
|
||||
bean creation phase and its subsequent initial publication, they need to be declared as
|
||||
`volatile` or guarded by a common lock whenever accessed.
|
||||
|
||||
Note that concurrent access to such configuration state in singleton bean instances,
|
||||
e.g. for controller instances or repository instances, is perfectly thread-safe after
|
||||
such safe initial publication from the container side. This includes common singleton
|
||||
`FactoryBean` instances which are processed within the general singleton lock as well.
|
||||
|
||||
For destruction callbacks, the configuration state remains thread-safe but any runtime
|
||||
state accumulated between initialization and destruction should be kept in thread-safe
|
||||
structures (or in `volatile` fields for simple cases) as per common Java guidelines.
|
||||
|
||||
Deeper `Lifecycle` integration as shown above involves runtime-mutable state such as
|
||||
a `runnable` field which will have to be declared as `volatile`. While the common
|
||||
lifecycle callbacks follow a certain order, e.g. a start callback is guaranteed to
|
||||
only happen after full initialization and a stop callback only after an initial start,
|
||||
there is a special case with the common stop before destroy arrangement: It is strongly
|
||||
recommended that the internal state in any such bean also allows for an immediate
|
||||
destroy callback without a preceding stop since this may happen during an extraordinary
|
||||
shutdown after a cancelled bootstrap or in case of a stop timeout caused by another bean.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-aware]]
|
||||
== `ApplicationContextAware` and `BeanNameAware`
|
||||
|
||||
|
||||
@@ -324,7 +324,6 @@ Kotlin::
|
||||
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-application]]
|
||||
=== Application Scope
|
||||
|
||||
@@ -374,7 +373,6 @@ Kotlin::
|
||||
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-websocket]]
|
||||
=== WebSocket Scope
|
||||
|
||||
@@ -384,7 +382,6 @@ xref:web/websocket/stomp/scope.adoc[WebSocket scope] for more details.
|
||||
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-other-injection]]
|
||||
=== Scoped Beans as Dependencies
|
||||
|
||||
@@ -544,6 +541,19 @@ see xref:core/aop/proxying.adoc[Proxying Mechanisms].
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-injection]]
|
||||
=== Injecting Request/Session References Directly
|
||||
|
||||
As an alternative to factory scopes, a Spring `WebApplicationContext` also supports
|
||||
the injection of `HttpServletRequest`, `HttpServletResponse`, `HttpSession`,
|
||||
`WebRequest` and (if JSF is present) `FacesContext` and `ExternalContext` into
|
||||
Spring-managed beans, simply through type-based autowiring next to regular injection
|
||||
points for other beans. Spring generally injects proxies for such request and session
|
||||
objects which has the advantage of working in singleton beans and serializable beans
|
||||
as well, similar to scoped proxies for factory-scoped beans.
|
||||
|
||||
|
||||
|
||||
[[beans-factory-scopes-custom]]
|
||||
== Custom Scopes
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
[[expressions-evaluation]]
|
||||
= Evaluation
|
||||
|
||||
This section introduces the simple use of SpEL interfaces and its expression language.
|
||||
The complete language reference can be found in
|
||||
This section introduces programmatic use of SpEL's interfaces and its expression language.
|
||||
The complete language reference can be found in the
|
||||
xref:core/expressions/language-ref.adoc[Language Reference].
|
||||
|
||||
The following code introduces the SpEL API to evaluate the literal string expression,
|
||||
`Hello World`.
|
||||
The following code demonstrates how to use the SpEL API to evaluate the literal string
|
||||
expression, `Hello World`.
|
||||
|
||||
[tabs]
|
||||
======
|
||||
@@ -18,7 +18,7 @@ Java::
|
||||
Expression exp = parser.parseExpression("'Hello World'"); // <1>
|
||||
String message = (String) exp.getValue();
|
||||
----
|
||||
<1> The value of the message variable is `'Hello World'`.
|
||||
<1> The value of the message variable is `"Hello World"`.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
@@ -28,24 +28,24 @@ Kotlin::
|
||||
val exp = parser.parseExpression("'Hello World'") // <1>
|
||||
val message = exp.value as String
|
||||
----
|
||||
<1> The value of the message variable is `'Hello World'`.
|
||||
<1> The value of the message variable is `"Hello World"`.
|
||||
======
|
||||
|
||||
|
||||
The SpEL classes and interfaces you are most likely to use are located in the
|
||||
`org.springframework.expression` package and its sub-packages, such as `spel.support`.
|
||||
|
||||
The `ExpressionParser` interface is responsible for parsing an expression string. In
|
||||
the preceding example, the expression string is a string literal denoted by the surrounding single
|
||||
quotation marks. The `Expression` interface is responsible for evaluating the previously defined
|
||||
expression string. Two exceptions that can be thrown, `ParseException` and
|
||||
`EvaluationException`, when calling `parser.parseExpression` and `exp.getValue`,
|
||||
respectively.
|
||||
The `ExpressionParser` interface is responsible for parsing an expression string. In the
|
||||
preceding example, the expression string is a string literal denoted by the surrounding
|
||||
single quotation marks. The `Expression` interface is responsible for evaluating the
|
||||
defined expression string. The two types of exceptions that can be thrown when calling
|
||||
`parser.parseExpression(...)` and `exp.getValue(...)` are `ParseException` and
|
||||
`EvaluationException`, respectively.
|
||||
|
||||
SpEL supports a wide range of features, such as calling methods, accessing properties,
|
||||
SpEL supports a wide range of features such as calling methods, accessing properties,
|
||||
and calling constructors.
|
||||
|
||||
In the following example of method invocation, we call the `concat` method on the string literal:
|
||||
In the following method invocation example, we call the `concat` method on the string
|
||||
literal, `Hello World`.
|
||||
|
||||
[tabs]
|
||||
======
|
||||
@@ -57,7 +57,7 @@ Java::
|
||||
Expression exp = parser.parseExpression("'Hello World'.concat('!')"); // <1>
|
||||
String message = (String) exp.getValue();
|
||||
----
|
||||
<1> The value of `message` is now 'Hello World!'.
|
||||
<1> The value of `message` is now `"Hello World!"`.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
@@ -67,10 +67,11 @@ Kotlin::
|
||||
val exp = parser.parseExpression("'Hello World'.concat('!')") // <1>
|
||||
val message = exp.value as String
|
||||
----
|
||||
<1> The value of `message` is now 'Hello World!'.
|
||||
<1> The value of `message` is now `"Hello World!"`.
|
||||
======
|
||||
|
||||
The following example of calling a JavaBean property calls the `String` property `Bytes`:
|
||||
The following example demonstrates how to access the `Bytes` JavaBean property of the
|
||||
string literal, `Hello World`.
|
||||
|
||||
[tabs]
|
||||
======
|
||||
@@ -100,10 +101,10 @@ Kotlin::
|
||||
======
|
||||
|
||||
SpEL also supports nested properties by using the standard dot notation (such as
|
||||
`prop1.prop2.prop3`) and also the corresponding setting of property values.
|
||||
`prop1.prop2.prop3`) as well as the corresponding setting of property values.
|
||||
Public fields may also be accessed.
|
||||
|
||||
The following example shows how to use dot notation to get the length of a literal:
|
||||
The following example shows how to use dot notation to get the length of a string literal.
|
||||
|
||||
[tabs]
|
||||
======
|
||||
@@ -133,7 +134,7 @@ Kotlin::
|
||||
======
|
||||
|
||||
The String's constructor can be called instead of using a string literal, as the following
|
||||
example shows:
|
||||
example shows.
|
||||
|
||||
[tabs]
|
||||
======
|
||||
@@ -145,7 +146,7 @@ Java::
|
||||
Expression exp = parser.parseExpression("new String('hello world').toUpperCase()"); // <1>
|
||||
String message = exp.getValue(String.class);
|
||||
----
|
||||
<1> Construct a new `String` from the literal and make it be upper case.
|
||||
<1> Construct a new `String` from the literal and convert it to upper case.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
@@ -155,10 +156,9 @@ Kotlin::
|
||||
val exp = parser.parseExpression("new String('hello world').toUpperCase()") // <1>
|
||||
val message = exp.getValue(String::class.java)
|
||||
----
|
||||
<1> Construct a new `String` from the literal and make it be upper case.
|
||||
<1> Construct a new `String` from the literal and convert it to upper case.
|
||||
======
|
||||
|
||||
|
||||
Note the use of the generic method: `public <T> T getValue(Class<T> desiredResultType)`.
|
||||
Using this method removes the need to cast the value of the expression to the desired
|
||||
result type. An `EvaluationException` is thrown if the value cannot be cast to the
|
||||
@@ -166,8 +166,8 @@ type `T` or converted by using the registered type converter.
|
||||
|
||||
The more common usage of SpEL is to provide an expression string that is evaluated
|
||||
against a specific object instance (called the root object). The following example shows
|
||||
how to retrieve the `name` property from an instance of the `Inventor` class or
|
||||
create a boolean condition:
|
||||
how to retrieve the `name` property from an instance of the `Inventor` class and how to
|
||||
reference the `name` property in a boolean expression.
|
||||
|
||||
[tabs]
|
||||
======
|
||||
@@ -240,7 +240,7 @@ It excludes Java type references, constructors, and bean references. It also req
|
||||
you to explicitly choose the level of support for properties and methods in expressions.
|
||||
By default, the `create()` static factory method enables only read access to properties.
|
||||
You can also obtain a builder to configure the exact level of support needed, targeting
|
||||
one or some combination of the following:
|
||||
one or some combination of the following.
|
||||
|
||||
* Custom `PropertyAccessor` only (no reflection)
|
||||
* Data binding properties for read-only access
|
||||
@@ -252,16 +252,15 @@ one or some combination of the following:
|
||||
|
||||
By default, SpEL uses the conversion service available in Spring core
|
||||
(`org.springframework.core.convert.ConversionService`). This conversion service comes
|
||||
with many built-in converters for common conversions but is also fully extensible so that
|
||||
you can add custom conversions between types. Additionally, it is
|
||||
generics-aware. This means that, when you work with generic types in
|
||||
expressions, SpEL attempts conversions to maintain type correctness for any objects
|
||||
it encounters.
|
||||
with many built-in converters for common conversions, but is also fully extensible so
|
||||
that you can add custom conversions between types. Additionally, it is generics-aware.
|
||||
This means that, when you work with generic types in expressions, SpEL attempts
|
||||
conversions to maintain type correctness for any objects it encounters.
|
||||
|
||||
What does this mean in practice? Suppose assignment, using `setValue()`, is being used
|
||||
to set a `List` property. The type of the property is actually `List<Boolean>`. SpEL
|
||||
recognizes that the elements of the list need to be converted to `Boolean` before
|
||||
being placed in it. The following example shows how to do so:
|
||||
being placed in it. The following example shows how to do so.
|
||||
|
||||
[tabs]
|
||||
======
|
||||
@@ -325,7 +324,7 @@ constructor before setting the specified value. If the element type does not hav
|
||||
default constructor, `null` will be added to the array or list. If there is no built-in
|
||||
or custom converter that knows how to set the value, `null` will remain in the array or
|
||||
list at the specified index. The following example demonstrates how to automatically grow
|
||||
the list:
|
||||
the list.
|
||||
|
||||
[tabs]
|
||||
======
|
||||
@@ -380,16 +379,25 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
By default, a SpEL expression cannot contain more than 10,000 characters; however, the
|
||||
`maxExpressionLength` is configurable. If you create a `SpelExpressionParser`
|
||||
programmatically, you can specify a custom `maxExpressionLength` when creating the
|
||||
`SpelParserConfiguration` that you provide to the `SpelExpressionParser`. If you wish to
|
||||
set the `maxExpressionLength` used for parsing SpEL expressions within an
|
||||
`ApplicationContext` -- for example, in XML bean definitions, `@Value`, etc. -- you can
|
||||
set a JVM system property or Spring property named `spring.context.expression.maxLength`
|
||||
to the maximum expression length needed by your application (see
|
||||
xref:appendix.adoc#appendix-spring-properties[Supported Spring Properties]).
|
||||
|
||||
|
||||
[[expressions-spel-compilation]]
|
||||
== SpEL Compilation
|
||||
|
||||
Spring Framework 4.1 includes a basic expression compiler. Expressions are usually
|
||||
interpreted, which provides a lot of dynamic flexibility during evaluation but
|
||||
does not provide optimum performance. For occasional expression usage,
|
||||
this is fine, but, when used by other components such as Spring Integration,
|
||||
performance can be very important, and there is no real need for the dynamism.
|
||||
Spring provides a basic compiler for SpEL expressions. Expressions are usually
|
||||
interpreted, which provides a lot of dynamic flexibility during evaluation but does not
|
||||
provide optimum performance. For occasional expression usage, this is fine, but, when
|
||||
used by other components such as Spring Integration, performance can be very important,
|
||||
and there is no real need for the dynamism.
|
||||
|
||||
The SpEL compiler is intended to address this need. During evaluation, the compiler
|
||||
generates a Java class that embodies the expression behavior at runtime and uses that
|
||||
@@ -402,16 +410,17 @@ information can cause trouble later if the types of the various expression eleme
|
||||
change over time. For this reason, compilation is best suited to expressions whose
|
||||
type information is not going to change on repeated evaluations.
|
||||
|
||||
Consider the following basic expression:
|
||||
Consider the following basic expression.
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
someArray[0].someProperty.someOtherProperty < 0.1
|
||||
someArray[0].someProperty.someOtherProperty < 0.1
|
||||
----
|
||||
|
||||
Because the preceding expression involves array access, some property de-referencing,
|
||||
and numeric operations, the performance gain can be very noticeable. In an example
|
||||
micro benchmark run of 50000 iterations, it took 75ms to evaluate by using the
|
||||
interpreter and only 3ms using the compiled version of the expression.
|
||||
Because the preceding expression involves array access, some property de-referencing, and
|
||||
numeric operations, the performance gain can be very noticeable. In an example micro
|
||||
benchmark run of 50,000 iterations, it took 75ms to evaluate by using the interpreter and
|
||||
only 3ms using the compiled version of the expression.
|
||||
|
||||
|
||||
[[expressions-compiler-configuration]]
|
||||
@@ -419,33 +428,34 @@ interpreter and only 3ms using the compiled version of the expression.
|
||||
|
||||
The compiler is not turned on by default, but you can turn it on in either of two
|
||||
different ways. You can turn it on by using the parser configuration process
|
||||
(xref:core/expressions/evaluation.adoc#expressions-parser-configuration[discussed earlier]) or by using a Spring property
|
||||
when SpEL usage is embedded inside another component. This section discusses both of
|
||||
these options.
|
||||
(xref:core/expressions/evaluation.adoc#expressions-parser-configuration[discussed
|
||||
earlier]) or by using a Spring property when SpEL usage is embedded inside another
|
||||
component. This section discusses both of these options.
|
||||
|
||||
The compiler can operate in one of three modes, which are captured in the
|
||||
`org.springframework.expression.spel.SpelCompilerMode` enum. The modes are as follows:
|
||||
`org.springframework.expression.spel.SpelCompilerMode` enum. The modes are as follows.
|
||||
|
||||
* `OFF` (default): The compiler is switched off.
|
||||
* `IMMEDIATE`: In immediate mode, the expressions are compiled as soon as possible. This
|
||||
is typically after the first interpreted evaluation. If the compiled expression fails
|
||||
(typically due to a type changing, as described earlier), the caller of the expression
|
||||
evaluation receives an exception.
|
||||
* `MIXED`: In mixed mode, the expressions silently switch between interpreted and compiled
|
||||
mode over time. After some number of interpreted runs, they switch to compiled
|
||||
form and, if something goes wrong with the compiled form (such as a type changing, as
|
||||
described earlier), the expression automatically switches back to interpreted form
|
||||
again. Sometime later, it may generate another compiled form and switch to it. Basically,
|
||||
the exception that the user gets in `IMMEDIATE` mode is instead handled internally.
|
||||
is typically after the first interpreted evaluation. If the compiled expression fails
|
||||
(typically due to a type changing, as described earlier), the caller of the expression
|
||||
evaluation receives an exception.
|
||||
* `MIXED`: In mixed mode, the expressions silently switch between interpreted and
|
||||
compiled mode over time. After some number of interpreted runs, they switch to compiled
|
||||
form and, if something goes wrong with the compiled form (such as a type changing, as
|
||||
described earlier), the expression automatically switches back to interpreted form
|
||||
again. Sometime later, it may generate another compiled form and switch to it.
|
||||
Basically, the exception that the user gets in `IMMEDIATE` mode is instead handled
|
||||
internally.
|
||||
|
||||
`IMMEDIATE` mode exists because `MIXED` mode could cause issues for expressions that
|
||||
have side effects. If a compiled expression blows up after partially succeeding, it
|
||||
may have already done something that has affected the state of the system. If this
|
||||
has happened, the caller may not want it to silently re-run in interpreted mode,
|
||||
since part of the expression may be running twice.
|
||||
since part of the expression may be run twice.
|
||||
|
||||
After selecting a mode, use the `SpelParserConfiguration` to configure the parser. The
|
||||
following example shows how to do so:
|
||||
following example shows how to do so.
|
||||
|
||||
[tabs]
|
||||
======
|
||||
@@ -482,15 +492,16 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
When you specify the compiler mode, you can also specify a classloader (passing null is allowed).
|
||||
Compiled expressions are defined in a child classloader created under any that is supplied.
|
||||
It is important to ensure that, if a classloader is specified, it can see all the types involved in
|
||||
the expression evaluation process. If you do not specify a classloader, a default classloader is used
|
||||
(typically the context classloader for the thread that is running during expression evaluation).
|
||||
When you specify the compiler mode, you can also specify a `ClassLoader` (passing `null`
|
||||
is allowed). Compiled expressions are defined in a child `ClassLoader` created under any
|
||||
that is supplied. It is important to ensure that, if a `ClassLoader` is specified, it can
|
||||
see all the types involved in the expression evaluation process. If you do not specify a
|
||||
`ClassLoader`, a default `ClassLoader` is used (typically the context `ClassLoader` for
|
||||
the thread that is running during expression evaluation).
|
||||
|
||||
The second way to configure the compiler is for use when SpEL is embedded inside some
|
||||
other component and it may not be possible to configure it through a configuration
|
||||
object. In these cases, it is possible to set the `spring.expression.compiler.mode`
|
||||
object. In such cases, it is possible to set the `spring.expression.compiler.mode`
|
||||
property via a JVM system property (or via the
|
||||
xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism) to one of the
|
||||
`SpelCompilerMode` enum values (`off`, `immediate`, or `mixed`).
|
||||
@@ -499,18 +510,14 @@ xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism) to
|
||||
[[expressions-compiler-limitations]]
|
||||
=== Compiler Limitations
|
||||
|
||||
Since Spring Framework 4.1, the basic compilation framework is in place. However, the framework
|
||||
does not yet support compiling every kind of expression. The initial focus has been on the
|
||||
common expressions that are likely to be used in performance-critical contexts. The following
|
||||
kinds of expression cannot be compiled at the moment:
|
||||
Spring does not support compiling every kind of expression. The primary focus is on
|
||||
common expressions that are likely to be used in performance-critical contexts. The
|
||||
following kinds of expressions cannot be compiled.
|
||||
|
||||
* Expressions involving assignment
|
||||
* Expressions relying on the conversion service
|
||||
* Expressions using custom resolvers or accessors
|
||||
* Expressions using selection or projection
|
||||
|
||||
More types of expressions will be compilable in the future.
|
||||
|
||||
|
||||
|
||||
Compilation of additional kinds of expressions may be supported in the future.
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
Projection lets a collection drive the evaluation of a sub-expression, and the result is
|
||||
a new collection. The syntax for projection is `.![projectionExpression]`. For example,
|
||||
suppose we have a list of inventors but want the list of cities where they were born.
|
||||
Effectively, we want to evaluate 'placeOfBirth.city' for every entry in the inventor
|
||||
Effectively, we want to evaluate `placeOfBirth.city` for every entry in the inventor
|
||||
list. The following example uses projection to do so:
|
||||
|
||||
[tabs]
|
||||
|
||||
@@ -440,12 +440,8 @@ Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
val tuples: MutableList<Array<Any>> = ArrayList()
|
||||
tuples.add(arrayOf("John", 35))
|
||||
tuples.add(arrayOf("Ann", 50))
|
||||
|
||||
client.sql("SELECT id, name, state FROM table WHERE age IN (:ages)")
|
||||
.bind("tuples", arrayOf(35, 50))
|
||||
.bind("ages", arrayOf(35, 50))
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
+5
@@ -38,6 +38,11 @@ within the method.
|
||||
A reactive transaction managed by `ReactiveTransactionManager` uses the Reactor context
|
||||
instead of thread-local attributes. As a consequence, all participating data access
|
||||
operations need to execute within the same Reactor context in the same reactive pipeline.
|
||||
|
||||
When configured with a `ReactiveTransactionManager`, all transaction-demarcated methods
|
||||
are expected to return a reactive pipeline. Void methods or regular return types need
|
||||
to be associated with a regular `PlatformTransactionManager`, e.g. through the
|
||||
`transactionManager` attribute of the corresponding `@Transactional` declarations.
|
||||
====
|
||||
|
||||
The following image shows a conceptual view of calling a method on a transactional proxy:
|
||||
|
||||
@@ -29,7 +29,7 @@ Brannen, Ramnivas Laddad, Arjen Poutsma, Chris Beams, Tareq Abedrabbo, Andy Clem
|
||||
Syer, Oliver Gierke, Rossen Stoyanchev, Phillip Webb, Rob Winch, Brian Clozel, Stephane
|
||||
Nicoll, Sebastien Deleuze, Jay Bryant, Mark Paluch
|
||||
|
||||
Copyright © 2002 - 2023 VMware, Inc. All Rights Reserved.
|
||||
Copyright © 2002 - 2024 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Copies of this document may be made for your own use and for distribution to others,
|
||||
provided that you do not charge any fee for such copies and further provided that each
|
||||
|
||||
@@ -85,7 +85,7 @@ email when someone places an order:
|
||||
|
||||
// Call the collaborators to persist the order...
|
||||
|
||||
// Create a thread safe "copy" of the template message and customize it
|
||||
// Create a thread-safe "copy" of the template message and customize it
|
||||
SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage);
|
||||
msg.setTo(order.getCustomer().getEmailAddress());
|
||||
msg.setText(
|
||||
|
||||
@@ -108,7 +108,7 @@ By default, the following `KeyValues` are created:
|
||||
|===
|
||||
|Name | Description
|
||||
|`code.function` _(required)_|Name of Java `Method` that is scheduled for execution.
|
||||
|`code.namespace` _(required)_|Canonical name of the class of the bean instance that holds the scheduled method.
|
||||
|`code.namespace` _(required)_|Canonical name of the class of the bean instance that holds the scheduled method, or `"ANONYMOUS"` for anonymous classes.
|
||||
|`error` _(required)_|Class name of the exception thrown during the execution, or `"none"` if no exception happened.
|
||||
|`exception` _(deprecated)_|Duplicates the `error` key and might be removed in the future.
|
||||
|`outcome` _(required)_|Outcome of the method execution. Can be `"SUCCESS"`, `"ERROR"` or `"UNKNOWN"` (if for example the operation was cancelled during execution).
|
||||
|
||||
@@ -906,8 +906,8 @@ For `WebClient`:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
WebClient client = WebClient.builder().baseUrl("https://api.github.com/").build();
|
||||
WebClientAdapter adapter = WebClientAdapter.forClient(webClient)
|
||||
WebClient webClient = WebClient.builder().baseUrl("https://api.github.com/").build();
|
||||
WebClientAdapter adapter = WebClientAdapter.create(webClient);
|
||||
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
|
||||
|
||||
RepositoryService service = factory.createClient(RepositoryService.class);
|
||||
@@ -1078,11 +1078,34 @@ underlying HTTP client, which operates at a lower level and provides more contro
|
||||
|
||||
|
||||
[[rest-http-interface-exceptions]]
|
||||
=== Exception Handling
|
||||
=== Error Handling
|
||||
|
||||
By default, `WebClient` raises `WebClientResponseException` for 4xx and 5xx HTTP status
|
||||
codes. To customize this, you can register a response status handler that applies to all
|
||||
responses performed through the client:
|
||||
To customize error response handling, you need to configure the underlying HTTP client.
|
||||
|
||||
For `RestClient`:
|
||||
|
||||
By default, `RestClient` raises `RestClientException` for 4xx and 5xx HTTP status codes.
|
||||
To customize this, register a response status handler that applies to all responses
|
||||
performed through the client:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
RestClient restClient = RestClient.builder()
|
||||
.defaultStatusHandler(HttpStatusCode::isError, (request, response) -> ...)
|
||||
.build();
|
||||
|
||||
RestClientAdapter adapter = RestClientAdapter.create(restClient);
|
||||
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
|
||||
----
|
||||
|
||||
For more details and options, such as suppressing error status codes, see the Javadoc of
|
||||
`defaultStatusHandler` in `RestClient.Builder`.
|
||||
|
||||
For `WebClient`:
|
||||
|
||||
By default, `WebClient` raises `WebClientResponseException` for 4xx and 5xx HTTP status codes.
|
||||
To customize this, register a response status handler that applies to all responses
|
||||
performed through the client:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1090,10 +1113,28 @@ responses performed through the client:
|
||||
.defaultStatusHandler(HttpStatusCode::isError, resp -> ...)
|
||||
.build();
|
||||
|
||||
WebClientAdapter clientAdapter = WebClientAdapter.forClient(webClient);
|
||||
HttpServiceProxyFactory factory = HttpServiceProxyFactory
|
||||
.builder(clientAdapter).build();
|
||||
WebClientAdapter adapter = WebClientAdapter.create(webClient);
|
||||
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(adapter).build();
|
||||
----
|
||||
|
||||
For more details and options, such as suppressing error status codes, see the Javadoc of
|
||||
`defaultStatusHandler` in `WebClient.Builder`.
|
||||
|
||||
For `RestTemplate`:
|
||||
|
||||
By default, `RestTemplate` raises `RestClientException` for 4xx and 5xx HTTP status codes.
|
||||
To customize this, register an error handler that applies to all responses
|
||||
performed through the client:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
restTemplate.setErrorHandler(myErrorHandler);
|
||||
|
||||
RestTemplateAdapter adapter = RestTemplateAdapter.create(restTemplate);
|
||||
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
|
||||
----
|
||||
|
||||
For more details and options, see the Javadoc of `setErrorHandler` in `RestTemplate` and
|
||||
the `ResponseErrorHandler` hierarchy.
|
||||
|
||||
|
||||
@@ -252,7 +252,9 @@ application server environments, as well -- in particular on Tomcat and Jetty.
|
||||
As of 6.1, `ThreadPoolTaskScheduler` provides a pause/resume capability and graceful
|
||||
shutdown through Spring's lifecycle management. There is also a new option called
|
||||
`SimpleAsyncTaskScheduler` which is aligned with JDK 21's Virtual Threads, using a
|
||||
single scheduler thread but firing up a new thread for every scheduled task execution.
|
||||
single scheduler thread but firing up a new thread for every scheduled task execution
|
||||
(except for fixed-delay tasks which all operate on a single scheduler thread, so for
|
||||
this virtual-thread-aligned option, fixed rates and cron triggers are recommended).
|
||||
|
||||
|
||||
|
||||
@@ -477,12 +479,12 @@ the framework to invoke a suspending function as a `Publisher`.
|
||||
|
||||
The Spring Framework will obtain a `Publisher` for the annotated method once and will
|
||||
schedule a `Runnable` in which it subscribes to said `Publisher`. These inner regular
|
||||
subscriptions occur according to the corresponding `cron`/fixedDelay`/`fixedRate` configuration.
|
||||
subscriptions occur according to the corresponding `cron`/`fixedDelay`/`fixedRate` configuration.
|
||||
|
||||
If the `Publisher` emits `onNext` signal(s), these are ignored and discarded (the same way
|
||||
return values from synchronous `@Scheduled` methods are ignored).
|
||||
|
||||
In the following example, the `Flux` emits `onNext("Hello"), onNext("World")` every 5
|
||||
In the following example, the `Flux` emits `onNext("Hello")`, `onNext("World")` every 5
|
||||
seconds, but these values are unused:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
|
||||
@@ -13,7 +13,7 @@ Most of the code samples of the reference documentation are
|
||||
provided in Kotlin in addition to Java.
|
||||
|
||||
The easiest way to build a Spring application with Kotlin is to leverage Spring Boot and
|
||||
its{spring-boot-docs}/boot-features-kotlin.html[dedicated Kotlin support].
|
||||
its {spring-boot-docs}/boot-features-kotlin.html[dedicated Kotlin support].
|
||||
{spring-site-guides}/tutorials/spring-boot-kotlin/[This comprehensive tutorial]
|
||||
will teach you how to build Spring Boot applications with Kotlin using https://start.spring.io/#!language=kotlin&type=gradle-project[start.spring.io].
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ NOTE: Spring Boot is based on JavaConfig and
|
||||
{spring-boot-issues}/8115[does not yet provide specific support for functional bean definition],
|
||||
but you can experimentally use functional bean definitions through Spring Boot's `ApplicationContextInitializer` support.
|
||||
See {stackoverflow-questions}/45935931/how-to-use-functional-bean-definition-kotlin-dsl-with-spring-boot-and-spring-w/46033685#46033685[this Stack Overflow answer]
|
||||
for more details and up-to-date information. See also the experimental Kofu DSL developed in {spring-github-org}/spring-fu[Spring Fu incubator].
|
||||
for more details and up-to-date information. See also the experimental Kofu DSL developed in {spring-github-org}-experimental/spring-fu[Spring Fu incubator].
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -14,8 +14,10 @@ Spring Framework provides support for Coroutines on the following scope:
|
||||
* Suspending function support in Spring MVC and WebFlux annotated `@Controller`
|
||||
* Extensions for WebFlux {spring-framework-api-kdoc}/spring-webflux/org.springframework.web.reactive.function.client/index.html[client] and {spring-framework-api-kdoc}/spring-webflux/org.springframework.web.reactive.function.server/index.html[server] functional API.
|
||||
* WebFlux.fn {spring-framework-api-kdoc}/spring-webflux/org.springframework.web.reactive.function.server/co-router.html[coRouter { }] DSL
|
||||
* WebFlux {spring-framework-api-kdoc}/spring-web/org.springframework.web.server/-co-web-filter/index.html[`CoWebFilter`]
|
||||
* Suspending function and `Flow` support in RSocket `@MessageMapping` annotated methods
|
||||
* Extensions for {spring-framework-api-kdoc}/spring-messaging/org.springframework.messaging.rsocket/index.html[`RSocketRequester`]
|
||||
* Spring AOP
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -10,22 +10,21 @@ The easiest way to learn how to build a Spring application with Kotlin is to fol
|
||||
== `start.spring.io`
|
||||
|
||||
The easiest way to start a new Spring Framework project in Kotlin is to create a new Spring
|
||||
Boot 2 project on https://start.spring.io/#!language=kotlin&type=gradle-project[start.spring.io].
|
||||
Boot project on https://start.spring.io/#!language=kotlin&type=gradle-project-kotlin[start.spring.io].
|
||||
|
||||
|
||||
|
||||
[[choosing-the-web-flavor]]
|
||||
== Choosing the Web Flavor
|
||||
|
||||
Spring Framework now comes with two different web stacks: xref:web/webmvc.adoc#mvc[Spring MVC] and
|
||||
Spring Framework comes with two different web stacks: xref:web/webmvc.adoc#mvc[Spring MVC] and
|
||||
xref:testing/unit.adoc#mock-objects-web-reactive[Spring WebFlux].
|
||||
|
||||
Spring WebFlux is recommended if you want to create applications that will deal with latency,
|
||||
long-lived connections, streaming scenarios or if you want to use the web functional
|
||||
Kotlin DSL.
|
||||
long-lived connections or streaming scenarios.
|
||||
|
||||
For other use cases, especially if you are using blocking technologies such as JPA, Spring
|
||||
MVC and its annotation-based programming model is the recommended choice.
|
||||
MVC is the recommended choice.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,15 +2,12 @@
|
||||
= Requirements
|
||||
:page-section-summary-toc: 1
|
||||
|
||||
Spring Framework supports Kotlin 1.3+ and requires
|
||||
Spring Framework supports Kotlin 1.7+ and requires
|
||||
https://search.maven.org/artifact/org.jetbrains.kotlin/kotlin-stdlib[`kotlin-stdlib`]
|
||||
(or one of its variants, such as https://search.maven.org/artifact/org.jetbrains.kotlin/kotlin-stdlib-jdk8[`kotlin-stdlib-jdk8`])
|
||||
and https://search.maven.org/artifact/org.jetbrains.kotlin/kotlin-reflect[`kotlin-reflect`]
|
||||
to be present on the classpath. They are provided by default if you bootstrap a Kotlin project on
|
||||
https://start.spring.io/#!language=kotlin&type=gradle-project[start.spring.io].
|
||||
|
||||
WARNING: Kotlin {kotlin-docs}/inline-classes.html[inline classes] are not yet supported.
|
||||
|
||||
NOTE: The {jackson-github-org}/jackson-module-kotlin[Jackson Kotlin module] is required
|
||||
for serializing or deserializing JSON data for Kotlin classes with Jackson, so make sure to add the
|
||||
`com.fasterxml.jackson.module:jackson-module-kotlin` dependency to your project if you have such need.
|
||||
|
||||
@@ -18,28 +18,9 @@ Kotlin and the Spring Framework:
|
||||
|
||||
The following Github projects offer examples that you can learn from and possibly even extend:
|
||||
|
||||
* https://github.com/spring-guides/tut-spring-boot-kotlin[tut-spring-boot-kotlin]: Sources of {spring-site}/guides/tutorials/spring-boot-kotlin/[the official Spring + Kotlin tutorial]
|
||||
* https://github.com/sdeleuze/spring-boot-kotlin-demo[spring-boot-kotlin-demo]: Regular Spring Boot and Spring Data JPA project
|
||||
* https://github.com/mixitconf/mixit[mixit]: Spring Boot 2, WebFlux, and Reactive Spring Data MongoDB
|
||||
* https://github.com/mixitconf/mixit[mixit]: Spring Boot, WebFlux, and Reactive Spring Data MongoDB
|
||||
* https://github.com/sdeleuze/spring-kotlin-functional[spring-kotlin-functional]: Standalone WebFlux and functional bean definition DSL
|
||||
* https://github.com/sdeleuze/spring-kotlin-fullstack[spring-kotlin-fullstack]: WebFlux Kotlin fullstack example with Kotlin2js for frontend instead of JavaScript or TypeScript
|
||||
* https://github.com/spring-petclinic/spring-petclinic-kotlin[spring-petclinic-kotlin]: Kotlin version of the Spring PetClinic Sample Application
|
||||
* https://github.com/sdeleuze/spring-kotlin-deepdive[spring-kotlin-deepdive]: A step-by-step migration guide for Boot 1.0 and Java to Boot 2.0 and Kotlin
|
||||
* https://github.com/spring-cloud/spring-cloud-gcp/tree/master/spring-cloud-gcp-kotlin-samples/spring-cloud-gcp-kotlin-app-sample[spring-cloud-gcp-kotlin-app-sample]: Spring Boot with Google Cloud Platform Integrations
|
||||
|
||||
|
||||
|
||||
[[issues]]
|
||||
== Issues
|
||||
|
||||
The following list categorizes the pending issues related to Spring and Kotlin support:
|
||||
|
||||
* Spring Framework
|
||||
** {spring-framework-issues}/20606[Unable to use WebTestClient with mock server in Kotlin]
|
||||
** {spring-framework-issues}/20496[Support null-safety at generics, varargs and array elements level]
|
||||
* Kotlin
|
||||
** {kotlin-issues}/KT-6380[Parent issue for Spring Framework support]
|
||||
** {kotlin-issues}/KT-5464[Kotlin requires type inference where Java doesn't]
|
||||
** {kotlin-issues}/KT-20283[Smart cast regression with open classes]
|
||||
** {kotlin-issues}/KT-14984[Impossible to pass not all SAM argument as function]
|
||||
** {kotlin-issues}/KT-15125[Support JSR 223 bindings directly via script variables]
|
||||
** {kotlin-issues}/KT-6653[Kotlin properties do not override Java-style getters and setters]
|
||||
|
||||
@@ -97,6 +97,9 @@ does not require the `kotlin-noarg` plugin if the module uses Spring Data object
|
||||
[[injecting-dependencies]]
|
||||
== Injecting Dependencies
|
||||
|
||||
[[favor-constructor-injection]]
|
||||
=== Favor constructor injection
|
||||
|
||||
Our recommendation is to try to favor constructor injection with `val` read-only (and
|
||||
non-nullable when possible) {kotlin-docs}/properties.html[properties],
|
||||
as the following example shows:
|
||||
@@ -130,7 +133,41 @@ as the following example shows:
|
||||
}
|
||||
----
|
||||
|
||||
[[internal-functions-name-mangling]]
|
||||
=== Internal functions name mangling
|
||||
|
||||
Kotlin functions with the `internal` {kotlin-docs}/visibility-modifiers.html#class-members[visibility modifier] have
|
||||
their names mangled when compiled to JVM bytecode, which has a side effect when injecting dependencies by name.
|
||||
|
||||
For example, this Kotlin class:
|
||||
[source,kotlin,indent=0]
|
||||
----
|
||||
@Configuration
|
||||
class SampleConfiguration {
|
||||
|
||||
@Bean
|
||||
internal fun sampleBean() = SampleBean()
|
||||
}
|
||||
----
|
||||
|
||||
Translates to this Java representation of the compiled JVM bytecode:
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Configuration
|
||||
@Metadata(/* ... */)
|
||||
public class SampleConfiguration {
|
||||
|
||||
@Bean
|
||||
@NotNull
|
||||
public SampleBean sampleBean$demo_kotlin_internal_test() {
|
||||
return new SampleBean();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
As a consequence, the related bean name represented as a Kotlin string is `"sampleBean\$demo_kotlin_internal_test"`,
|
||||
instead of `"sampleBean"` for the regular `public` function use-case. Make sure to use the mangled name when injecting
|
||||
such bean by name.
|
||||
|
||||
[[injecting-configuration-properties]]
|
||||
== Injecting Configuration Properties
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
Spring Framework comes with a Kotlin router DSL available in 3 flavors:
|
||||
|
||||
* WebMvc.fn DSL with {spring-framework-api-kdoc}/spring-webmvc/org.springframework.web.servlet.function/router.html[router { }]
|
||||
* WebFlux.fn <<web-reactive#webflux-fn, Reactive>> DSL with {spring-framework-api-kdoc}/spring-webflux/org.springframework.web.reactive.function.server/router.html[router { }]
|
||||
* WebFlux.fn <<Coroutines>> DSL with {spring-framework-api-kdoc}/spring-webflux/org.springframework.web.reactive.function.server/co-router.html[coRouter { }]
|
||||
* xref:web/webmvc-functional.adoc[WebMvc.fn DSL] with {spring-framework-api-kdoc}/spring-webmvc/org.springframework.web.servlet.function/router.html[router { }]
|
||||
* xref:web/webflux-functional.adoc[WebFlux.fn Reactive DSL] with {spring-framework-api-kdoc}/spring-webflux/org.springframework.web.reactive.function.server/router.html[router { }]
|
||||
* xref:languages/kotlin/coroutines.adoc[WebFlux.fn Coroutines DSL] with {spring-framework-api-kdoc}/spring-webflux/org.springframework.web.reactive.function.server/co-router.html[coRouter { }]
|
||||
|
||||
These DSL let you write clean and idiomatic Kotlin code to build a `RouterFunction` instance as the following example shows:
|
||||
|
||||
@@ -126,7 +126,7 @@ project for more details.
|
||||
[[kotlin-multiplatform-serialization]]
|
||||
== Kotlin multiplatform serialization
|
||||
|
||||
As of Spring Framework 5.3, {kotlin-github-org}/kotlinx.serialization[Kotlin multiplatform serialization] is
|
||||
{kotlin-github-org}/kotlinx.serialization[Kotlin multiplatform serialization] is
|
||||
supported in Spring MVC, Spring WebFlux and Spring Messaging (RSocket). The builtin support currently targets CBOR, JSON, and ProtoBuf formats.
|
||||
|
||||
To enable it, follow {kotlin-github-org}/kotlinx.serialization#setup[those instructions] to add the related dependency and plugin.
|
||||
|
||||
@@ -78,8 +78,9 @@ it does the same, but it also compares the computed value against the `If-None-M
|
||||
request header and, if the two are equal, returns a 304 (NOT_MODIFIED).
|
||||
|
||||
This strategy saves network bandwidth but not CPU, as the full response must be computed for each request.
|
||||
State-changing HTTP methods and other HTTP conditional request headers such as `If-Match` and `If-Unmodified-Since` are outside the scope of this filter.
|
||||
Other strategies at the controller level can avoid the computation and have a broader support for HTTP conditional requests.
|
||||
State-changing HTTP methods and other HTTP conditional request headers such as `If-Match` and
|
||||
`If-Unmodified-Since` are outside the scope of this filter. Other strategies at the controller level
|
||||
can avoid the computation and have a broader support for HTTP conditional requests.
|
||||
See xref:web/webmvc/mvc-caching.adoc[HTTP Caching].
|
||||
|
||||
This filter has a `writeWeakETag` parameter that configures the filter to write weak ETags
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ The next example uses server-side configuration to register a custom authenticat
|
||||
interceptor. Note that an interceptor needs only to authenticate and set
|
||||
the user header on the CONNECT `Message`. Spring notes and saves the authenticated
|
||||
user and associate it with subsequent STOMP messages on the same session. The following
|
||||
example shows how register a custom authentication interceptor:
|
||||
example shows how to register a custom authentication interceptor:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
|
||||
@@ -7,16 +7,17 @@ javaPlatform {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(platform("com.fasterxml.jackson:jackson-bom:2.15.2"))
|
||||
api(platform("io.micrometer:micrometer-bom:1.12.1"))
|
||||
api(platform("io.netty:netty-bom:4.1.101.Final"))
|
||||
api(platform("com.fasterxml.jackson:jackson-bom:2.15.3"))
|
||||
api(platform("io.micrometer:micrometer-bom:1.12.2"))
|
||||
api(platform("io.netty:netty-bom:4.1.104.Final"))
|
||||
api(platform("io.netty:netty5-bom:5.0.0.Alpha5"))
|
||||
api(platform("io.projectreactor:reactor-bom:2023.0.1"))
|
||||
api(platform("io.projectreactor:reactor-bom:2023.0.2"))
|
||||
api(platform("io.rsocket:rsocket-bom:1.1.3"))
|
||||
api(platform("org.apache.groovy:groovy-bom:4.0.16"))
|
||||
api(platform("org.apache.groovy:groovy-bom:4.0.17"))
|
||||
api(platform("org.apache.logging.log4j:log4j-bom:2.21.1"))
|
||||
api(platform("org.eclipse.jetty:jetty-bom:12.0.4"))
|
||||
api(platform("org.eclipse.jetty.ee10:jetty-ee10-bom:12.0.3"))
|
||||
api(platform("org.assertj:assertj-bom:3.25.1"))
|
||||
api(platform("org.eclipse.jetty:jetty-bom:12.0.5"))
|
||||
api(platform("org.eclipse.jetty.ee10:jetty-ee10-bom:12.0.5"))
|
||||
api(platform("org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.7.3"))
|
||||
api(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:1.6.0"))
|
||||
api(platform("org.junit:junit-bom:5.10.1"))
|
||||
@@ -26,11 +27,11 @@ dependencies {
|
||||
api("com.fasterxml:aalto-xml:1.3.2")
|
||||
api("com.fasterxml.woodstox:woodstox-core:6.5.1")
|
||||
api("com.github.ben-manes.caffeine:caffeine:3.1.8")
|
||||
api("com.github.librepdf:openpdf:1.3.33")
|
||||
api("com.github.librepdf:openpdf:1.3.36")
|
||||
api("com.google.code.findbugs:findbugs:3.0.1")
|
||||
api("com.google.code.findbugs:jsr305:3.0.2")
|
||||
api("com.google.code.gson:gson:2.10.1")
|
||||
api("com.google.protobuf:protobuf-java-util:3.25.0")
|
||||
api("com.google.protobuf:protobuf-java-util:3.25.1")
|
||||
api("com.h2database:h2:2.2.224")
|
||||
api("com.jayway.jsonpath:json-path:2.8.0")
|
||||
api("com.rometools:rome:1.19.0")
|
||||
@@ -99,17 +100,16 @@ dependencies {
|
||||
api("org.apache.derby:derby:10.16.1.1")
|
||||
api("org.apache.derby:derbyclient:10.16.1.1")
|
||||
api("org.apache.derby:derbytools:10.16.1.1")
|
||||
api("org.apache.httpcomponents.client5:httpclient5:5.2.1")
|
||||
api("org.apache.httpcomponents.core5:httpcore5-reactive:5.2.3")
|
||||
api("org.apache.poi:poi-ooxml:5.2.4")
|
||||
api("org.apache.tomcat.embed:tomcat-embed-core:10.1.16")
|
||||
api("org.apache.tomcat.embed:tomcat-embed-websocket:10.1.16")
|
||||
api("org.apache.tomcat:tomcat-util:10.1.16")
|
||||
api("org.apache.tomcat:tomcat-websocket:10.1.16")
|
||||
api("org.aspectj:aspectjrt:1.9.20.1")
|
||||
api("org.aspectj:aspectjtools:1.9.20.1")
|
||||
api("org.aspectj:aspectjweaver:1.9.20.1")
|
||||
api("org.assertj:assertj-core:3.24.2")
|
||||
api("org.apache.httpcomponents.client5:httpclient5:5.3")
|
||||
api("org.apache.httpcomponents.core5:httpcore5-reactive:5.2.4")
|
||||
api("org.apache.poi:poi-ooxml:5.2.5")
|
||||
api("org.apache.tomcat.embed:tomcat-embed-core:10.1.18")
|
||||
api("org.apache.tomcat.embed:tomcat-embed-websocket:10.1.18")
|
||||
api("org.apache.tomcat:tomcat-util:10.1.18")
|
||||
api("org.apache.tomcat:tomcat-websocket:10.1.18")
|
||||
api("org.aspectj:aspectjrt:1.9.21")
|
||||
api("org.aspectj:aspectjtools:1.9.21")
|
||||
api("org.aspectj:aspectjweaver:1.9.21")
|
||||
api("org.awaitility:awaitility:4.2.0")
|
||||
api("org.bouncycastle:bcpkix-jdk18on:1.72")
|
||||
api("org.codehaus.jettison:jettison:1.5.4")
|
||||
@@ -131,7 +131,7 @@ dependencies {
|
||||
api("org.hsqldb:hsqldb:2.7.2")
|
||||
api("org.javamoney:moneta:1.4.2")
|
||||
api("org.jruby:jruby:9.4.5.0")
|
||||
api("org.junit.support:testng-engine:1.0.4")
|
||||
api("org.junit.support:testng-engine:1.0.5")
|
||||
api("org.mozilla:rhino:1.7.14")
|
||||
api("org.ogce:xpp3:1.1.6")
|
||||
api("org.python:jython-standalone:2.7.3")
|
||||
@@ -139,8 +139,8 @@ dependencies {
|
||||
api("org.seleniumhq.selenium:htmlunit-driver:2.70.0")
|
||||
api("org.seleniumhq.selenium:selenium-java:3.141.59")
|
||||
api("org.skyscreamer:jsonassert:1.5.1")
|
||||
api("org.slf4j:slf4j-api:2.0.9")
|
||||
api("org.testng:testng:7.8.0")
|
||||
api("org.slf4j:slf4j-api:2.0.11")
|
||||
api("org.testng:testng:7.9.0")
|
||||
api("org.webjars:underscorejs:1.8.3")
|
||||
api("org.webjars:webjars-locator-core:0.55")
|
||||
api("org.xmlunit:xmlunit-assertj:2.9.1")
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
version=6.1.2-SNAPSHOT
|
||||
version=6.1.3
|
||||
|
||||
org.gradle.caching=true
|
||||
org.gradle.jvmargs=-Xmx2048m
|
||||
org.gradle.parallel=true
|
||||
|
||||
kotlinVersion=1.9.21
|
||||
kotlinVersion=1.9.22
|
||||
|
||||
kotlin.jvm.target.validation.mode=ignore
|
||||
kotlin.stdlib.default.dependency=false
|
||||
|
||||
+18
-2
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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 org.springframework.aop.framework.autoproxy
|
||||
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -94,12 +110,12 @@ class AspectJAutoProxyInterceptorKotlinIntegrationTests(
|
||||
open class Echo {
|
||||
|
||||
open fun echo(value: String): String {
|
||||
return value;
|
||||
return value
|
||||
}
|
||||
|
||||
open suspend fun suspendingEcho(value: String): String {
|
||||
delay(1)
|
||||
return value;
|
||||
return value
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -334,13 +334,15 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
Object targetObject = null;
|
||||
Object thisObject = null;
|
||||
try {
|
||||
MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
|
||||
targetObject = mi.getThis();
|
||||
if (!(mi instanceof ProxyMethodInvocation _pmi)) {
|
||||
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
|
||||
MethodInvocation curr = ExposeInvocationInterceptor.currentInvocation();
|
||||
if (curr.getMethod() == method) {
|
||||
targetObject = curr.getThis();
|
||||
if (!(curr instanceof ProxyMethodInvocation currPmi)) {
|
||||
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + curr);
|
||||
}
|
||||
pmi = currPmi;
|
||||
thisObject = pmi.getProxy();
|
||||
}
|
||||
pmi = _pmi;
|
||||
thisObject = pmi.getProxy();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
// No current invocation...
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -293,7 +293,7 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
// This can match only on declared pointcut.
|
||||
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass));
|
||||
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass, args));
|
||||
}
|
||||
|
||||
private boolean isAspectMaterialized() {
|
||||
|
||||
+10
-21
@@ -201,9 +201,8 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
List<BeanReference> beanReferences = new ArrayList<>();
|
||||
|
||||
List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS);
|
||||
for (int i = METHOD_INDEX; i < declareParents.size(); i++) {
|
||||
Element declareParentsElement = declareParents.get(i);
|
||||
beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext));
|
||||
for (Element declareParent : declareParents) {
|
||||
beanDefinitions.add(parseDeclareParents(declareParent, parserContext));
|
||||
}
|
||||
|
||||
// We have to parse "advice" and all the advice kinds in one loop, to get the
|
||||
@@ -405,24 +404,14 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
*/
|
||||
private Class<?> getAdviceClass(Element adviceElement, ParserContext parserContext) {
|
||||
String elementName = parserContext.getDelegate().getLocalName(adviceElement);
|
||||
if (BEFORE.equals(elementName)) {
|
||||
return AspectJMethodBeforeAdvice.class;
|
||||
}
|
||||
else if (AFTER.equals(elementName)) {
|
||||
return AspectJAfterAdvice.class;
|
||||
}
|
||||
else if (AFTER_RETURNING_ELEMENT.equals(elementName)) {
|
||||
return AspectJAfterReturningAdvice.class;
|
||||
}
|
||||
else if (AFTER_THROWING_ELEMENT.equals(elementName)) {
|
||||
return AspectJAfterThrowingAdvice.class;
|
||||
}
|
||||
else if (AROUND.equals(elementName)) {
|
||||
return AspectJAroundAdvice.class;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unknown advice kind [" + elementName + "].");
|
||||
}
|
||||
return switch (elementName) {
|
||||
case BEFORE -> AspectJMethodBeforeAdvice.class;
|
||||
case AFTER -> AspectJAfterAdvice.class;
|
||||
case AFTER_RETURNING_ELEMENT -> AspectJAfterReturningAdvice.class;
|
||||
case AFTER_THROWING_ELEMENT -> AspectJAfterThrowingAdvice.class;
|
||||
case AROUND -> AspectJAroundAdvice.class;
|
||||
default -> throw new IllegalArgumentException("Unknown advice kind [" + elementName + "].");
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -42,10 +42,8 @@ class ScopedProxyBeanDefinitionDecorator implements BeanDefinitionDecorator {
|
||||
@Override
|
||||
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
|
||||
boolean proxyTargetClass = true;
|
||||
if (node instanceof Element ele) {
|
||||
if (ele.hasAttribute(PROXY_TARGET_CLASS)) {
|
||||
proxyTargetClass = Boolean.parseBoolean(ele.getAttribute(PROXY_TARGET_CLASS));
|
||||
}
|
||||
if (node instanceof Element ele && ele.hasAttribute(PROXY_TARGET_CLASS)) {
|
||||
proxyTargetClass = Boolean.parseBoolean(ele.getAttribute(PROXY_TARGET_CLASS));
|
||||
}
|
||||
|
||||
// Register the original bean definition as it will be referenced by the scoped proxy
|
||||
|
||||
@@ -102,8 +102,23 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
*/
|
||||
private List<Advisor> advisors = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* List of minimal {@link AdvisorKeyEntry} instances,
|
||||
* to be assigned to the {@link #advisors} field on reduction.
|
||||
* @since 6.0.10
|
||||
* @see #reduceToAdvisorKey
|
||||
*/
|
||||
private List<Advisor> advisorKey = this.advisors;
|
||||
|
||||
/**
|
||||
* Optional field for {@link AopProxy} implementations to store metadata in.
|
||||
* Used by {@link JdkDynamicAopProxy}.
|
||||
* @since 6.1.3
|
||||
* @see JdkDynamicAopProxy#JdkDynamicAopProxy(AdvisedSupport)
|
||||
*/
|
||||
@Nullable
|
||||
transient volatile Object proxyMetadataCache;
|
||||
|
||||
|
||||
/**
|
||||
* No-arg constructor for use as a JavaBean.
|
||||
@@ -491,6 +506,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
*/
|
||||
protected void adviceChanged() {
|
||||
this.methodCache.clear();
|
||||
this.proxyMetadataCache = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -551,18 +567,6 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Serialization support
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
// Rely on default serialization; just initialize state after deserialization.
|
||||
ois.defaultReadObject();
|
||||
|
||||
// Initialize transient fields.
|
||||
this.methodCache = new ConcurrentHashMap<>(32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toProxyConfigString() {
|
||||
return toString();
|
||||
@@ -584,6 +588,19 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Serialization support
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
// Rely on default serialization; just initialize state after deserialization.
|
||||
ois.defaultReadObject();
|
||||
|
||||
// Initialize transient fields.
|
||||
this.methodCache = new ConcurrentHashMap<>(32);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple wrapper class around a Method. Used as the key when
|
||||
* caching methods, for efficient equals and hashCode comparisons.
|
||||
@@ -633,7 +650,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* @see #getConfigurationOnlyCopy()
|
||||
* @see #getAdvisorKey()
|
||||
*/
|
||||
private static class AdvisorKeyEntry implements Advisor {
|
||||
private static final class AdvisorKeyEntry implements Advisor {
|
||||
|
||||
private final Class<?> adviceType;
|
||||
|
||||
@@ -643,7 +660,6 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
@Nullable
|
||||
private final String methodMatcherKey;
|
||||
|
||||
|
||||
public AdvisorKeyEntry(Advisor advisor) {
|
||||
this.adviceType = advisor.getAdvice().getClass();
|
||||
if (advisor instanceof PointcutAdvisor pointcutAdvisor) {
|
||||
|
||||
+79
-49
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.aop.framework;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -71,34 +73,16 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
private static final long serialVersionUID = 5531744639992436476L;
|
||||
|
||||
|
||||
/*
|
||||
* NOTE: We could avoid the code duplication between this class and the CGLIB
|
||||
* proxies by refactoring "invoke" into a template method. However, this approach
|
||||
* adds at least 10% performance overhead versus a copy-paste solution, so we sacrifice
|
||||
* elegance for performance (we have a good test suite to ensure that the different
|
||||
* proxies behave the same :-)).
|
||||
* This way, we can also more easily take advantage of minor optimizations in each class.
|
||||
*/
|
||||
private static final String COROUTINES_FLOW_CLASS_NAME = "kotlinx.coroutines.flow.Flow";
|
||||
|
||||
/** We use a static Log to avoid serialization issues. */
|
||||
private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
|
||||
|
||||
private static final String COROUTINES_FLOW_CLASS_NAME = "kotlinx.coroutines.flow.Flow";
|
||||
|
||||
/** Config used to configure this proxy. */
|
||||
private final AdvisedSupport advised;
|
||||
|
||||
private final Class<?>[] proxiedInterfaces;
|
||||
|
||||
/**
|
||||
* Is the {@link #equals} method defined on the proxied interfaces?
|
||||
*/
|
||||
private boolean equalsDefined;
|
||||
|
||||
/**
|
||||
* Is the {@link #hashCode} method defined on the proxied interfaces?
|
||||
*/
|
||||
private boolean hashCodeDefined;
|
||||
/** Cached in {@link AdvisedSupport#proxyMetadataCache}. */
|
||||
private transient ProxiedInterfacesCache cache;
|
||||
|
||||
|
||||
/**
|
||||
@@ -110,8 +94,17 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
|
||||
Assert.notNull(config, "AdvisedSupport must not be null");
|
||||
this.advised = config;
|
||||
this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
|
||||
findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
|
||||
|
||||
// Initialize ProxiedInterfacesCache if not cached already
|
||||
ProxiedInterfacesCache cache;
|
||||
if (config.proxyMetadataCache instanceof ProxiedInterfacesCache proxiedInterfacesCache) {
|
||||
cache = proxiedInterfacesCache;
|
||||
}
|
||||
else {
|
||||
cache = new ProxiedInterfacesCache(config);
|
||||
config.proxyMetadataCache = cache;
|
||||
}
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
|
||||
@@ -125,13 +118,13 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
|
||||
}
|
||||
return Proxy.newProxyInstance(determineClassLoader(classLoader), this.proxiedInterfaces, this);
|
||||
return Proxy.newProxyInstance(determineClassLoader(classLoader), this.cache.proxiedInterfaces, this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public Class<?> getProxyClass(@Nullable ClassLoader classLoader) {
|
||||
return Proxy.getProxyClass(determineClassLoader(classLoader), this.proxiedInterfaces);
|
||||
return Proxy.getProxyClass(determineClassLoader(classLoader), this.cache.proxiedInterfaces);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,28 +153,6 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds any {@link #equals} or {@link #hashCode} method that may be defined
|
||||
* on the supplied set of interfaces.
|
||||
* @param proxiedInterfaces the interfaces to introspect
|
||||
*/
|
||||
private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
|
||||
for (Class<?> proxiedInterface : proxiedInterfaces) {
|
||||
Method[] methods = proxiedInterface.getDeclaredMethods();
|
||||
for (Method method : methods) {
|
||||
if (AopUtils.isEqualsMethod(method)) {
|
||||
this.equalsDefined = true;
|
||||
}
|
||||
if (AopUtils.isHashCodeMethod(method)) {
|
||||
this.hashCodeDefined = true;
|
||||
}
|
||||
if (this.equalsDefined && this.hashCodeDefined) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of {@code InvocationHandler.invoke}.
|
||||
@@ -198,11 +169,11 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
Object target = null;
|
||||
|
||||
try {
|
||||
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
|
||||
if (!this.cache.equalsDefined && AopUtils.isEqualsMethod(method)) {
|
||||
// The target does not implement the equals(Object) method itself.
|
||||
return equals(args[0]);
|
||||
}
|
||||
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
|
||||
else if (!this.cache.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
|
||||
// The target does not implement the hashCode() method itself.
|
||||
return hashCode();
|
||||
}
|
||||
@@ -324,4 +295,63 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
return JdkDynamicAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Serialization support
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
// Rely on default serialization; just initialize state after deserialization.
|
||||
ois.defaultReadObject();
|
||||
|
||||
// Initialize transient fields.
|
||||
this.cache = new ProxiedInterfacesCache(this.advised);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Holder for the complete proxied interfaces and derived metadata,
|
||||
* to be cached in {@link AdvisedSupport#proxyMetadataCache}.
|
||||
* @since 6.1.3
|
||||
*/
|
||||
private static final class ProxiedInterfacesCache {
|
||||
|
||||
final Class<?>[] proxiedInterfaces;
|
||||
|
||||
final boolean equalsDefined;
|
||||
|
||||
final boolean hashCodeDefined;
|
||||
|
||||
ProxiedInterfacesCache(AdvisedSupport config) {
|
||||
this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(config, true);
|
||||
|
||||
// Find any {@link #equals} or {@link #hashCode} method that may be defined
|
||||
// on the supplied set of interfaces.
|
||||
boolean equalsDefined = false;
|
||||
boolean hashCodeDefined = false;
|
||||
for (Class<?> proxiedInterface : this.proxiedInterfaces) {
|
||||
Method[] methods = proxiedInterface.getDeclaredMethods();
|
||||
for (Method method : methods) {
|
||||
if (AopUtils.isEqualsMethod(method)) {
|
||||
equalsDefined = true;
|
||||
if (hashCodeDefined) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (AopUtils.isHashCodeMethod(method)) {
|
||||
hashCodeDefined = true;
|
||||
if (equalsDefined) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (equalsDefined && hashCodeDefined) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.equalsDefined = equalsDefined;
|
||||
this.hashCodeDefined = hashCodeDefined;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -58,6 +58,7 @@ import org.springframework.util.function.SingletonSupplier;
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @author He Bo
|
||||
* @author Sebastien Deleuze
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
@@ -292,7 +293,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
else if (Future.class.isAssignableFrom(returnType)) {
|
||||
return executor.submit(task);
|
||||
}
|
||||
else if (void.class == returnType) {
|
||||
else if (void.class == returnType || "kotlin.Unit".equals(returnType.getName())) {
|
||||
executor.submit(task);
|
||||
return null;
|
||||
}
|
||||
|
||||
+5
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,7 +32,6 @@ import org.springframework.core.Ordered;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* AOP Alliance {@code MethodInterceptor} that processes method invocations
|
||||
@@ -101,10 +100,9 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport imple
|
||||
@Nullable
|
||||
public Object invoke(final MethodInvocation invocation) throws Throwable {
|
||||
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
|
||||
Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
|
||||
final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
|
||||
final Method userMethod = BridgeMethodResolver.getMostSpecificMethod(invocation.getMethod(), targetClass);
|
||||
|
||||
AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
|
||||
AsyncTaskExecutor executor = determineAsyncExecutor(userMethod);
|
||||
if (executor == null) {
|
||||
throw new IllegalStateException(
|
||||
"No executor specified and no default executor set on AsyncExecutionInterceptor either");
|
||||
@@ -118,10 +116,10 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport imple
|
||||
}
|
||||
}
|
||||
catch (ExecutionException ex) {
|
||||
handleError(ex.getCause(), userDeclaredMethod, invocation.getArguments());
|
||||
handleError(ex.getCause(), userMethod, invocation.getArguments());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
handleError(ex, userDeclaredMethod, invocation.getArguments());
|
||||
handleError(ex, userMethod, invocation.getArguments());
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -199,12 +199,11 @@ public abstract class AopUtils {
|
||||
* @return the specific target method, or the original method if the
|
||||
* {@code targetClass} doesn't implement it or is {@code null}
|
||||
* @see org.springframework.util.ClassUtils#getMostSpecificMethod
|
||||
* @see org.springframework.core.BridgeMethodResolver#getMostSpecificMethod
|
||||
*/
|
||||
public static Method getMostSpecificMethod(Method method, @Nullable Class<?> targetClass) {
|
||||
Class<?> specificTargetClass = (targetClass != null ? ClassUtils.getUserClass(targetClass) : null);
|
||||
Method resolvedMethod = ClassUtils.getMostSpecificMethod(method, specificTargetClass);
|
||||
// If we are dealing with method with generic parameters, find the original method.
|
||||
return BridgeMethodResolver.findBridgedMethod(resolvedMethod);
|
||||
return BridgeMethodResolver.getMostSpecificMethod(method, specificTargetClass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,7 +52,7 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
|
||||
|
||||
/**
|
||||
* The class against which to match.
|
||||
* <p>Available for use in subclasses since 6.1.
|
||||
* @since 6.1
|
||||
*/
|
||||
protected final Class<?> clazz;
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,7 +29,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AspectJAdviceParameterNameDiscoverer}.
|
||||
* Tests for {@link AspectJAdviceParameterNameDiscoverer}.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Chris Beams
|
||||
|
||||
+23
-25
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,7 +23,6 @@ import java.util.Map;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.aspectj.weaver.tools.PointcutExpression;
|
||||
import org.aspectj.weaver.tools.PointcutPrimitive;
|
||||
import org.aspectj.weaver.tools.UnsupportedPointcutPrimitiveException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -66,7 +65,7 @@ public class AspectJExpressionPointcutTests {
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws NoSuchMethodException {
|
||||
public void setup() throws NoSuchMethodException {
|
||||
getAge = TestBean.class.getMethod("getAge");
|
||||
setAge = TestBean.class.getMethod("setAge", int.class);
|
||||
setSomeNumber = TestBean.class.getMethod("setSomeNumber", Number.class);
|
||||
@@ -247,14 +246,13 @@ public class AspectJExpressionPointcutTests {
|
||||
@Test
|
||||
public void testInvalidExpression() {
|
||||
String expression = "execution(void org.springframework.beans.testfixture.beans.TestBean.setSomeNumber(Number) && args(Double)";
|
||||
assertThatIllegalArgumentException().isThrownBy(
|
||||
getPointcut(expression)::getClassFilter); // call to getClassFilter forces resolution
|
||||
assertThatIllegalArgumentException().isThrownBy(getPointcut(expression)::getClassFilter); // call to getClassFilter forces resolution
|
||||
}
|
||||
|
||||
private TestBean getAdvisedProxy(String pointcutExpression, CallCountingInterceptor interceptor) {
|
||||
TestBean target = new TestBean();
|
||||
|
||||
Pointcut pointcut = getPointcut(pointcutExpression);
|
||||
AspectJExpressionPointcut pointcut = getPointcut(pointcutExpression);
|
||||
|
||||
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
|
||||
advisor.setAdvice(interceptor);
|
||||
@@ -278,40 +276,31 @@ public class AspectJExpressionPointcutTests {
|
||||
@Test
|
||||
public void testWithUnsupportedPointcutPrimitive() {
|
||||
String expression = "call(int org.springframework.beans.testfixture.beans.TestBean.getAge())";
|
||||
assertThatExceptionOfType(UnsupportedPointcutPrimitiveException.class).isThrownBy(() ->
|
||||
getPointcut(expression).getClassFilter()) // call to getClassFilter forces resolution...
|
||||
.satisfies(ex -> assertThat(ex.getUnsupportedPrimitive()).isEqualTo(PointcutPrimitive.CALL));
|
||||
assertThatExceptionOfType(UnsupportedPointcutPrimitiveException.class)
|
||||
.isThrownBy(() -> getPointcut(expression).getClassFilter()) // call to getClassFilter forces resolution...
|
||||
.satisfies(ex -> assertThat(ex.getUnsupportedPrimitive()).isEqualTo(PointcutPrimitive.CALL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAndSubstitution() {
|
||||
Pointcut pc = getPointcut("execution(* *(..)) and args(String)");
|
||||
PointcutExpression expr = ((AspectJExpressionPointcut) pc).getPointcutExpression();
|
||||
assertThat(expr.getPointcutExpression()).isEqualTo("execution(* *(..)) && args(String)");
|
||||
AspectJExpressionPointcut pc = getPointcut("execution(* *(..)) and args(String)");
|
||||
String expr = pc.getPointcutExpression().getPointcutExpression();
|
||||
assertThat(expr).isEqualTo("execution(* *(..)) && args(String)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleAndSubstitutions() {
|
||||
Pointcut pc = getPointcut("execution(* *(..)) and args(String) and this(Object)");
|
||||
PointcutExpression expr = ((AspectJExpressionPointcut) pc).getPointcutExpression();
|
||||
assertThat(expr.getPointcutExpression()).isEqualTo("execution(* *(..)) && args(String) && this(Object)");
|
||||
AspectJExpressionPointcut pc = getPointcut("execution(* *(..)) and args(String) and this(Object)");
|
||||
String expr = pc.getPointcutExpression().getPointcutExpression();
|
||||
assertThat(expr).isEqualTo("execution(* *(..)) && args(String) && this(Object)");
|
||||
}
|
||||
|
||||
private Pointcut getPointcut(String expression) {
|
||||
private AspectJExpressionPointcut getPointcut(String expression) {
|
||||
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
pointcut.setExpression(expression);
|
||||
return pointcut;
|
||||
}
|
||||
|
||||
|
||||
public static class OtherIOther implements IOther {
|
||||
|
||||
@Override
|
||||
public void absquatulate() {
|
||||
// Empty
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchGenericArgument() {
|
||||
String expression = "execution(* set*(java.util.List<org.springframework.beans.testfixture.beans.TestBean>) )";
|
||||
@@ -531,6 +520,15 @@ public class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
|
||||
public static class OtherIOther implements IOther {
|
||||
|
||||
@Override
|
||||
public void absquatulate() {
|
||||
// Empty
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class HasGeneric {
|
||||
|
||||
public void setFriends(List<TestBean> friends) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,7 +31,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link TypePatternClassFilter} class.
|
||||
* Tests for {@link TypePatternClassFilter}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Rick Evans
|
||||
|
||||
+40
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -42,26 +42,38 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
*/
|
||||
class ArgumentBindingTests {
|
||||
|
||||
@Test
|
||||
void bindingInPointcutUsedByAdvice() {
|
||||
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean());
|
||||
proxyFactory.addAspect(NamedPointcutWithArgs.class);
|
||||
|
||||
ITestBean proxiedTestBean = proxyFactory.getProxy();
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> proxiedTestBean.setName("enigma"))
|
||||
.withMessage("enigma");
|
||||
}
|
||||
|
||||
@Test
|
||||
void annotationArgumentNameBinding() {
|
||||
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TransactionalBean());
|
||||
proxyFactory.addAspect(PointcutWithAnnotationArgument.class);
|
||||
|
||||
ITransactionalBean proxiedTestBean = proxyFactory.getProxy();
|
||||
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(proxiedTestBean::doInTransaction)
|
||||
.withMessage("Invoked with @Transactional");
|
||||
.isThrownBy(proxiedTestBean::doInTransaction)
|
||||
.withMessage("Invoked with @Transactional");
|
||||
}
|
||||
|
||||
@Test
|
||||
void bindingInPointcutUsedByAdvice() {
|
||||
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean());
|
||||
proxyFactory.addAspect(NamedPointcutWithArgs.class);
|
||||
ITestBean proxiedTestBean = proxyFactory.getProxy();
|
||||
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> proxiedTestBean.setName("enigma"))
|
||||
.withMessage("enigma");
|
||||
}
|
||||
|
||||
@Test
|
||||
void bindingWithDynamicAdvice() {
|
||||
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean());
|
||||
proxyFactory.addAspect(DynamicPointcutWithArgs.class);
|
||||
ITestBean proxiedTestBean = proxyFactory.getProxy();
|
||||
|
||||
proxiedTestBean.applyName(1);
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> proxiedTestBean.applyName("enigma"))
|
||||
.withMessage("enigma");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -94,6 +106,7 @@ class ArgumentBindingTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mimics Spring's @Transactional annotation without actually introducing the dependency.
|
||||
*/
|
||||
@@ -101,16 +114,17 @@ class ArgumentBindingTests {
|
||||
@interface Transactional {
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
static class PointcutWithAnnotationArgument {
|
||||
|
||||
@Around(value = "execution(* org.springframework..*.*(..)) && @annotation(transactional)")
|
||||
@Around("execution(* org.springframework..*.*(..)) && @annotation(transactional)")
|
||||
public Object around(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable {
|
||||
throw new IllegalStateException("Invoked with @Transactional");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
static class NamedPointcutWithArgs {
|
||||
|
||||
@@ -121,7 +135,16 @@ class ArgumentBindingTests {
|
||||
public Object doAround(ProceedingJoinPoint pjp, String aString) throws Throwable {
|
||||
throw new IllegalArgumentException(aString);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Aspect("pertarget(execution(* *(..)))")
|
||||
static class DynamicPointcutWithArgs {
|
||||
|
||||
@Around("execution(* *(..)) && args(java.lang.String)")
|
||||
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
|
||||
throw new IllegalArgumentException(String.valueOf(pjp.getArgs()[0]));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,7 +30,7 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link DebugInterceptor} class.
|
||||
* Tests for {@link DebugInterceptor}.
|
||||
*
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,7 +29,7 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link SimpleTraceInterceptor} class.
|
||||
* Tests for {@link SimpleTraceInterceptor}.
|
||||
*
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,7 +24,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link DefaultScopedObject} class.
|
||||
* Tests for {@link DefaultScopedObject}.
|
||||
*
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,7 +22,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ScopedProxyUtils}.
|
||||
* Tests for {@link ScopedProxyUtils}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.1.10
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,7 +29,7 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ClassFilters}.
|
||||
* Tests for {@link ClassFilters}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,7 +24,7 @@ import org.springframework.beans.testfixture.beans.ITestBean;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link RootClassFilter}.
|
||||
* Tests for {@link RootClassFilter}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.1.10
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,7 +25,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AnnotationMatchingPointcut}.
|
||||
* Tests for {@link AnnotationMatchingPointcut}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.1.10
|
||||
|
||||
@@ -46,7 +46,7 @@ class AopUtilsKotlinTests {
|
||||
@Suppress("unused")
|
||||
suspend fun suspendingFunction(value: String): String {
|
||||
delay(1)
|
||||
return value;
|
||||
return value
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -41,7 +41,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.core.testfixture.TestGroup.LONG_RUNNING;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AnnotationAsyncExecutionAspect}.
|
||||
* Tests for {@link AnnotationAsyncExecutionAspect}.
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
* @author Stephane Nicoll
|
||||
@@ -221,7 +221,7 @@ public class AnnotationAsyncExecutionAspectTests {
|
||||
|
||||
@Async public Future<Integer> incrementReturningAFuture() {
|
||||
counter++;
|
||||
return new AsyncResult<Integer>(5);
|
||||
return new AsyncResult<>(5);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -256,7 +256,7 @@ public class AnnotationAsyncExecutionAspectTests {
|
||||
|
||||
public Future<Integer> incrementReturningAFuture() {
|
||||
counter++;
|
||||
return new AsyncResult<Integer>(5);
|
||||
return new AsyncResult<>(5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,12 +265,12 @@ public class AnnotationAsyncExecutionAspectTests {
|
||||
|
||||
@Async
|
||||
public Future<Thread> defaultWork() {
|
||||
return new AsyncResult<Thread>(Thread.currentThread());
|
||||
return new AsyncResult<>(Thread.currentThread());
|
||||
}
|
||||
|
||||
@Async("e1")
|
||||
public ListenableFuture<Thread> e1Work() {
|
||||
return new AsyncResult<Thread>(Thread.currentThread());
|
||||
return new AsyncResult<>(Thread.currentThread());
|
||||
}
|
||||
|
||||
@Async("e1")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.beans
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode
|
||||
@@ -30,22 +30,22 @@ import org.openjdk.jmh.annotations.State
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
open class KotlinBeanUtilsBenchmark {
|
||||
|
||||
private val noArgConstructor = TestClass1::class.java.getDeclaredConstructor()
|
||||
private val constructor = TestClass2::class.java.getDeclaredConstructor(Int::class.java, String::class.java)
|
||||
private val noArgConstructor = TestClass1::class.java.getDeclaredConstructor()
|
||||
private val constructor = TestClass2::class.java.getDeclaredConstructor(Int::class.java, String::class.java)
|
||||
|
||||
@Benchmark
|
||||
fun emptyConstructor(): Any {
|
||||
@Benchmark
|
||||
fun emptyConstructor(): Any {
|
||||
return BeanUtils.instantiateClass(noArgConstructor)
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun nonEmptyConstructor(): Any {
|
||||
@Benchmark
|
||||
fun nonEmptyConstructor(): Any {
|
||||
return BeanUtils.instantiateClass(constructor, 1, "str")
|
||||
}
|
||||
}
|
||||
|
||||
class TestClass1()
|
||||
class TestClass1
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
class TestClass2(int: Int, string: String)
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
class TestClass2(int: Int, string: String)
|
||||
}
|
||||
|
||||
|
||||
+7
-1
@@ -461,7 +461,9 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
ph.setValue(valueToApply);
|
||||
}
|
||||
catch (TypeMismatchException ex) {
|
||||
throw ex;
|
||||
if (!ph.setValueFallbackIfPossible(pv.getValue())) {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
PropertyChangeEvent propertyChangeEvent = new PropertyChangeEvent(
|
||||
@@ -1061,6 +1063,10 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
public abstract Object getValue() throws Exception;
|
||||
|
||||
public abstract void setValue(@Nullable Object value) throws Exception;
|
||||
|
||||
public boolean setValueFallbackIfPossible(@Nullable Object value) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ package org.springframework.beans;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -278,6 +280,22 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
ReflectionUtils.makeAccessible(writeMethod);
|
||||
writeMethod.invoke(getWrappedInstance(), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setValueFallbackIfPossible(@Nullable Object value) {
|
||||
Method writeMethod = this.pd.getWriteMethodFallback(value != null ? value.getClass() : null);
|
||||
if (writeMethod != null) {
|
||||
ReflectionUtils.makeAccessible(writeMethod);
|
||||
try {
|
||||
writeMethod.invoke(getWrappedInstance(), value);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LogFactory.getLog(BeanPropertyHandler.class).debug("Write method fallback failed", ex);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -524,20 +524,7 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
|
||||
@Override
|
||||
public int compare(PropertyDescriptor desc1, PropertyDescriptor desc2) {
|
||||
String left = desc1.getName();
|
||||
String right = desc2.getName();
|
||||
byte[] leftBytes = left.getBytes();
|
||||
byte[] rightBytes = right.getBytes();
|
||||
for (int i = 0; i < left.length(); i++) {
|
||||
if (right.length() == i) {
|
||||
return 1;
|
||||
}
|
||||
int result = leftBytes[i] - rightBytes[i];
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return left.length() - right.length();
|
||||
return desc1.getName().compareTo(desc2.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-5
@@ -54,7 +54,9 @@ final class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor {
|
||||
private final Method writeMethod;
|
||||
|
||||
@Nullable
|
||||
private volatile Set<Method> ambiguousWriteMethods;
|
||||
private Set<Method> ambiguousWriteMethods;
|
||||
|
||||
private volatile boolean ambiguousWriteMethodsLogged;
|
||||
|
||||
@Nullable
|
||||
private MethodParameter writeMethodParameter;
|
||||
@@ -147,16 +149,28 @@ final class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor {
|
||||
|
||||
public Method getWriteMethodForActualAccess() {
|
||||
Assert.state(this.writeMethod != null, "No write method available");
|
||||
Set<Method> ambiguousCandidates = this.ambiguousWriteMethods;
|
||||
if (ambiguousCandidates != null) {
|
||||
this.ambiguousWriteMethods = null;
|
||||
if (this.ambiguousWriteMethods != null && !this.ambiguousWriteMethodsLogged) {
|
||||
this.ambiguousWriteMethodsLogged = true;
|
||||
LogFactory.getLog(GenericTypeAwarePropertyDescriptor.class).debug("Non-unique JavaBean property '" +
|
||||
getName() + "' being accessed! Ambiguous write methods found next to actually used [" +
|
||||
this.writeMethod + "]: " + ambiguousCandidates);
|
||||
this.writeMethod + "]: " + this.ambiguousWriteMethods);
|
||||
}
|
||||
return this.writeMethod;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Method getWriteMethodFallback(@Nullable Class<?> valueType) {
|
||||
if (this.ambiguousWriteMethods != null) {
|
||||
for (Method method : this.ambiguousWriteMethods) {
|
||||
Class<?> paramType = method.getParameterTypes()[0];
|
||||
if (valueType != null ? paramType.isAssignableFrom(valueType) : !paramType.isPrimitive()) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public MethodParameter getWriteMethodParameter() {
|
||||
Assert.state(this.writeMethodParameter != null, "No write method available");
|
||||
return this.writeMethodParameter;
|
||||
|
||||
@@ -170,6 +170,8 @@ public interface BeanFactory {
|
||||
* Return an instance, which may be shared or independent, of the specified bean.
|
||||
* <p>Allows for specifying explicit constructor arguments / factory method arguments,
|
||||
* overriding the specified default arguments (if any) in the bean definition.
|
||||
* Note that the provided arguments need to match a specific candidate constructor /
|
||||
* factory method in the order of declared parameters.
|
||||
* @param name the name of the bean to retrieve
|
||||
* @param args arguments to use when creating a bean instance using explicit arguments
|
||||
* (only applied when creating a new instance as opposed to retrieving an existing one)
|
||||
@@ -202,6 +204,8 @@ public interface BeanFactory {
|
||||
* Return an instance, which may be shared or independent, of the specified bean.
|
||||
* <p>Allows for specifying explicit constructor arguments / factory method arguments,
|
||||
* overriding the specified default arguments (if any) in the bean definition.
|
||||
* Note that the provided arguments need to match a specific candidate constructor /
|
||||
* factory method in the order of declared parameters.
|
||||
* <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
|
||||
* but may also be translated into a conventional by-name lookup based on the name
|
||||
* of the given type. For more extensive retrieval operations across sets of beans,
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -517,9 +517,9 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
}
|
||||
|
||||
/**
|
||||
* 'Native' processing method for direct calls with an arbitrary target instance,
|
||||
* resolving all of its fields and methods which are annotated with one of the
|
||||
* configured 'autowired' annotation types.
|
||||
* <em>Native</em> processing method for direct calls with an arbitrary target
|
||||
* instance, resolving all of its fields and methods which are annotated with
|
||||
* one of the configured 'autowired' annotation types.
|
||||
* @param bean the target instance to process
|
||||
* @throws BeanCreationException if autowiring failed
|
||||
* @see #setAutowiredAnnotationTypes(Set)
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -367,7 +367,7 @@ class BeanDefinitionPropertiesCodeGenerator {
|
||||
* @param castNecessary whether a cast is necessary
|
||||
* @param castType the type to cast to
|
||||
* @param valueCode the code for the value
|
||||
* @return the existing value or a form of {@code (CastType) valueCode} if a
|
||||
* @return the existing value or a form of {@code (castType) valueCode} if a
|
||||
* cast is necessary
|
||||
*/
|
||||
private CodeBlock castIfNecessary(boolean castNecessary, Class<?> castType, CodeBlock valueCode) {
|
||||
|
||||
+2
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -98,9 +98,7 @@ public final class ParseState {
|
||||
for (ParseState.Entry entry : this.state) {
|
||||
if (i > 0) {
|
||||
sb.append('\n');
|
||||
for (int j = 0; j < i; j++) {
|
||||
sb.append('\t');
|
||||
}
|
||||
sb.append("\t".repeat(i));
|
||||
sb.append("-> ");
|
||||
}
|
||||
sb.append(entry);
|
||||
|
||||
+5
-5
@@ -92,10 +92,10 @@ import org.springframework.util.function.ThrowingSupplier;
|
||||
* Supports autowiring constructors, properties by name, and properties by type.
|
||||
*
|
||||
* <p>The main template method to be implemented by subclasses is
|
||||
* {@link #resolveDependency(DependencyDescriptor, String, Set, TypeConverter)},
|
||||
* used for autowiring by type. In case of a factory which is capable of searching
|
||||
* its bean definitions, matching beans will typically be implemented through such
|
||||
* a search. For other factory styles, simplified matching algorithms can be implemented.
|
||||
* {@link #resolveDependency(DependencyDescriptor, String, Set, TypeConverter)}, used for
|
||||
* autowiring. In case of a {@link org.springframework.beans.factory.ListableBeanFactory}
|
||||
* which is capable of searching its bean definitions, matching beans will typically be
|
||||
* implemented through such a search. Otherwise, simplified matching can be implemented.
|
||||
*
|
||||
* <p>Note that this class does <i>not</i> assume or implement bean definition
|
||||
* registry capabilities. See {@link DefaultListableBeanFactory} for an implementation
|
||||
@@ -653,7 +653,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
// Apply SmartInstantiationAwareBeanPostProcessors to predict the
|
||||
// eventual type after a before-instantiation shortcut.
|
||||
if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
|
||||
boolean matchingOnlyFactoryBean = typesToMatch.length == 1 && typesToMatch[0] == FactoryBean.class;
|
||||
boolean matchingOnlyFactoryBean = (typesToMatch.length == 1 && typesToMatch[0] == FactoryBean.class);
|
||||
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
|
||||
Class<?> predicted = bp.predictBeanType(targetType, beanName);
|
||||
if (predicted != null &&
|
||||
|
||||
+1
-1
@@ -581,7 +581,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
*/
|
||||
@Override
|
||||
public boolean isLazyInit() {
|
||||
return (this.lazyInit != null && this.lazyInit.booleanValue());
|
||||
return (this.lazyInit != null && this.lazyInit);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -59,7 +59,7 @@ public class BeanDefinitionDefaults {
|
||||
* @return whether to apply lazy-init semantics ({@code false} by default)
|
||||
*/
|
||||
public boolean isLazyInit() {
|
||||
return (this.lazyInit != null && this.lazyInit.booleanValue());
|
||||
return (this.lazyInit != null && this.lazyInit);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-5
@@ -121,11 +121,7 @@ class ConstructorResolver {
|
||||
|
||||
/**
|
||||
* "autowire constructor" (with constructor arguments by type) behavior.
|
||||
* Also applied if explicit constructor argument values are specified,
|
||||
* matching all remaining arguments with beans from the bean factory.
|
||||
* <p>This corresponds to constructor injection: In this mode, a Spring
|
||||
* bean factory is able to host components that expect constructor-based
|
||||
* dependency resolution.
|
||||
* Also applied if explicit constructor argument values are specified.
|
||||
* @param beanName the name of the bean
|
||||
* @param mbd the merged bean definition for the bean
|
||||
* @param chosenCtors chosen candidate constructors (or {@code null} if none)
|
||||
|
||||
+13
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -294,7 +294,7 @@ abstract class AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void setNestedPropertyPolymorphic() throws Exception {
|
||||
void setNestedPropertyPolymorphic() {
|
||||
ITestBean target = new TestBean("rod", 31);
|
||||
ITestBean kerry = new Employee();
|
||||
|
||||
@@ -316,7 +316,7 @@ abstract class AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void setAnotherNestedProperty() throws Exception {
|
||||
void setAnotherNestedProperty() {
|
||||
ITestBean target = new TestBean("rod", 31);
|
||||
ITestBean kerry = new TestBean("kerry", 0);
|
||||
|
||||
@@ -386,7 +386,7 @@ abstract class AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void setAnotherPropertyIntermediatePropertyIsNull() throws Exception {
|
||||
void setAnotherPropertyIntermediatePropertyIsNull() {
|
||||
ITestBean target = new TestBean("rod", 31);
|
||||
AbstractPropertyAccessor accessor = createAccessor(target);
|
||||
assertThatExceptionOfType(NullValueInNestedPathException.class).isThrownBy(() ->
|
||||
@@ -406,7 +406,6 @@ abstract class AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void setPropertyIntermediateListIsNullWithAutoGrow() {
|
||||
Foo target = new Foo();
|
||||
AbstractPropertyAccessor accessor = createAccessor(target);
|
||||
@@ -553,7 +552,7 @@ abstract class AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void setStringPropertyWithCustomEditor() throws Exception {
|
||||
void setStringPropertyWithCustomEditor() {
|
||||
TestBean target = new TestBean();
|
||||
AbstractPropertyAccessor accessor = createAccessor(target);
|
||||
accessor.registerCustomEditor(String.class, "name", new PropertyEditorSupport() {
|
||||
@@ -724,7 +723,7 @@ abstract class AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void setPropertiesProperty() throws Exception {
|
||||
void setPropertiesProperty() {
|
||||
PropsTester target = new PropsTester();
|
||||
AbstractPropertyAccessor accessor = createAccessor(target);
|
||||
accessor.setPropertyValue("name", "ptest");
|
||||
@@ -742,7 +741,7 @@ abstract class AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void setStringArrayProperty() throws Exception {
|
||||
void setStringArrayProperty() {
|
||||
PropsTester target = new PropsTester();
|
||||
AbstractPropertyAccessor accessor = createAccessor(target);
|
||||
|
||||
@@ -767,7 +766,7 @@ abstract class AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void setStringArrayPropertyWithCustomStringEditor() throws Exception {
|
||||
void setStringArrayPropertyWithCustomStringEditor() {
|
||||
PropsTester target = new PropsTester();
|
||||
AbstractPropertyAccessor accessor = createAccessor(target);
|
||||
accessor.registerCustomEditor(String.class, "stringArray", new PropertyEditorSupport() {
|
||||
@@ -796,7 +795,7 @@ abstract class AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void setStringArrayPropertyWithStringSplitting() throws Exception {
|
||||
void setStringArrayPropertyWithStringSplitting() {
|
||||
PropsTester target = new PropsTester();
|
||||
AbstractPropertyAccessor accessor = createAccessor(target);
|
||||
accessor.useConfigValueEditors();
|
||||
@@ -805,7 +804,7 @@ abstract class AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void setStringArrayPropertyWithCustomStringDelimiter() throws Exception {
|
||||
void setStringArrayPropertyWithCustomStringDelimiter() {
|
||||
PropsTester target = new PropsTester();
|
||||
AbstractPropertyAccessor accessor = createAccessor(target);
|
||||
accessor.registerCustomEditor(String[].class, "stringArray", new StringArrayPropertyEditor("-"));
|
||||
@@ -814,7 +813,7 @@ abstract class AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void setStringArrayWithAutoGrow() throws Exception {
|
||||
void setStringArrayWithAutoGrow() {
|
||||
StringArrayBean target = new StringArrayBean();
|
||||
AbstractPropertyAccessor accessor = createAccessor(target);
|
||||
accessor.setAutoGrowNestedPaths(true);
|
||||
@@ -888,7 +887,7 @@ abstract class AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void setIntArrayPropertyWithStringSplitting() throws Exception {
|
||||
void setIntArrayPropertyWithStringSplitting() {
|
||||
PropsTester target = new PropsTester();
|
||||
AbstractPropertyAccessor accessor = createAccessor(target);
|
||||
accessor.useConfigValueEditors();
|
||||
@@ -943,7 +942,7 @@ abstract class AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void setPrimitiveArrayPropertyWithAutoGrow() throws Exception {
|
||||
void setPrimitiveArrayPropertyWithAutoGrow() {
|
||||
PrimitiveArrayBean target = new PrimitiveArrayBean();
|
||||
AbstractPropertyAccessor accessor = createAccessor(target);
|
||||
accessor.setAutoGrowNestedPaths(true);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,7 +52,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
import static org.assertj.core.api.SoftAssertions.assertSoftly;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link BeanUtils}.
|
||||
* Tests for {@link BeanUtils}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
|
||||
+21
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,7 +30,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public class BeanWrapperAutoGrowingTests {
|
||||
class BeanWrapperAutoGrowingTests {
|
||||
|
||||
private final Bean bean = new Bean();
|
||||
|
||||
@@ -38,43 +38,43 @@ public class BeanWrapperAutoGrowingTests {
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
void setup() {
|
||||
wrapper.setAutoGrowNestedPaths(true);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getPropertyValueNullValueInNestedPath() {
|
||||
void getPropertyValueNullValueInNestedPath() {
|
||||
assertThat(wrapper.getPropertyValue("nested.prop")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPropertyValueNullValueInNestedPath() {
|
||||
void setPropertyValueNullValueInNestedPath() {
|
||||
wrapper.setPropertyValue("nested.prop", "test");
|
||||
assertThat(bean.getNested().getProp()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyValueNullValueInNestedPathNoDefaultConstructor() {
|
||||
void getPropertyValueNullValueInNestedPathNoDefaultConstructor() {
|
||||
assertThatExceptionOfType(NullValueInNestedPathException.class).isThrownBy(() ->
|
||||
wrapper.getPropertyValue("nestedNoConstructor.prop"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyValueAutoGrowArray() {
|
||||
void getPropertyValueAutoGrowArray() {
|
||||
assertNotNull(wrapper.getPropertyValue("array[0]"));
|
||||
assertThat(bean.getArray()).hasSize(1);
|
||||
assertThat(bean.getArray()[0]).isInstanceOf(Bean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPropertyValueAutoGrowArray() {
|
||||
void setPropertyValueAutoGrowArray() {
|
||||
wrapper.setPropertyValue("array[0].prop", "test");
|
||||
assertThat(bean.getArray()[0].getProp()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyValueAutoGrowArrayBySeveralElements() {
|
||||
void getPropertyValueAutoGrowArrayBySeveralElements() {
|
||||
assertNotNull(wrapper.getPropertyValue("array[4]"));
|
||||
assertThat(bean.getArray()).hasSize(5);
|
||||
assertThat(bean.getArray()[0]).isInstanceOf(Bean.class);
|
||||
@@ -89,21 +89,21 @@ public class BeanWrapperAutoGrowingTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyValueAutoGrow2dArray() {
|
||||
void getPropertyValueAutoGrow2dArray() {
|
||||
assertThat(wrapper.getPropertyValue("multiArray[0][0]")).isNotNull();
|
||||
assertThat(bean.getMultiArray()[0]).hasSize(1);
|
||||
assertThat(bean.getMultiArray()[0][0]).isInstanceOf(Bean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyValueAutoGrow3dArray() {
|
||||
void getPropertyValueAutoGrow3dArray() {
|
||||
assertThat(wrapper.getPropertyValue("threeDimensionalArray[1][2][3]")).isNotNull();
|
||||
assertThat(bean.getThreeDimensionalArray()[1]).hasNumberOfRows(3);
|
||||
assertThat(bean.getThreeDimensionalArray()[1][2][3]).isInstanceOf(Bean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPropertyValueAutoGrow2dArray() {
|
||||
void setPropertyValueAutoGrow2dArray() {
|
||||
Bean newBean = new Bean();
|
||||
newBean.setProp("enigma");
|
||||
wrapper.setPropertyValue("multiArray[2][3]", newBean);
|
||||
@@ -113,7 +113,7 @@ public class BeanWrapperAutoGrowingTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPropertyValueAutoGrow3dArray() {
|
||||
void setPropertyValueAutoGrow3dArray() {
|
||||
Bean newBean = new Bean();
|
||||
newBean.setProp("enigma");
|
||||
wrapper.setPropertyValue("threeDimensionalArray[2][3][4]", newBean);
|
||||
@@ -123,20 +123,20 @@ public class BeanWrapperAutoGrowingTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyValueAutoGrowList() {
|
||||
void getPropertyValueAutoGrowList() {
|
||||
assertNotNull(wrapper.getPropertyValue("list[0]"));
|
||||
assertThat(bean.getList()).hasSize(1);
|
||||
assertThat(bean.getList()).element(0).isInstanceOf(Bean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPropertyValueAutoGrowList() {
|
||||
void setPropertyValueAutoGrowList() {
|
||||
wrapper.setPropertyValue("list[0].prop", "test");
|
||||
assertThat(bean.getList().get(0).getProp()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyValueAutoGrowListBySeveralElements() {
|
||||
void getPropertyValueAutoGrowListBySeveralElements() {
|
||||
assertNotNull(wrapper.getPropertyValue("list[4]"));
|
||||
assertThat(bean.getList()).hasSize(5);
|
||||
assertThat(bean.getList()).element(0).isInstanceOf(Bean.class);
|
||||
@@ -151,7 +151,7 @@ public class BeanWrapperAutoGrowingTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyValueAutoGrowListFailsAgainstLimit() {
|
||||
void getPropertyValueAutoGrowListFailsAgainstLimit() {
|
||||
wrapper.setAutoGrowCollectionLimit(2);
|
||||
assertThatExceptionOfType(InvalidPropertyException.class).isThrownBy(() ->
|
||||
wrapper.getPropertyValue("list[4]"))
|
||||
@@ -159,26 +159,26 @@ public class BeanWrapperAutoGrowingTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyValueAutoGrowMultiDimensionalList() {
|
||||
void getPropertyValueAutoGrowMultiDimensionalList() {
|
||||
assertNotNull(wrapper.getPropertyValue("multiList[0][0]"));
|
||||
assertThat(bean.getMultiList()).element(0).asList().hasSize(1);
|
||||
assertThat(bean.getMultiList().get(0)).element(0).isInstanceOf(Bean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyValueAutoGrowListNotParameterized() {
|
||||
void getPropertyValueAutoGrowListNotParameterized() {
|
||||
assertThatExceptionOfType(InvalidPropertyException.class).isThrownBy(() ->
|
||||
wrapper.getPropertyValue("listNotParameterized[0]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPropertyValueAutoGrowMap() {
|
||||
void setPropertyValueAutoGrowMap() {
|
||||
wrapper.setPropertyValue("map[A]", new Bean());
|
||||
assertThat(bean.getMap().get("A")).isInstanceOf(Bean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setNestedPropertyValueAutoGrowMap() {
|
||||
void setNestedPropertyValueAutoGrowMap() {
|
||||
wrapper.setPropertyValue("map[A].nested", new Bean());
|
||||
assertThat(bean.getMap().get("A").getNested()).isInstanceOf(Bean.class);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,10 +31,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class BeanWrapperEnumTests {
|
||||
class BeanWrapperEnumTests {
|
||||
|
||||
@Test
|
||||
public void testCustomEnum() {
|
||||
void testCustomEnum() {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("customEnum", "VALUE_1");
|
||||
@@ -42,7 +42,7 @@ public class BeanWrapperEnumTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomEnumWithNull() {
|
||||
void testCustomEnumWithNull() {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("customEnum", null);
|
||||
@@ -50,7 +50,7 @@ public class BeanWrapperEnumTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomEnumWithEmptyString() {
|
||||
void testCustomEnumWithEmptyString() {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("customEnum", "");
|
||||
@@ -58,7 +58,7 @@ public class BeanWrapperEnumTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomEnumArrayWithSingleValue() {
|
||||
void testCustomEnumArrayWithSingleValue() {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("customEnumArray", "VALUE_1");
|
||||
@@ -67,7 +67,7 @@ public class BeanWrapperEnumTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomEnumArrayWithMultipleValues() {
|
||||
void testCustomEnumArrayWithMultipleValues() {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("customEnumArray", new String[] {"VALUE_1", "VALUE_2"});
|
||||
@@ -77,7 +77,7 @@ public class BeanWrapperEnumTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomEnumArrayWithMultipleValuesAsCsv() {
|
||||
void testCustomEnumArrayWithMultipleValuesAsCsv() {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("customEnumArray", "VALUE_1,VALUE_2");
|
||||
@@ -87,7 +87,7 @@ public class BeanWrapperEnumTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomEnumSetWithSingleValue() {
|
||||
void testCustomEnumSetWithSingleValue() {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("customEnumSet", "VALUE_1");
|
||||
@@ -96,7 +96,7 @@ public class BeanWrapperEnumTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomEnumSetWithMultipleValues() {
|
||||
void testCustomEnumSetWithMultipleValues() {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("customEnumSet", new String[] {"VALUE_1", "VALUE_2"});
|
||||
@@ -106,7 +106,7 @@ public class BeanWrapperEnumTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomEnumSetWithMultipleValuesAsCsv() {
|
||||
void testCustomEnumSetWithMultipleValuesAsCsv() {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("customEnumSet", "VALUE_1,VALUE_2");
|
||||
@@ -116,7 +116,7 @@ public class BeanWrapperEnumTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomEnumSetWithGetterSetterMismatch() {
|
||||
void testCustomEnumSetWithGetterSetterMismatch() {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("customEnumSetMismatch", new String[] {"VALUE_1", "VALUE_2"});
|
||||
@@ -126,7 +126,7 @@ public class BeanWrapperEnumTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStandardEnumSetWithMultipleValues() {
|
||||
void testStandardEnumSetWithMultipleValues() {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setConversionService(new DefaultConversionService());
|
||||
@@ -138,7 +138,7 @@ public class BeanWrapperEnumTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStandardEnumSetWithAutoGrowing() {
|
||||
void testStandardEnumSetWithAutoGrowing() {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setAutoGrowNestedPaths(true);
|
||||
@@ -148,7 +148,7 @@ public class BeanWrapperEnumTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStandardEnumMapWithMultipleValues() {
|
||||
void testStandardEnumMapWithMultipleValues() {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setConversionService(new DefaultConversionService());
|
||||
@@ -163,7 +163,7 @@ public class BeanWrapperEnumTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStandardEnumMapWithAutoGrowing() {
|
||||
void testStandardEnumMapWithAutoGrowing() {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setAutoGrowNestedPaths(true);
|
||||
@@ -174,7 +174,7 @@ public class BeanWrapperEnumTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonPublicEnum() {
|
||||
void testNonPublicEnum() {
|
||||
NonPublicEnumHolder holder = new NonPublicEnumHolder();
|
||||
BeanWrapper bw = new BeanWrapperImpl(holder);
|
||||
bw.setPropertyValue("nonPublicEnum", "VALUE_1");
|
||||
@@ -184,7 +184,7 @@ public class BeanWrapperEnumTests {
|
||||
|
||||
enum NonPublicEnum {
|
||||
|
||||
VALUE_1, VALUE_2;
|
||||
VALUE_1, VALUE_2
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -201,7 +201,7 @@ class BeanWrapperGenericsTests {
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("listOfLists[0][0]", 5);
|
||||
assertThat(bw.getPropertyValue("listOfLists[0][0]")).isEqualTo(5);
|
||||
assertThat(gb.getListOfLists().get(0)).element(0).isEqualTo(5);
|
||||
assertThat(gb.getListOfLists()).singleElement().asList().containsExactly(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -213,7 +213,7 @@ class BeanWrapperGenericsTests {
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("listOfLists[0][0]", "5");
|
||||
assertThat(bw.getPropertyValue("listOfLists[0][0]")).isEqualTo(5);
|
||||
assertThat(gb.getListOfLists().get(0)).element(0).isEqualTo(5);
|
||||
assertThat(gb.getListOfLists()).singleElement().asList().containsExactly(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -298,7 +298,7 @@ class BeanWrapperGenericsTests {
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("mapOfLists[1][0]", 5);
|
||||
assertThat(bw.getPropertyValue("mapOfLists[1][0]")).isEqualTo(5);
|
||||
assertThat(gb.getMapOfLists().get(1)).element(0).isEqualTo(5);
|
||||
assertThat(gb.getMapOfLists().get(1)).containsExactly(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -310,7 +310,7 @@ class BeanWrapperGenericsTests {
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("mapOfLists[1][0]", "5");
|
||||
assertThat(bw.getPropertyValue("mapOfLists[1][0]")).isEqualTo(5);
|
||||
assertThat(gb.getMapOfLists().get(1)).element(0).isEqualTo(5);
|
||||
assertThat(gb.getMapOfLists().get(1)).containsExactly(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -516,8 +516,7 @@ class BeanWrapperGenericsTests {
|
||||
bw.setPropertyValue("genericProperty", "10");
|
||||
bw.setPropertyValue("genericListProperty", new String[] {"20", "30"});
|
||||
assertThat(gb.getGenericProperty()).isEqualTo(10);
|
||||
assertThat(gb.getGenericListProperty()).element(0).isEqualTo(20);
|
||||
assertThat(gb.getGenericListProperty()).element(1).isEqualTo(30);
|
||||
assertThat(gb.getGenericListProperty()).containsExactly(20, 30);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -526,9 +525,9 @@ class BeanWrapperGenericsTests {
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("genericProperty", "10");
|
||||
bw.setPropertyValue("genericListProperty", new String[] {"20", "30"});
|
||||
assertThat(gb.getGenericProperty()).element(0).isEqualTo(10);
|
||||
assertThat(gb.getGenericListProperty().get(0)).element(0).isEqualTo(20);
|
||||
assertThat(gb.getGenericListProperty().get(1)).element(0).isEqualTo(30);
|
||||
assertThat(gb.getGenericProperty()).containsExactly(10);
|
||||
assertThat(gb.getGenericListProperty().get(0)).containsExactly(20);
|
||||
assertThat(gb.getGenericListProperty().get(1)).containsExactly(30);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.beans;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -172,10 +173,26 @@ class BeanWrapperTests extends AbstractPropertyAccessorTests {
|
||||
void setterOverload() {
|
||||
SetterOverload target = new SetterOverload();
|
||||
BeanWrapper accessor = createAccessor(target);
|
||||
|
||||
accessor.setPropertyValue("object", "a String");
|
||||
assertThat(target.value).isEqualTo("a String");
|
||||
assertThat(target.getObject()).isEqualTo("a String");
|
||||
assertThat(accessor.getPropertyValue("object")).isEqualTo("a String");
|
||||
|
||||
accessor.setPropertyValue("object", 1000);
|
||||
assertThat(target.value).isEqualTo("1000");
|
||||
assertThat(target.getObject()).isEqualTo("1000");
|
||||
assertThat(accessor.getPropertyValue("object")).isEqualTo("1000");
|
||||
|
||||
accessor.setPropertyValue("value", 1000);
|
||||
assertThat(target.value).isEqualTo("1000i");
|
||||
assertThat(target.getObject()).isEqualTo("1000i");
|
||||
assertThat(accessor.getPropertyValue("object")).isEqualTo("1000i");
|
||||
|
||||
accessor.setPropertyValue("value", Duration.ofSeconds(1000));
|
||||
assertThat(target.value).isEqualTo("1000s");
|
||||
assertThat(target.getObject()).isEqualTo("1000s");
|
||||
assertThat(accessor.getPropertyValue("object")).isEqualTo("1000s");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -382,7 +399,7 @@ class BeanWrapperTests extends AbstractPropertyAccessorTests {
|
||||
public String value;
|
||||
|
||||
public void setObject(Integer length) {
|
||||
this.value = length.toString();
|
||||
this.value = length + "i";
|
||||
}
|
||||
|
||||
public void setObject(String object) {
|
||||
@@ -392,6 +409,14 @@ class BeanWrapperTests extends AbstractPropertyAccessorTests {
|
||||
public String getObject() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(int length) {
|
||||
this.value = length + "i";
|
||||
}
|
||||
|
||||
public void setValue(Duration duration) {
|
||||
this.value = duration.getSeconds() + "s";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -403,7 +428,7 @@ class BeanWrapperTests extends AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,10 +32,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Chris Beams
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class CachedIntrospectionResultsTests {
|
||||
class CachedIntrospectionResultsTests {
|
||||
|
||||
@Test
|
||||
public void acceptAndClearClassLoader() throws Exception {
|
||||
void acceptAndClearClassLoader() throws Exception {
|
||||
BeanWrapper bw = new BeanWrapperImpl(TestBean.class);
|
||||
assertThat(bw.isWritableProperty("name")).isTrue();
|
||||
assertThat(bw.isWritableProperty("age")).isTrue();
|
||||
@@ -56,7 +56,7 @@ public class CachedIntrospectionResultsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearClassLoaderForSystemClassLoader() throws Exception {
|
||||
void clearClassLoaderForSystemClassLoader() {
|
||||
BeanUtils.getPropertyDescriptors(ArrayList.class);
|
||||
assertThat(CachedIntrospectionResults.strongClassCache.containsKey(ArrayList.class)).isTrue();
|
||||
CachedIntrospectionResults.clearClassLoader(ArrayList.class.getClassLoader());
|
||||
@@ -64,7 +64,7 @@ public class CachedIntrospectionResultsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldUseExtendedBeanInfoWhenApplicable() throws NoSuchMethodException, SecurityException {
|
||||
void shouldUseExtendedBeanInfoWhenApplicable() throws NoSuchMethodException, SecurityException {
|
||||
// given a class with a non-void returning setter method
|
||||
@SuppressWarnings("unused")
|
||||
class C {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -97,7 +97,7 @@ class ConcurrentBeanWrapperTests {
|
||||
// ByteArrayOutputStream does not throw
|
||||
// any IOException
|
||||
}
|
||||
String value = new String(buffer.toByteArray());
|
||||
String value = buffer.toString();
|
||||
|
||||
BeanWrapperImpl wrapper = new BeanWrapperImpl(bean);
|
||||
wrapper.setPropertyValue("properties", value);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -558,7 +558,7 @@ class ExtendedBeanInfoTests {
|
||||
* @see #cornerSpr9702()
|
||||
*/
|
||||
@Test
|
||||
void cornerSpr10111() throws Exception {
|
||||
void cornerSpr10111() {
|
||||
assertThatNoException().isThrownBy(() -> new ExtendedBeanInfo(Introspector.getBeanInfo(BigDecimal.class)));
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,22 +21,22 @@ import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PropertyAccessorUtils}.
|
||||
* Tests for {@link PropertyAccessorUtils}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class PropertyAccessorUtilsTests {
|
||||
class PropertyAccessorUtilsTests {
|
||||
|
||||
@Test
|
||||
public void getPropertyName() {
|
||||
void getPropertyName() {
|
||||
assertThat(PropertyAccessorUtils.getPropertyName("")).isEmpty();
|
||||
assertThat(PropertyAccessorUtils.getPropertyName("[user]")).isEmpty();
|
||||
assertThat(PropertyAccessorUtils.getPropertyName("user")).isEqualTo("user");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNestedOrIndexedProperty() {
|
||||
void isNestedOrIndexedProperty() {
|
||||
assertThat(PropertyAccessorUtils.isNestedOrIndexedProperty(null)).isFalse();
|
||||
assertThat(PropertyAccessorUtils.isNestedOrIndexedProperty("")).isFalse();
|
||||
assertThat(PropertyAccessorUtils.isNestedOrIndexedProperty("user")).isFalse();
|
||||
@@ -46,19 +46,19 @@ public class PropertyAccessorUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFirstNestedPropertySeparatorIndex() {
|
||||
void getFirstNestedPropertySeparatorIndex() {
|
||||
assertThat(PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex("[user]")).isEqualTo(-1);
|
||||
assertThat(PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex("user.name")).isEqualTo(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLastNestedPropertySeparatorIndex() {
|
||||
void getLastNestedPropertySeparatorIndex() {
|
||||
assertThat(PropertyAccessorUtils.getLastNestedPropertySeparatorIndex("[user]")).isEqualTo(-1);
|
||||
assertThat(PropertyAccessorUtils.getLastNestedPropertySeparatorIndex("user.address.street")).isEqualTo(12);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesProperty() {
|
||||
void matchesProperty() {
|
||||
assertThat(PropertyAccessorUtils.matchesProperty("user", "email")).isFalse();
|
||||
assertThat(PropertyAccessorUtils.matchesProperty("username", "user")).isFalse();
|
||||
assertThat(PropertyAccessorUtils.matchesProperty("admin[user]", "user")).isFalse();
|
||||
@@ -68,7 +68,7 @@ public class PropertyAccessorUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canonicalPropertyName() {
|
||||
void canonicalPropertyName() {
|
||||
assertThat(PropertyAccessorUtils.canonicalPropertyName(null)).isEmpty();
|
||||
assertThat(PropertyAccessorUtils.canonicalPropertyName("map")).isEqualTo("map");
|
||||
assertThat(PropertyAccessorUtils.canonicalPropertyName("map[key1]")).isEqualTo("map[key1]");
|
||||
@@ -82,7 +82,7 @@ public class PropertyAccessorUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canonicalPropertyNames() {
|
||||
void canonicalPropertyNames() {
|
||||
assertThat(PropertyAccessorUtils.canonicalPropertyNames(null)).isNull();
|
||||
|
||||
String[] original =
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,28 +30,28 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class PropertyMatchesTests {
|
||||
class PropertyMatchesTests {
|
||||
|
||||
@Test
|
||||
public void simpleBeanPropertyTypo() {
|
||||
void simpleBeanPropertyTypo() {
|
||||
PropertyMatches matches = PropertyMatches.forProperty("naem", SampleBeanProperties.class);
|
||||
assertThat(matches.getPossibleMatches()).contains("name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void complexBeanPropertyTypo() {
|
||||
void complexBeanPropertyTypo() {
|
||||
PropertyMatches matches = PropertyMatches.forProperty("desriptn", SampleBeanProperties.class);
|
||||
assertThat(matches.getPossibleMatches()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unknownBeanProperty() {
|
||||
void unknownBeanProperty() {
|
||||
PropertyMatches matches = PropertyMatches.forProperty("unknown", SampleBeanProperties.class);
|
||||
assertThat(matches.getPossibleMatches()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void severalMatchesBeanProperty() {
|
||||
void severalMatchesBeanProperty() {
|
||||
PropertyMatches matches = PropertyMatches.forProperty("counter", SampleBeanProperties.class);
|
||||
assertThat(matches.getPossibleMatches()).contains("counter1");
|
||||
assertThat(matches.getPossibleMatches()).contains("counter2");
|
||||
@@ -59,7 +59,7 @@ public class PropertyMatchesTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleBeanPropertyErrorMessage() {
|
||||
void simpleBeanPropertyErrorMessage() {
|
||||
PropertyMatches matches = PropertyMatches.forProperty("naem", SampleBeanProperties.class);
|
||||
String msg = matches.buildErrorMessage();
|
||||
assertThat(msg).contains("naem");
|
||||
@@ -69,7 +69,7 @@ public class PropertyMatchesTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void complexBeanPropertyErrorMessage() {
|
||||
void complexBeanPropertyErrorMessage() {
|
||||
PropertyMatches matches = PropertyMatches.forProperty("counter", SampleBeanProperties.class);
|
||||
String msg = matches.buildErrorMessage();
|
||||
assertThat(msg).contains("counter");
|
||||
@@ -79,25 +79,25 @@ public class PropertyMatchesTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleFieldPropertyTypo() {
|
||||
void simpleFieldPropertyTypo() {
|
||||
PropertyMatches matches = PropertyMatches.forField("naem", SampleFieldProperties.class);
|
||||
assertThat(matches.getPossibleMatches()).contains("name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void complexFieldPropertyTypo() {
|
||||
void complexFieldPropertyTypo() {
|
||||
PropertyMatches matches = PropertyMatches.forField("desriptn", SampleFieldProperties.class);
|
||||
assertThat(matches.getPossibleMatches()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unknownFieldProperty() {
|
||||
void unknownFieldProperty() {
|
||||
PropertyMatches matches = PropertyMatches.forField("unknown", SampleFieldProperties.class);
|
||||
assertThat(matches.getPossibleMatches()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void severalMatchesFieldProperty() {
|
||||
void severalMatchesFieldProperty() {
|
||||
PropertyMatches matches = PropertyMatches.forField("counter", SampleFieldProperties.class);
|
||||
assertThat(matches.getPossibleMatches()).contains("counter1");
|
||||
assertThat(matches.getPossibleMatches()).contains("counter2");
|
||||
@@ -105,7 +105,7 @@ public class PropertyMatchesTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleFieldPropertyErrorMessage() {
|
||||
void simpleFieldPropertyErrorMessage() {
|
||||
PropertyMatches matches = PropertyMatches.forField("naem", SampleFieldProperties.class);
|
||||
String msg = matches.buildErrorMessage();
|
||||
assertThat(msg).contains("naem");
|
||||
@@ -115,7 +115,7 @@ public class PropertyMatchesTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void complexFieldPropertyErrorMessage() {
|
||||
void complexFieldPropertyErrorMessage() {
|
||||
PropertyMatches matches = PropertyMatches.forField("counter", SampleFieldProperties.class);
|
||||
String msg = matches.buildErrorMessage();
|
||||
assertThat(msg).contains("counter");
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,10 +30,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Chris Beams
|
||||
* @see ExtendedBeanInfoTests
|
||||
*/
|
||||
public class SimplePropertyDescriptorTests {
|
||||
class SimplePropertyDescriptorTests {
|
||||
|
||||
@Test
|
||||
public void toStringOutput() throws IntrospectionException, SecurityException, NoSuchMethodException {
|
||||
void toStringOutput() throws IntrospectionException, SecurityException, NoSuchMethodException {
|
||||
{
|
||||
Object pd = new ExtendedBeanInfo.SimplePropertyDescriptor("foo", null, null);
|
||||
assertThat(pd.toString()).contains(
|
||||
@@ -71,7 +71,7 @@ public class SimplePropertyDescriptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonIndexedEquality() throws IntrospectionException, SecurityException, NoSuchMethodException {
|
||||
void nonIndexedEquality() throws IntrospectionException, SecurityException, NoSuchMethodException {
|
||||
Object pd1 = new ExtendedBeanInfo.SimplePropertyDescriptor("foo", null, null);
|
||||
assertThat(pd1).isEqualTo(pd1);
|
||||
|
||||
@@ -108,7 +108,7 @@ public class SimplePropertyDescriptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void indexedEquality() throws IntrospectionException, SecurityException, NoSuchMethodException {
|
||||
void indexedEquality() throws IntrospectionException, SecurityException, NoSuchMethodException {
|
||||
Object pd1 = new ExtendedBeanInfo.SimpleIndexedPropertyDescriptor("foo", null, null, null, null);
|
||||
assertThat(pd1).isEqualTo(pd1);
|
||||
|
||||
|
||||
+21
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -49,7 +49,7 @@ import static org.springframework.core.testfixture.io.ResourceTestUtils.qualifie
|
||||
* @author Sam Brannen
|
||||
* @since 04.07.2003
|
||||
*/
|
||||
public class BeanFactoryUtilsTests {
|
||||
class BeanFactoryUtilsTests {
|
||||
|
||||
private static final Class<?> CLASS = BeanFactoryUtilsTests.class;
|
||||
private static final Resource ROOT_CONTEXT = qualifiedResource(CLASS, "root.xml");
|
||||
@@ -63,7 +63,7 @@ public class BeanFactoryUtilsTests {
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
void setup() {
|
||||
// Interesting hierarchical factory to test counts.
|
||||
|
||||
DefaultListableBeanFactory grandParent = new DefaultListableBeanFactory();
|
||||
@@ -81,7 +81,7 @@ public class BeanFactoryUtilsTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void testHierarchicalCountBeansWithNonHierarchicalFactory() {
|
||||
void testHierarchicalCountBeansWithNonHierarchicalFactory() {
|
||||
StaticListableBeanFactory lbf = new StaticListableBeanFactory();
|
||||
lbf.addBean("t1", new TestBean());
|
||||
lbf.addBean("t2", new TestBean());
|
||||
@@ -92,7 +92,7 @@ public class BeanFactoryUtilsTests {
|
||||
* Check that override doesn't count as two separate beans.
|
||||
*/
|
||||
@Test
|
||||
public void testHierarchicalCountBeansWithOverride() {
|
||||
void testHierarchicalCountBeansWithOverride() {
|
||||
// Leaf count
|
||||
assertThat(this.listableBeanFactory.getBeanDefinitionCount()).isEqualTo(1);
|
||||
// Count minus duplicate
|
||||
@@ -101,14 +101,14 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHierarchicalNamesWithNoMatch() {
|
||||
void testHierarchicalNamesWithNoMatch() {
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory, NoOp.class));
|
||||
assertThat(names).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHierarchicalNamesWithMatchOnlyInRoot() {
|
||||
void testHierarchicalNamesWithMatchOnlyInRoot() {
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory, IndexedTestBean.class));
|
||||
assertThat(names).hasSize(1);
|
||||
@@ -118,7 +118,7 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanNamesForTypeWithOverride() {
|
||||
void testGetBeanNamesForTypeWithOverride() {
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class));
|
||||
// includes 2 TestBeans from FactoryBeans (DummyFactory definitions)
|
||||
@@ -130,7 +130,7 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoBeansOfType() {
|
||||
void testNoBeansOfType() {
|
||||
StaticListableBeanFactory lbf = new StaticListableBeanFactory();
|
||||
lbf.addBean("foo", new Object());
|
||||
Map<String, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, true, false);
|
||||
@@ -138,7 +138,7 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindsBeansOfTypeWithStaticFactory() {
|
||||
void testFindsBeansOfTypeWithStaticFactory() {
|
||||
StaticListableBeanFactory lbf = new StaticListableBeanFactory();
|
||||
TestBean t1 = new TestBean();
|
||||
TestBean t2 = new TestBean();
|
||||
@@ -169,7 +169,7 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindsBeansOfTypeWithDefaultFactory() {
|
||||
void testFindsBeansOfTypeWithDefaultFactory() {
|
||||
Object test3 = this.listableBeanFactory.getBean("test3");
|
||||
Object test = this.listableBeanFactory.getBean("test");
|
||||
|
||||
@@ -232,7 +232,7 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHierarchicalResolutionWithOverride() {
|
||||
void testHierarchicalResolutionWithOverride() {
|
||||
Object test3 = this.listableBeanFactory.getBean("test3");
|
||||
Object test = this.listableBeanFactory.getBean("test");
|
||||
|
||||
@@ -271,14 +271,14 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHierarchicalNamesForAnnotationWithNoMatch() {
|
||||
void testHierarchicalNamesForAnnotationWithNoMatch() {
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(this.listableBeanFactory, Override.class));
|
||||
assertThat(names).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHierarchicalNamesForAnnotationWithMatchOnlyInRoot() {
|
||||
void testHierarchicalNamesForAnnotationWithMatchOnlyInRoot() {
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(this.listableBeanFactory, TestAnnotation.class));
|
||||
assertThat(names).hasSize(1);
|
||||
@@ -288,7 +288,7 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanNamesForAnnotationWithOverride() {
|
||||
void testGetBeanNamesForAnnotationWithOverride() {
|
||||
AnnotatedBean annotatedBean = new AnnotatedBean();
|
||||
this.listableBeanFactory.registerSingleton("anotherAnnotatedBean", annotatedBean);
|
||||
List<String> names = Arrays.asList(
|
||||
@@ -299,31 +299,31 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testADependencies() {
|
||||
void testADependencies() {
|
||||
String[] deps = this.dependentBeansFactory.getDependentBeans("a");
|
||||
assertThat(ObjectUtils.isEmpty(deps)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBDependencies() {
|
||||
void testBDependencies() {
|
||||
String[] deps = this.dependentBeansFactory.getDependentBeans("b");
|
||||
assertThat(Arrays.equals(new String[] { "c" }, deps)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCDependencies() {
|
||||
void testCDependencies() {
|
||||
String[] deps = this.dependentBeansFactory.getDependentBeans("c");
|
||||
assertThat(Arrays.equals(new String[] { "int", "long" }, deps)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntDependencies() {
|
||||
void testIntDependencies() {
|
||||
String[] deps = this.dependentBeansFactory.getDependentBeans("int");
|
||||
assertThat(Arrays.equals(new String[] { "buffer" }, deps)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAnnotationOnBean() {
|
||||
void findAnnotationOnBean() {
|
||||
this.listableBeanFactory.registerSingleton("controllerAdvice", new ControllerAdviceClass());
|
||||
this.listableBeanFactory.registerSingleton("restControllerAdvice", new RestControllerAdviceClass());
|
||||
testFindAnnotationOnBean(this.listableBeanFactory);
|
||||
@@ -350,7 +350,7 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSingletonAndIsPrototypeWithStaticFactory() {
|
||||
void isSingletonAndIsPrototypeWithStaticFactory() {
|
||||
StaticListableBeanFactory lbf = new StaticListableBeanFactory();
|
||||
TestBean bean = new TestBean();
|
||||
DummyFactory fb1 = new DummyFactory();
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1240,7 +1240,7 @@ class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void arrayPropertyWithOptionalAutowiring() throws MalformedURLException {
|
||||
void arrayPropertyWithOptionalAutowiring() {
|
||||
RootBeanDefinition rbd = new RootBeanDefinition(ArrayBean.class);
|
||||
rbd.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
|
||||
lbf.registerBeanDefinition("arrayBean", rbd);
|
||||
@@ -3211,7 +3211,7 @@ class DefaultListableBeanFactoryTests {
|
||||
extends RepositoryFactoryBeanSupport<T, S, ID> {
|
||||
|
||||
@Override
|
||||
public T getObject() throws Exception {
|
||||
public T getObject() {
|
||||
throw new IllegalArgumentException("Should not be called");
|
||||
}
|
||||
|
||||
@@ -3460,7 +3460,7 @@ class DefaultListableBeanFactoryTests {
|
||||
|
||||
enum NonPublicEnum {
|
||||
|
||||
VALUE_1, VALUE_2;
|
||||
VALUE_1, VALUE_2
|
||||
}
|
||||
|
||||
|
||||
|
||||
+9
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,42 +32,42 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class FactoryBeanLookupTests {
|
||||
class FactoryBeanLookupTests {
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
void setUp() {
|
||||
beanFactory = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader((BeanDefinitionRegistry) beanFactory).loadBeanDefinitions(
|
||||
new ClassPathResource("FactoryBeanLookupTests-context.xml", this.getClass()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void factoryBeanLookupByNameDereferencing() {
|
||||
void factoryBeanLookupByNameDereferencing() {
|
||||
Object fooFactory = beanFactory.getBean("&fooFactory");
|
||||
assertThat(fooFactory).isInstanceOf(FooFactoryBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void factoryBeanLookupByType() {
|
||||
void factoryBeanLookupByType() {
|
||||
FooFactoryBean fooFactory = beanFactory.getBean(FooFactoryBean.class);
|
||||
assertThat(fooFactory).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void factoryBeanLookupByTypeAndNameDereference() {
|
||||
void factoryBeanLookupByTypeAndNameDereference() {
|
||||
FooFactoryBean fooFactory = beanFactory.getBean("&fooFactory", FooFactoryBean.class);
|
||||
assertThat(fooFactory).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void factoryBeanObjectLookupByName() {
|
||||
void factoryBeanObjectLookupByName() {
|
||||
Object fooFactory = beanFactory.getBean("fooFactory");
|
||||
assertThat(fooFactory).isInstanceOf(Foo.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void factoryBeanObjectLookupByNameAndType() {
|
||||
void factoryBeanObjectLookupByNameAndType() {
|
||||
Foo foo = beanFactory.getBean("fooFactory", Foo.class);
|
||||
assertThat(foo).isNotNull();
|
||||
}
|
||||
@@ -75,7 +75,7 @@ public class FactoryBeanLookupTests {
|
||||
|
||||
class FooFactoryBean extends AbstractFactoryBean<Foo> {
|
||||
@Override
|
||||
protected Foo createInstance() throws Exception {
|
||||
protected Foo createInstance() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,7 +38,7 @@ import static org.springframework.core.testfixture.io.ResourceTestUtils.qualifie
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class FactoryBeanTests {
|
||||
class FactoryBeanTests {
|
||||
|
||||
private static final Class<?> CLASS = FactoryBeanTests.class;
|
||||
private static final Resource RETURNS_NULL_CONTEXT = qualifiedResource(CLASS, "returnsNull.xml");
|
||||
@@ -48,7 +48,7 @@ public class FactoryBeanTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void testFactoryBeanReturnsNull() throws Exception {
|
||||
void testFactoryBeanReturnsNull() {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(RETURNS_NULL_CONTEXT);
|
||||
|
||||
@@ -56,7 +56,7 @@ public class FactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFactoryBeansWithAutowiring() throws Exception {
|
||||
void testFactoryBeansWithAutowiring() {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(WITH_AUTOWIRING_CONTEXT);
|
||||
|
||||
@@ -77,7 +77,7 @@ public class FactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFactoryBeansWithIntermediateFactoryBeanAutowiringFailure() throws Exception {
|
||||
void testFactoryBeansWithIntermediateFactoryBeanAutowiringFailure() {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(WITH_AUTOWIRING_CONTEXT);
|
||||
|
||||
@@ -92,21 +92,21 @@ public class FactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbstractFactoryBeanViaAnnotation() throws Exception {
|
||||
void testAbstractFactoryBeanViaAnnotation() {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(ABSTRACT_CONTEXT);
|
||||
factory.getBeansWithAnnotation(Component.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbstractFactoryBeanViaType() throws Exception {
|
||||
void testAbstractFactoryBeanViaType() {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(ABSTRACT_CONTEXT);
|
||||
factory.getBeansOfType(AbstractFactoryBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCircularReferenceWithPostProcessor() {
|
||||
void testCircularReferenceWithPostProcessor() {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(CIRCULAR_CONTEXT);
|
||||
|
||||
@@ -284,11 +284,7 @@ public class FactoryBeanTests {
|
||||
if (bean instanceof FactoryBean) {
|
||||
return bean;
|
||||
}
|
||||
AtomicInteger c = count.get(beanName);
|
||||
if (c == null) {
|
||||
c = new AtomicInteger();
|
||||
count.put(beanName, c);
|
||||
}
|
||||
AtomicInteger c = count.computeIfAbsent(beanName, k -> new AtomicInteger());
|
||||
c.incrementAndGet();
|
||||
return bean;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,10 +33,10 @@ import static org.springframework.beans.factory.support.BeanDefinitionBuilder.ro
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class Spr5475Tests {
|
||||
class Spr5475Tests {
|
||||
|
||||
@Test
|
||||
public void noArgFactoryMethodInvokedWithOneArg() {
|
||||
void noArgFactoryMethodInvokedWithOneArg() {
|
||||
assertExceptionMessageForMisconfiguredFactoryMethod(
|
||||
rootBeanDefinition(Foo.class)
|
||||
.setFactoryMethod("noArgFactory")
|
||||
@@ -47,7 +47,7 @@ public class Spr5475Tests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noArgFactoryMethodInvokedWithTwoArgs() {
|
||||
void noArgFactoryMethodInvokedWithTwoArgs() {
|
||||
assertExceptionMessageForMisconfiguredFactoryMethod(
|
||||
rootBeanDefinition(Foo.class)
|
||||
.setFactoryMethod("noArgFactory")
|
||||
@@ -59,7 +59,7 @@ public class Spr5475Tests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noArgFactoryMethodInvokedWithTwoArgsAndTypesSpecified() {
|
||||
void noArgFactoryMethodInvokedWithTwoArgsAndTypesSpecified() {
|
||||
RootBeanDefinition def = new RootBeanDefinition(Foo.class);
|
||||
def.setFactoryMethodName("noArgFactory");
|
||||
ConstructorArgumentValues cav = new ConstructorArgumentValues();
|
||||
@@ -82,7 +82,7 @@ public class Spr5475Tests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleArgFactoryMethodInvokedWithNoArgs() {
|
||||
void singleArgFactoryMethodInvokedWithNoArgs() {
|
||||
// calling a factory method that accepts arguments without any arguments emits an exception unlike cases
|
||||
// where a no-arg factory method is called with arguments. Adding this test just to document the difference
|
||||
assertExceptionMessageForMisconfiguredFactoryMethod(
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,30 +27,30 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class AnnotationBeanWiringInfoResolverTests {
|
||||
class AnnotationBeanWiringInfoResolverTests {
|
||||
|
||||
@Test
|
||||
public void testResolveWiringInfo() throws Exception {
|
||||
void testResolveWiringInfo() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
new AnnotationBeanWiringInfoResolver().resolveWiringInfo(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveWiringInfoWithAnInstanceOfANonAnnotatedClass() {
|
||||
void testResolveWiringInfoWithAnInstanceOfANonAnnotatedClass() {
|
||||
AnnotationBeanWiringInfoResolver resolver = new AnnotationBeanWiringInfoResolver();
|
||||
BeanWiringInfo info = resolver.resolveWiringInfo("java.lang.String is not @Configurable");
|
||||
assertThat(info).as("Must be returning null for a non-@Configurable class instance").isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveWiringInfoWithAnInstanceOfAnAnnotatedClass() {
|
||||
void testResolveWiringInfoWithAnInstanceOfAnAnnotatedClass() {
|
||||
AnnotationBeanWiringInfoResolver resolver = new AnnotationBeanWiringInfoResolver();
|
||||
BeanWiringInfo info = resolver.resolveWiringInfo(new Soap());
|
||||
assertThat(info).as("Must *not* be returning null for a non-@Configurable class instance").isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveWiringInfoWithAnInstanceOfAnAnnotatedClassWithAutowiringTurnedOffExplicitly() {
|
||||
void testResolveWiringInfoWithAnInstanceOfAnAnnotatedClassWithAutowiringTurnedOffExplicitly() {
|
||||
AnnotationBeanWiringInfoResolver resolver = new AnnotationBeanWiringInfoResolver();
|
||||
BeanWiringInfo info = resolver.resolveWiringInfo(new WirelessSoap());
|
||||
assertThat(info).as("Must *not* be returning null for an @Configurable class instance even when autowiring is NO").isNotNull();
|
||||
@@ -59,7 +59,7 @@ public class AnnotationBeanWiringInfoResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveWiringInfoWithAnInstanceOfAnAnnotatedClassWithAutowiringTurnedOffExplicitlyAndCustomBeanName() {
|
||||
void testResolveWiringInfoWithAnInstanceOfAnAnnotatedClassWithAutowiringTurnedOffExplicitlyAndCustomBeanName() {
|
||||
AnnotationBeanWiringInfoResolver resolver = new AnnotationBeanWiringInfoResolver();
|
||||
BeanWiringInfo info = resolver.resolveWiringInfo(new NamedWirelessSoap());
|
||||
assertThat(info).as("Must *not* be returning null for an @Configurable class instance even when autowiring is NO").isNotNull();
|
||||
|
||||
+65
-102
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,6 @@ import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -83,13 +82,15 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Tests for {@link AutowiredAnnotationBeanPostProcessor}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Mark Fisher
|
||||
* @author Sam Brannen
|
||||
* @author Chris Beams
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
class AutowiredAnnotationBeanPostProcessorTests {
|
||||
|
||||
private DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
|
||||
@@ -119,6 +120,20 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
.withRootCauseInstanceOf(IllegalStateException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void processInjection() {
|
||||
ResourceInjectionBean bean = new ResourceInjectionBean();
|
||||
assertThat(bean.getTestBean()).isNull();
|
||||
assertThat(bean.getTestBean2()).isNull();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
bpp.processInjection(bean);
|
||||
|
||||
assertThat(bean.getTestBean()).isSameAs(tb);
|
||||
assertThat(bean.getTestBean2()).isSameAs(tb);
|
||||
}
|
||||
|
||||
@Test
|
||||
void resourceInjection() {
|
||||
RootBeanDefinition bd = new RootBeanDefinition(ResourceInjectionBean.class);
|
||||
@@ -711,15 +726,9 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.getTestBean3()).isSameAs(tb);
|
||||
assertThat(bean.getTestBean4()).isSameAs(tb);
|
||||
assertThat(bean.getIndexedTestBean()).isSameAs(itb);
|
||||
assertThat(bean.getNestedTestBeans()).hasSize(2);
|
||||
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb2);
|
||||
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb1);
|
||||
assertThat(bean.nestedTestBeansSetter).hasSize(2);
|
||||
assertThat(bean.nestedTestBeansSetter).element(0).isSameAs(ntb2);
|
||||
assertThat(bean.nestedTestBeansSetter).element(1).isSameAs(ntb1);
|
||||
assertThat(bean.nestedTestBeansField).hasSize(2);
|
||||
assertThat(bean.nestedTestBeansField).element(0).isSameAs(ntb2);
|
||||
assertThat(bean.nestedTestBeansField).element(1).isSameAs(ntb1);
|
||||
assertThat(bean.getNestedTestBeans()).containsExactly(ntb2, ntb1);
|
||||
assertThat(bean.nestedTestBeansSetter).containsExactly(ntb2, ntb1);
|
||||
assertThat(bean.nestedTestBeansField).containsExactly(ntb2, ntb1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -744,15 +753,9 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.getTestBean3()).isSameAs(tb);
|
||||
assertThat(bean.getTestBean4()).isSameAs(tb);
|
||||
assertThat(bean.getIndexedTestBean()).isSameAs(itb);
|
||||
assertThat(bean.getNestedTestBeans()).hasSize(2);
|
||||
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb2);
|
||||
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb1);
|
||||
assertThat(bean.nestedTestBeansSetter).hasSize(2);
|
||||
assertThat(bean.nestedTestBeansSetter).element(0).isSameAs(ntb2);
|
||||
assertThat(bean.nestedTestBeansSetter).element(1).isSameAs(ntb1);
|
||||
assertThat(bean.nestedTestBeansField).hasSize(2);
|
||||
assertThat(bean.nestedTestBeansField).element(0).isSameAs(ntb2);
|
||||
assertThat(bean.nestedTestBeansField).element(1).isSameAs(ntb1);
|
||||
assertThat(bean.getNestedTestBeans()).containsExactly(ntb2, ntb1);
|
||||
assertThat(bean.nestedTestBeansSetter).containsExactly(ntb2, ntb1);
|
||||
assertThat(bean.nestedTestBeansField).containsExactly(ntb2, ntb1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1112,9 +1115,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
ConstructorsCollectionResourceInjectionBean bean = bf.getBean("annotatedBean", ConstructorsCollectionResourceInjectionBean.class);
|
||||
assertThat(bean.getTestBean3()).isNull();
|
||||
assertThat(bean.getTestBean4()).isSameAs(tb);
|
||||
assertThat(bean.getNestedTestBeans()).hasSize(2);
|
||||
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb2);
|
||||
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb1);
|
||||
assertThat(bean.getNestedTestBeans()).containsExactly(ntb2, ntb1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1129,9 +1130,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
|
||||
SingleConstructorVarargBean bean = bf.getBean("annotatedBean", SingleConstructorVarargBean.class);
|
||||
assertThat(bean.getTestBean()).isSameAs(tb);
|
||||
assertThat(bean.getNestedTestBeans()).hasSize(2);
|
||||
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb2);
|
||||
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb1);
|
||||
assertThat(bean.getNestedTestBeans()).containsExactly(ntb2, ntb1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1158,9 +1157,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
|
||||
SingleConstructorRequiredCollectionBean bean = bf.getBean("annotatedBean", SingleConstructorRequiredCollectionBean.class);
|
||||
assertThat(bean.getTestBean()).isSameAs(tb);
|
||||
assertThat(bean.getNestedTestBeans()).hasSize(2);
|
||||
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb2);
|
||||
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb1);
|
||||
assertThat(bean.getNestedTestBeans()).containsExactly(ntb2, ntb1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1187,9 +1184,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
|
||||
SingleConstructorOptionalCollectionBean bean = bf.getBean("annotatedBean", SingleConstructorOptionalCollectionBean.class);
|
||||
assertThat(bean.getTestBean()).isSameAs(tb);
|
||||
assertThat(bean.getNestedTestBeans()).hasSize(2);
|
||||
assertThat(bean.getNestedTestBeans()).element(0).isSameAs(ntb2);
|
||||
assertThat(bean.getNestedTestBeans()).element(1).isSameAs(ntb1);
|
||||
assertThat(bean.getNestedTestBeans()).containsExactly(ntb2, ntb1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1500,8 +1495,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
SelfInjectionBean bean = bf.getBean("annotatedBean", SelfInjectionBean.class);
|
||||
SelfInjectionBean bean2 = bf.getBean("annotatedBean2", SelfInjectionBean.class);
|
||||
assertThat(bean.reference).isSameAs(bean2);
|
||||
assertThat(bean.referenceCollection).hasSize(1);
|
||||
assertThat(bean.referenceCollection).element(0).isSameAs(bean2);
|
||||
assertThat(bean.referenceCollection).containsExactly(bean2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1986,10 +1980,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.integerArray).hasSize(1);
|
||||
assertThat(bean.stringArray[0]).isSameAs(sv);
|
||||
assertThat(bean.integerArray[0]).isSameAs(iv);
|
||||
assertThat(bean.stringList).hasSize(1);
|
||||
assertThat(bean.integerList).hasSize(1);
|
||||
assertThat(bean.stringList).element(0).isSameAs(sv);
|
||||
assertThat(bean.integerList).element(0).isSameAs(iv);
|
||||
assertThat(bean.stringList).containsExactly(sv);
|
||||
assertThat(bean.integerList).containsExactly(iv);
|
||||
assertThat(bean.stringMap).hasSize(1);
|
||||
assertThat(bean.integerMap).hasSize(1);
|
||||
assertThat(bean.stringMap.get("stringValue")).isSameAs(sv);
|
||||
@@ -2000,10 +1992,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.integerRepositoryArray).hasSize(1);
|
||||
assertThat(bean.stringRepositoryArray[0]).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryArray[0]).isSameAs(ir);
|
||||
assertThat(bean.stringRepositoryList).hasSize(1);
|
||||
assertThat(bean.integerRepositoryList).hasSize(1);
|
||||
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryList).element(0).isSameAs(ir);
|
||||
assertThat(bean.stringRepositoryList).containsExactly(sr);
|
||||
assertThat(bean.integerRepositoryList).containsExactly(ir);
|
||||
assertThat(bean.stringRepositoryMap).hasSize(1);
|
||||
assertThat(bean.integerRepositoryMap).hasSize(1);
|
||||
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
|
||||
@@ -2032,10 +2022,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.integerArray).hasSize(1);
|
||||
assertThat(bean.stringArray[0]).isSameAs(sv);
|
||||
assertThat(bean.integerArray[0]).isSameAs(iv);
|
||||
assertThat(bean.stringList).hasSize(1);
|
||||
assertThat(bean.integerList).hasSize(1);
|
||||
assertThat(bean.stringList).element(0).isSameAs(sv);
|
||||
assertThat(bean.integerList).element(0).isSameAs(iv);
|
||||
assertThat(bean.stringList).containsExactly(sv);
|
||||
assertThat(bean.integerList).containsExactly(iv);
|
||||
assertThat(bean.stringMap).hasSize(1);
|
||||
assertThat(bean.integerMap).hasSize(1);
|
||||
assertThat(bean.stringMap.get("stringValue")).isSameAs(sv);
|
||||
@@ -2046,10 +2034,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.integerRepositoryArray).hasSize(1);
|
||||
assertThat(bean.stringRepositoryArray[0]).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryArray[0]).isSameAs(ir);
|
||||
assertThat(bean.stringRepositoryList).hasSize(1);
|
||||
assertThat(bean.integerRepositoryList).hasSize(1);
|
||||
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryList).element(0).isSameAs(ir);
|
||||
assertThat(bean.stringRepositoryList).containsExactly(sr);
|
||||
assertThat(bean.integerRepositoryList).containsExactly(ir);
|
||||
assertThat(bean.stringRepositoryMap).hasSize(1);
|
||||
assertThat(bean.integerRepositoryMap).hasSize(1);
|
||||
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
|
||||
@@ -2074,10 +2060,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.integerRepositoryArray).hasSize(1);
|
||||
assertThat(bean.stringRepositoryArray[0]).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryArray[0]).isSameAs(ir);
|
||||
assertThat(bean.stringRepositoryList).hasSize(1);
|
||||
assertThat(bean.integerRepositoryList).hasSize(1);
|
||||
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryList).element(0).isSameAs(ir);
|
||||
assertThat(bean.stringRepositoryList).containsExactly(sr);
|
||||
assertThat(bean.integerRepositoryList).containsExactly(ir);
|
||||
assertThat(bean.stringRepositoryMap).hasSize(1);
|
||||
assertThat(bean.integerRepositoryMap).hasSize(1);
|
||||
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
|
||||
@@ -2141,9 +2125,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.stringRepositoryArray).hasSize(1);
|
||||
assertThat(bean.repositoryArray[0]).isSameAs(repo);
|
||||
assertThat(bean.stringRepositoryArray[0]).isSameAs(repo);
|
||||
assertThat(bean.repositoryList).hasSize(1);
|
||||
assertThat(bean.repositoryList).containsExactly(repo);
|
||||
assertThat(bean.stringRepositoryList).hasSize(1);
|
||||
assertThat(bean.repositoryList).element(0).isSameAs(repo);
|
||||
assertThat(bean.stringRepositoryList).element(0).isSameAs(repo);
|
||||
assertThat(bean.repositoryMap).hasSize(1);
|
||||
assertThat(bean.stringRepositoryMap).hasSize(1);
|
||||
@@ -2201,7 +2184,6 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.stringRepositoryArray[0]).isSameAs(repo);
|
||||
assertThat(bean.repositoryList).hasSize(1);
|
||||
assertThat(bean.stringRepositoryList).hasSize(1);
|
||||
assertThat(bean.repositoryList).element(0).isSameAs(repo);
|
||||
assertThat(bean.stringRepositoryList).element(0).isSameAs(repo);
|
||||
assertThat(bean.repositoryMap).hasSize(1);
|
||||
assertThat(bean.stringRepositoryMap).hasSize(1);
|
||||
@@ -2230,9 +2212,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.stringRepositoryArray).hasSize(1);
|
||||
assertThat(bean.repositoryArray[0]).isSameAs(repo);
|
||||
assertThat(bean.stringRepositoryArray[0]).isSameAs(repo);
|
||||
assertThat(bean.repositoryList).hasSize(1);
|
||||
assertThat(bean.repositoryList).containsExactly(repo);
|
||||
assertThat(bean.stringRepositoryList).hasSize(1);
|
||||
assertThat(bean.repositoryList).element(0).isSameAs(repo);
|
||||
assertThat(bean.stringRepositoryList).element(0).isSameAs(repo);
|
||||
assertThat(bean.repositoryMap).hasSize(1);
|
||||
assertThat(bean.stringRepositoryMap).hasSize(1);
|
||||
@@ -2270,10 +2251,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.integerArray).hasSize(1);
|
||||
assertThat(bean.stringArray[0]).isSameAs(sv);
|
||||
assertThat(bean.integerArray[0]).isSameAs(iv);
|
||||
assertThat(bean.stringList).hasSize(1);
|
||||
assertThat(bean.integerList).hasSize(1);
|
||||
assertThat(bean.stringList).element(0).isSameAs(sv);
|
||||
assertThat(bean.integerList).element(0).isSameAs(iv);
|
||||
assertThat(bean.stringList).containsExactly(sv);
|
||||
assertThat(bean.integerList).containsExactly(iv);
|
||||
assertThat(bean.stringMap).hasSize(1);
|
||||
assertThat(bean.integerMap).hasSize(1);
|
||||
assertThat(bean.stringMap.get("stringValue")).isSameAs(sv);
|
||||
@@ -2284,10 +2263,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.integerRepositoryArray).hasSize(1);
|
||||
assertThat(bean.stringRepositoryArray[0]).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryArray[0]).isSameAs(ir);
|
||||
assertThat(bean.stringRepositoryList).hasSize(1);
|
||||
assertThat(bean.integerRepositoryList).hasSize(1);
|
||||
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryList).element(0).isSameAs(ir);
|
||||
assertThat(bean.stringRepositoryList).containsExactly(sr);
|
||||
assertThat(bean.integerRepositoryList).containsExactly(ir);
|
||||
assertThat(bean.stringRepositoryMap).hasSize(1);
|
||||
assertThat(bean.integerRepositoryMap).hasSize(1);
|
||||
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
|
||||
@@ -2316,10 +2293,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.integerArray).hasSize(1);
|
||||
assertThat(bean.stringArray[0]).isSameAs(sv);
|
||||
assertThat(bean.integerArray[0]).isSameAs(iv);
|
||||
assertThat(bean.stringList).hasSize(1);
|
||||
assertThat(bean.integerList).hasSize(1);
|
||||
assertThat(bean.stringList).element(0).isSameAs(sv);
|
||||
assertThat(bean.integerList).element(0).isSameAs(iv);
|
||||
assertThat(bean.stringList).containsExactly(sv);
|
||||
assertThat(bean.integerList).containsExactly(iv);
|
||||
assertThat(bean.stringMap).hasSize(1);
|
||||
assertThat(bean.integerMap).hasSize(1);
|
||||
assertThat(bean.stringMap.get("stringValue")).isSameAs(sv);
|
||||
@@ -2330,10 +2305,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.integerRepositoryArray).hasSize(1);
|
||||
assertThat(bean.stringRepositoryArray[0]).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryArray[0]).isSameAs(ir);
|
||||
assertThat(bean.stringRepositoryList).hasSize(1);
|
||||
assertThat(bean.integerRepositoryList).hasSize(1);
|
||||
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryList).element(0).isSameAs(ir);
|
||||
assertThat(bean.stringRepositoryList).containsExactly(sr);
|
||||
assertThat(bean.integerRepositoryList).containsExactly(ir);
|
||||
assertThat(bean.stringRepositoryMap).hasSize(1);
|
||||
assertThat(bean.integerRepositoryMap).hasSize(1);
|
||||
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
|
||||
@@ -2357,10 +2330,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.integerRepositoryArray).hasSize(1);
|
||||
assertThat(bean.stringRepositoryArray[0]).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryArray[0]).isSameAs(ir);
|
||||
assertThat(bean.stringRepositoryList).hasSize(1);
|
||||
assertThat(bean.integerRepositoryList).hasSize(1);
|
||||
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryList).element(0).isSameAs(ir);
|
||||
assertThat(bean.stringRepositoryList).containsExactly(sr);
|
||||
assertThat(bean.integerRepositoryList).containsExactly(ir);
|
||||
assertThat(bean.stringRepositoryMap).hasSize(1);
|
||||
assertThat(bean.integerRepositoryMap).hasSize(1);
|
||||
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
|
||||
@@ -2383,10 +2354,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.integerRepositoryArray).hasSize(1);
|
||||
assertThat(bean.stringRepositoryArray[0]).isSameAs(gr);
|
||||
assertThat(bean.integerRepositoryArray[0]).isSameAs(gr);
|
||||
assertThat(bean.stringRepositoryList).hasSize(1);
|
||||
assertThat(bean.integerRepositoryList).hasSize(1);
|
||||
assertThat(bean.stringRepositoryList).element(0).isSameAs(gr);
|
||||
assertThat(bean.integerRepositoryList).element(0).isSameAs(gr);
|
||||
assertThat(bean.stringRepositoryList).containsExactly(gr);
|
||||
assertThat(bean.integerRepositoryList).containsExactly(gr);
|
||||
assertThat(bean.stringRepositoryMap).hasSize(1);
|
||||
assertThat(bean.integerRepositoryMap).hasSize(1);
|
||||
assertThat(bean.stringRepositoryMap.get("genericRepo")).isSameAs(gr);
|
||||
@@ -2408,10 +2377,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.integerRepositoryArray).hasSize(1);
|
||||
assertThat(bean.stringRepositoryArray[0]).isSameAs(ngr);
|
||||
assertThat(bean.integerRepositoryArray[0]).isSameAs(ngr);
|
||||
assertThat(bean.stringRepositoryList).hasSize(1);
|
||||
assertThat(bean.integerRepositoryList).hasSize(1);
|
||||
assertThat(bean.stringRepositoryList).element(0).isSameAs(ngr);
|
||||
assertThat(bean.integerRepositoryList).element(0).isSameAs(ngr);
|
||||
assertThat(bean.stringRepositoryList).containsExactly(ngr);
|
||||
assertThat(bean.integerRepositoryList).containsExactly(ngr);
|
||||
assertThat(bean.stringRepositoryMap).hasSize(1);
|
||||
assertThat(bean.integerRepositoryMap).hasSize(1);
|
||||
assertThat(bean.stringRepositoryMap.get("simpleRepo")).isSameAs(ngr);
|
||||
@@ -2436,10 +2403,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.integerRepositoryArray).hasSize(1);
|
||||
assertThat(bean.stringRepositoryArray[0]).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryArray[0]).isSameAs(gr);
|
||||
assertThat(bean.stringRepositoryList).hasSize(1);
|
||||
assertThat(bean.integerRepositoryList).hasSize(1);
|
||||
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryList).element(0).isSameAs(gr);
|
||||
assertThat(bean.stringRepositoryList).containsExactly(sr);
|
||||
assertThat(bean.integerRepositoryList).containsExactly(gr);
|
||||
assertThat(bean.stringRepositoryMap).hasSize(1);
|
||||
assertThat(bean.integerRepositoryMap).hasSize(1);
|
||||
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
|
||||
@@ -2463,10 +2428,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertThat(bean.integerRepositoryArray).hasSize(1);
|
||||
assertThat(bean.stringRepositoryArray[0]).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryArray[0]).isSameAs(ngr);
|
||||
assertThat(bean.stringRepositoryList).hasSize(1);
|
||||
assertThat(bean.integerRepositoryList).hasSize(1);
|
||||
assertThat(bean.stringRepositoryList).element(0).isSameAs(sr);
|
||||
assertThat(bean.integerRepositoryList).element(0).isSameAs(ngr);
|
||||
assertThat(bean.stringRepositoryList).containsExactly(sr);
|
||||
assertThat(bean.integerRepositoryList).containsExactly(ngr);
|
||||
assertThat(bean.stringRepositoryMap).hasSize(1);
|
||||
assertThat(bean.integerRepositoryMap).hasSize(1);
|
||||
assertThat(bean.stringRepositoryMap.get("stringRepo")).isSameAs(sr);
|
||||
@@ -2602,7 +2565,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mixedNullableArgMethodInjection(){
|
||||
void mixedNullableArgMethodInjection(){
|
||||
bf.registerSingleton("nonNullBean", "Test");
|
||||
bf.registerBeanDefinition("mixedNullableInjectionBean",
|
||||
new RootBeanDefinition(MixedNullableInjectionBean.class));
|
||||
@@ -2612,7 +2575,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mixedOptionalArgMethodInjection(){
|
||||
void mixedOptionalArgMethodInjection(){
|
||||
bf.registerSingleton("nonNullBean", "Test");
|
||||
bf.registerBeanDefinition("mixedOptionalInjectionBean",
|
||||
new RootBeanDefinition(MixedOptionalInjectionBean.class));
|
||||
@@ -3463,7 +3426,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
public static class StringFactoryBean implements FactoryBean<String> {
|
||||
|
||||
@Override
|
||||
public String getObject() throws Exception {
|
||||
public String getObject() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -3998,7 +3961,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T createMock(Class<T> toMock) {
|
||||
return (T) Proxy.newProxyInstance(AutowiredAnnotationBeanPostProcessorTests.class.getClassLoader(), new Class<?>[] {toMock},
|
||||
(InvocationHandler) (proxy, method, args) -> {
|
||||
(proxy, method, args) -> {
|
||||
throw new UnsupportedOperationException("mocked!");
|
||||
});
|
||||
}
|
||||
@@ -4146,7 +4109,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
public static class MyCallable implements Callable<Thread> {
|
||||
|
||||
@Override
|
||||
public Thread call() throws Exception {
|
||||
public Thread call() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -4155,7 +4118,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
public static class SecondCallable implements Callable<Thread>{
|
||||
|
||||
@Override
|
||||
public Thread call() throws Exception {
|
||||
public Thread call() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,16 +28,16 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.core.testfixture.io.ResourceTestUtils.qualifiedResource;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link CustomAutowireConfigurer}.
|
||||
* Tests for {@link CustomAutowireConfigurer}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class CustomAutowireConfigurerTests {
|
||||
class CustomAutowireConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testCustomResolver() {
|
||||
void testCustomResolver() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
|
||||
qualifiedResource(CustomAutowireConfigurerTests.class, "context.xml"));
|
||||
|
||||
+47
-66
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,6 +33,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessorTests.StringFactoryBean;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
|
||||
@@ -49,13 +50,13 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor}
|
||||
* processing the JSR-330 {@link jakarta.inject.Inject} annotation.
|
||||
* Tests for {@link AutowiredAnnotationBeanPostProcessor} processing
|
||||
* the JSR-330 {@link jakarta.inject.Inject} annotation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class InjectAnnotationBeanPostProcessorTests {
|
||||
class InjectAnnotationBeanPostProcessorTests {
|
||||
|
||||
private DefaultListableBeanFactory bf;
|
||||
|
||||
@@ -63,7 +64,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
void setup() {
|
||||
bf = new DefaultListableBeanFactory();
|
||||
bf.registerResolvableDependency(BeanFactory.class, bf);
|
||||
bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
@@ -73,13 +74,13 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void close() {
|
||||
void close() {
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIncompleteBeanDefinition() {
|
||||
void testIncompleteBeanDefinition() {
|
||||
bf.registerBeanDefinition("testBean", new GenericBeanDefinition());
|
||||
try {
|
||||
bf.getBean("testBean");
|
||||
@@ -90,7 +91,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceInjection() {
|
||||
void testResourceInjection() {
|
||||
RootBeanDefinition bd = new RootBeanDefinition(ResourceInjectionBean.class);
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", bd);
|
||||
@@ -107,7 +108,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtendedResourceInjection() {
|
||||
void testExtendedResourceInjection() {
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TypedExtendedResourceInjectionBean.class);
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", bd);
|
||||
@@ -134,7 +135,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtendedResourceInjectionWithOverriding() {
|
||||
void testExtendedResourceInjectionWithOverriding() {
|
||||
RootBeanDefinition annotatedBd = new RootBeanDefinition(TypedExtendedResourceInjectionBean.class);
|
||||
TestBean tb2 = new TestBean();
|
||||
annotatedBd.getPropertyValues().add("testBean2", tb2);
|
||||
@@ -154,7 +155,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorResourceInjection() {
|
||||
void testConstructorResourceInjection() {
|
||||
RootBeanDefinition bd = new RootBeanDefinition(ConstructorResourceInjectionBean.class);
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", bd);
|
||||
@@ -181,7 +182,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorResourceInjectionWithMultipleCandidatesAsCollection() {
|
||||
void testConstructorResourceInjectionWithMultipleCandidatesAsCollection() {
|
||||
bf.registerBeanDefinition("annotatedBean",
|
||||
new RootBeanDefinition(ConstructorsCollectionResourceInjectionBean.class));
|
||||
TestBean tb = new TestBean();
|
||||
@@ -200,7 +201,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorResourceInjectionWithMultipleCandidatesAndFallback() {
|
||||
void testConstructorResourceInjectionWithMultipleCandidatesAndFallback() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ConstructorsResourceInjectionBean.class));
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
@@ -211,7 +212,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorInjectionWithMap() {
|
||||
void testConstructorInjectionWithMap() {
|
||||
RootBeanDefinition bd = new RootBeanDefinition(MapConstructorInjectionBean.class);
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", bd);
|
||||
@@ -236,7 +237,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFieldInjectionWithMap() {
|
||||
void testFieldInjectionWithMap() {
|
||||
RootBeanDefinition bd = new RootBeanDefinition(MapFieldInjectionBean.class);
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", bd);
|
||||
@@ -261,7 +262,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodInjectionWithMap() {
|
||||
void testMethodInjectionWithMap() {
|
||||
RootBeanDefinition bd = new RootBeanDefinition(MapMethodInjectionBean.class);
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", bd);
|
||||
@@ -282,7 +283,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodInjectionWithMapAndMultipleMatches() {
|
||||
void testMethodInjectionWithMapAndMultipleMatches() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(MapMethodInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean1", new RootBeanDefinition(TestBean.class));
|
||||
bf.registerBeanDefinition("testBean2", new RootBeanDefinition(TestBean.class));
|
||||
@@ -291,7 +292,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodInjectionWithMapAndMultipleMatchesButOnlyOneAutowireCandidate() {
|
||||
void testMethodInjectionWithMapAndMultipleMatchesButOnlyOneAutowireCandidate() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(MapMethodInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean1", new RootBeanDefinition(TestBean.class));
|
||||
RootBeanDefinition rbd2 = new RootBeanDefinition(TestBean.class);
|
||||
@@ -307,7 +308,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryInjection() {
|
||||
void testObjectFactoryInjection() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryQualifierFieldInjectionBean.class));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "testBean"));
|
||||
@@ -319,7 +320,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryQualifierInjection() {
|
||||
void testObjectFactoryQualifierInjection() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryQualifierFieldInjectionBean.class));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "testBean"));
|
||||
@@ -330,7 +331,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryFieldInjectionIntoPrototypeBean() {
|
||||
void testObjectFactoryFieldInjectionIntoPrototypeBean() {
|
||||
RootBeanDefinition annotatedBeanDefinition = new RootBeanDefinition(ObjectFactoryQualifierFieldInjectionBean.class);
|
||||
annotatedBeanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", annotatedBeanDefinition);
|
||||
@@ -347,7 +348,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryMethodInjectionIntoPrototypeBean() {
|
||||
void testObjectFactoryMethodInjectionIntoPrototypeBean() {
|
||||
RootBeanDefinition annotatedBeanDefinition = new RootBeanDefinition(ObjectFactoryQualifierMethodInjectionBean.class);
|
||||
annotatedBeanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", annotatedBeanDefinition);
|
||||
@@ -364,7 +365,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryWithBeanField() throws Exception {
|
||||
void testObjectFactoryWithBeanField() throws Exception {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryFieldInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
bf.setSerializationId("test");
|
||||
@@ -376,7 +377,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryWithBeanMethod() throws Exception {
|
||||
void testObjectFactoryWithBeanMethod() throws Exception {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryMethodInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
bf.setSerializationId("test");
|
||||
@@ -388,7 +389,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryWithTypedListField() throws Exception {
|
||||
void testObjectFactoryWithTypedListField() throws Exception {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryListFieldInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
bf.setSerializationId("test");
|
||||
@@ -400,7 +401,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryWithTypedListMethod() throws Exception {
|
||||
void testObjectFactoryWithTypedListMethod() throws Exception {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryListMethodInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
bf.setSerializationId("test");
|
||||
@@ -412,7 +413,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryWithTypedMapField() throws Exception {
|
||||
void testObjectFactoryWithTypedMapField() throws Exception {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryMapFieldInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
bf.setSerializationId("test");
|
||||
@@ -424,7 +425,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryWithTypedMapMethod() throws Exception {
|
||||
void testObjectFactoryWithTypedMapMethod() throws Exception {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryMapMethodInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
bf.setSerializationId("test");
|
||||
@@ -441,7 +442,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
* specifically addressing SPR-4040.
|
||||
*/
|
||||
@Test
|
||||
public void testBeanAutowiredWithFactoryBean() {
|
||||
void testBeanAutowiredWithFactoryBean() {
|
||||
bf.registerBeanDefinition("factoryBeanDependentBean", new RootBeanDefinition(FactoryBeanDependentBean.class));
|
||||
bf.registerSingleton("stringFactoryBean", new StringFactoryBean());
|
||||
|
||||
@@ -454,7 +455,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullableFieldInjectionWithBeanAvailable() {
|
||||
void testNullableFieldInjectionWithBeanAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(NullableFieldInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
@@ -463,7 +464,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullableFieldInjectionWithBeanNotAvailable() {
|
||||
void testNullableFieldInjectionWithBeanNotAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(NullableFieldInjectionBean.class));
|
||||
|
||||
NullableFieldInjectionBean bean = (NullableFieldInjectionBean) bf.getBean("annotatedBean");
|
||||
@@ -471,7 +472,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullableMethodInjectionWithBeanAvailable() {
|
||||
void testNullableMethodInjectionWithBeanAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(NullableMethodInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
@@ -480,7 +481,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullableMethodInjectionWithBeanNotAvailable() {
|
||||
void testNullableMethodInjectionWithBeanNotAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(NullableMethodInjectionBean.class));
|
||||
|
||||
NullableMethodInjectionBean bean = (NullableMethodInjectionBean) bf.getBean("annotatedBean");
|
||||
@@ -488,7 +489,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionalFieldInjectionWithBeanAvailable() {
|
||||
void testOptionalFieldInjectionWithBeanAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(OptionalFieldInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
@@ -498,7 +499,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionalFieldInjectionWithBeanNotAvailable() {
|
||||
void testOptionalFieldInjectionWithBeanNotAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(OptionalFieldInjectionBean.class));
|
||||
|
||||
OptionalFieldInjectionBean bean = (OptionalFieldInjectionBean) bf.getBean("annotatedBean");
|
||||
@@ -506,7 +507,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionalMethodInjectionWithBeanAvailable() {
|
||||
void testOptionalMethodInjectionWithBeanAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(OptionalMethodInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
@@ -516,7 +517,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionalMethodInjectionWithBeanNotAvailable() {
|
||||
void testOptionalMethodInjectionWithBeanNotAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(OptionalMethodInjectionBean.class));
|
||||
|
||||
OptionalMethodInjectionBean bean = (OptionalMethodInjectionBean) bf.getBean("annotatedBean");
|
||||
@@ -524,7 +525,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionalListFieldInjectionWithBeanAvailable() {
|
||||
void testOptionalListFieldInjectionWithBeanAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(OptionalListFieldInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
@@ -534,7 +535,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionalListFieldInjectionWithBeanNotAvailable() {
|
||||
void testOptionalListFieldInjectionWithBeanNotAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(OptionalListFieldInjectionBean.class));
|
||||
|
||||
OptionalListFieldInjectionBean bean = (OptionalListFieldInjectionBean) bf.getBean("annotatedBean");
|
||||
@@ -542,7 +543,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionalListMethodInjectionWithBeanAvailable() {
|
||||
void testOptionalListMethodInjectionWithBeanAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(OptionalListMethodInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
@@ -552,7 +553,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionalListMethodInjectionWithBeanNotAvailable() {
|
||||
void testOptionalListMethodInjectionWithBeanNotAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(OptionalListMethodInjectionBean.class));
|
||||
|
||||
OptionalListMethodInjectionBean bean = (OptionalListMethodInjectionBean) bf.getBean("annotatedBean");
|
||||
@@ -560,7 +561,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderOfOptionalFieldInjectionWithBeanAvailable() {
|
||||
void testProviderOfOptionalFieldInjectionWithBeanAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ProviderOfOptionalFieldInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
@@ -570,7 +571,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderOfOptionalFieldInjectionWithBeanNotAvailable() {
|
||||
void testProviderOfOptionalFieldInjectionWithBeanNotAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ProviderOfOptionalFieldInjectionBean.class));
|
||||
|
||||
ProviderOfOptionalFieldInjectionBean bean = (ProviderOfOptionalFieldInjectionBean) bf.getBean("annotatedBean");
|
||||
@@ -578,7 +579,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderOfOptionalMethodInjectionWithBeanAvailable() {
|
||||
void testProviderOfOptionalMethodInjectionWithBeanAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ProviderOfOptionalMethodInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
@@ -588,7 +589,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderOfOptionalMethodInjectionWithBeanNotAvailable() {
|
||||
void testProviderOfOptionalMethodInjectionWithBeanNotAvailable() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ProviderOfOptionalMethodInjectionBean.class));
|
||||
|
||||
ProviderOfOptionalMethodInjectionBean bean = (ProviderOfOptionalMethodInjectionBean) bf.getBean("annotatedBean");
|
||||
@@ -596,7 +597,7 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotatedDefaultConstructor() {
|
||||
void testAnnotatedDefaultConstructor() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(AnnotatedDefaultConstructorBean.class));
|
||||
|
||||
assertThat(bf.getBean("annotatedBean")).isNotNull();
|
||||
@@ -644,7 +645,6 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
|
||||
@Override
|
||||
@Inject
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setTestBean2(TestBean testBean2) {
|
||||
super.setTestBean2(testBean2);
|
||||
}
|
||||
@@ -1108,25 +1108,6 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
|
||||
public static class StringFactoryBean implements FactoryBean<String> {
|
||||
|
||||
@Override
|
||||
public String getObject() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<String> getObjectType() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
|
||||
+12
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,13 +31,13 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
* @author Karl Pietrzak
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class LookupAnnotationTests {
|
||||
class LookupAnnotationTests {
|
||||
|
||||
private DefaultListableBeanFactory beanFactory;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
void setup() {
|
||||
beanFactory = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor aabpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
aabpp.setBeanFactory(beanFactory);
|
||||
@@ -51,7 +51,7 @@ public class LookupAnnotationTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void testWithoutConstructorArg() {
|
||||
void testWithoutConstructorArg() {
|
||||
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
|
||||
Object expected = bean.get();
|
||||
assertThat(expected.getClass()).isEqualTo(TestBean.class);
|
||||
@@ -59,7 +59,7 @@ public class LookupAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithOverloadedArg() {
|
||||
void testWithOverloadedArg() {
|
||||
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
|
||||
TestBean expected = bean.get("haha");
|
||||
assertThat(expected.getClass()).isEqualTo(TestBean.class);
|
||||
@@ -68,7 +68,7 @@ public class LookupAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithOneConstructorArg() {
|
||||
void testWithOneConstructorArg() {
|
||||
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
|
||||
TestBean expected = bean.getOneArgument("haha");
|
||||
assertThat(expected.getClass()).isEqualTo(TestBean.class);
|
||||
@@ -77,7 +77,7 @@ public class LookupAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithTwoConstructorArg() {
|
||||
void testWithTwoConstructorArg() {
|
||||
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
|
||||
TestBean expected = bean.getTwoArguments("haha", 72);
|
||||
assertThat(expected.getClass()).isEqualTo(TestBean.class);
|
||||
@@ -87,7 +87,7 @@ public class LookupAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithThreeArgsShouldFail() {
|
||||
void testWithThreeArgsShouldFail() {
|
||||
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
|
||||
assertThatExceptionOfType(AbstractMethodError.class).as("TestBean has no three arg constructor").isThrownBy(() ->
|
||||
bean.getThreeArguments("name", 1, 2));
|
||||
@@ -95,7 +95,7 @@ public class LookupAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithEarlyInjection() {
|
||||
void testWithEarlyInjection() {
|
||||
AbstractBean bean = beanFactory.getBean("beanConsumer", BeanConsumer.class).abstractBean;
|
||||
Object expected = bean.get();
|
||||
assertThat(expected.getClass()).isEqualTo(TestBean.class);
|
||||
@@ -115,7 +115,7 @@ public class LookupAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithGenericBean() {
|
||||
void testWithGenericBean() {
|
||||
beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class));
|
||||
beanFactory.registerBeanDefinition("doubleStore", new RootBeanDefinition(DoubleStore.class));
|
||||
beanFactory.registerBeanDefinition("floatStore", new RootBeanDefinition(FloatStore.class));
|
||||
@@ -126,7 +126,7 @@ public class LookupAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingletonWithoutMetadataCaching() {
|
||||
void testSingletonWithoutMetadataCaching() {
|
||||
beanFactory.setCacheBeanMetadata(false);
|
||||
|
||||
beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class));
|
||||
@@ -139,7 +139,7 @@ public class LookupAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrototypeWithoutMetadataCaching() {
|
||||
void testPrototypeWithoutMetadataCaching() {
|
||||
beanFactory.setCacheBeanMetadata(false);
|
||||
|
||||
beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class, BeanDefinition.SCOPE_PROTOTYPE, null));
|
||||
|
||||
+12
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,35 +35,35 @@ import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ParameterResolutionDelegate}.
|
||||
* Tests for {@link ParameterResolutionDelegate}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @author Juergen Hoeller
|
||||
* @author Loïc Ledoyen
|
||||
*/
|
||||
public class ParameterResolutionTests {
|
||||
class ParameterResolutionTests {
|
||||
|
||||
@Test
|
||||
public void isAutowirablePreconditions() {
|
||||
void isAutowirablePreconditions() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
ParameterResolutionDelegate.isAutowirable(null, 0))
|
||||
.withMessageContaining("Parameter must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotatedParametersInMethodAreCandidatesForAutowiring() throws Exception {
|
||||
void annotatedParametersInMethodAreCandidatesForAutowiring() throws Exception {
|
||||
Method method = getClass().getDeclaredMethod("autowirableMethod", String.class, String.class, String.class, String.class);
|
||||
assertAutowirableParameters(method);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotatedParametersInTopLevelClassConstructorAreCandidatesForAutowiring() throws Exception {
|
||||
void annotatedParametersInTopLevelClassConstructorAreCandidatesForAutowiring() throws Exception {
|
||||
Constructor<?> constructor = AutowirableClass.class.getConstructor(String.class, String.class, String.class, String.class);
|
||||
assertAutowirableParameters(constructor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotatedParametersInInnerClassConstructorAreCandidatesForAutowiring() throws Exception {
|
||||
void annotatedParametersInInnerClassConstructorAreCandidatesForAutowiring() throws Exception {
|
||||
Class<?> innerClass = AutowirableClass.InnerAutowirableClass.class;
|
||||
assertThat(ClassUtils.isInnerClass(innerClass)).isTrue();
|
||||
Constructor<?> constructor = innerClass.getConstructor(AutowirableClass.class, String.class, String.class);
|
||||
@@ -81,7 +81,7 @@ public class ParameterResolutionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonAnnotatedParametersInTopLevelClassConstructorAreNotCandidatesForAutowiring() throws Exception {
|
||||
void nonAnnotatedParametersInTopLevelClassConstructorAreNotCandidatesForAutowiring() throws Exception {
|
||||
Constructor<?> notAutowirableConstructor = AutowirableClass.class.getConstructor(String.class);
|
||||
|
||||
Parameter[] parameters = notAutowirableConstructor.getParameters();
|
||||
@@ -92,21 +92,21 @@ public class ParameterResolutionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveDependencyPreconditionsForParameter() {
|
||||
void resolveDependencyPreconditionsForParameter() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> ParameterResolutionDelegate.resolveDependency(null, 0, null, mock()))
|
||||
.withMessageContaining("Parameter must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveDependencyPreconditionsForContainingClass() throws Exception {
|
||||
void resolveDependencyPreconditionsForContainingClass() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
ParameterResolutionDelegate.resolveDependency(getParameter(), 0, null, null))
|
||||
.withMessageContaining("Containing class must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveDependencyPreconditionsForBeanFactory() throws Exception {
|
||||
void resolveDependencyPreconditionsForBeanFactory() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
ParameterResolutionDelegate.resolveDependency(getParameter(), 0, getClass(), null))
|
||||
.withMessageContaining("AutowireCapableBeanFactory must not be null");
|
||||
@@ -118,7 +118,7 @@ public class ParameterResolutionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveDependencyForAnnotatedParametersInTopLevelClassConstructor() throws Exception {
|
||||
void resolveDependencyForAnnotatedParametersInTopLevelClassConstructor() throws Exception {
|
||||
Constructor<?> constructor = AutowirableClass.class.getConstructor(String.class, String.class, String.class, String.class);
|
||||
|
||||
AutowireCapableBeanFactory beanFactory = mock();
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -692,7 +692,7 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getObject() throws Exception {
|
||||
public String getObject() {
|
||||
return getPrefix() + " " + getName();
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,11 +26,11 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.aot.test.generate.TestGenerationContext;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.annotation.InjectAnnotationBeanPostProcessorTests.StringFactoryBean;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.testfixture.beans.factory.DummyFactory;
|
||||
import org.springframework.beans.testfixture.beans.factory.StringFactoryBean;
|
||||
import org.springframework.beans.testfixture.beans.factory.aot.GenericFactoryBean;
|
||||
import org.springframework.beans.testfixture.beans.factory.aot.MockBeanRegistrationCode;
|
||||
import org.springframework.beans.testfixture.beans.factory.aot.MockBeanRegistrationsCode;
|
||||
@@ -275,7 +275,7 @@ class DefaultBeanRegistrationCodeFragmentsTests {
|
||||
static class PrivilegedTestBeanFactoryBean implements FactoryBean<SimpleBean> {
|
||||
|
||||
@Override
|
||||
public SimpleBean getObject() throws Exception {
|
||||
public SimpleBean getObject() {
|
||||
return new SimpleBean();
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user