mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
444 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 | |||
| d4406507d0 | |||
| a612518f96 | |||
| ec0ec7a0d6 | |||
| 0970b1dc7a | |||
| a01c6d57bb | |||
| 8d4deca2a6 | |||
| cd64e6676c | |||
| 2acc7c609f | |||
| 409cecfff9 | |||
| 3c2c9ca186 | |||
| 75da9c3c47 | |||
| 952223dcf9 | |||
| 125e2902be | |||
| 4d838c1092 | |||
| c75c0ae2d5 | |||
| c0683cd30b | |||
| 7471fd1dd0 | |||
| 1c58511cb2 | |||
| 8de0fadd09 | |||
| da01e0c6e2 | |||
| b87852612b | |||
| 7adc2f0779 | |||
| 33b28fe5bf | |||
| b85fcb6aec | |||
| 134bb6e31f | |||
| 240a75f313 | |||
| 6dcba4de2c | |||
| 6bb9775309 | |||
| eae53560e4 | |||
| f0abdf2264 | |||
| c7f24efc27 | |||
| 07d2571e0b | |||
| 8c51315cd6 | |||
| e8cd26bbf0 | |||
| 9aded3fcad | |||
| aabe4d0b07 | |||
| 570074259d | |||
| f962211e0a | |||
| 6077c998d1 | |||
| 57b8100a06 | |||
| 7432a96b48 | |||
| a01384068a | |||
| d75a7c3818 | |||
| e2c2268c39 | |||
| b510bc3bab | |||
| b6364e3665 | |||
| f29bfd9769 | |||
| 361dfd1ae4 | |||
| 8704ad98a7 | |||
| c57b7e8418 | |||
| 77b0382a6c | |||
| a7f9da1670 | |||
| b782747472 | |||
| 69bc4e2828 | |||
| e4e2224449 | |||
| d919930d83 | |||
| afc1f37616 | |||
| 748dd94dab | |||
| b3a3b79b44 | |||
| 91b9a75371 | |||
| b78aed99ea | |||
| 2eba3510f7 | |||
| 56afd38148 | |||
| 33e4129155 | |||
| 0717ea5ca5 | |||
| 3b4c7a8906 | |||
| 2e07f9ab33 | |||
| dd23b1d156 | |||
| 753409083d | |||
| e36d035f58 | |||
| 302cdeeee6 | |||
| 61dd9fce73 | |||
| 7a221eb581 | |||
| 2e5d1daeff | |||
| bf6cb7cd89 | |||
| 2c053b34f0 | |||
| 438c3818cc | |||
| f14b122c9c | |||
| 9f305bfaab | |||
| d410872e4f | |||
| 8fe2c780df | |||
| b53ffa3855 | |||
| 25537938d6 | |||
| 9704b809b1 | |||
| 0e6c17f518 | |||
| 1afea0b144 | |||
| 7b95bd72f7 | |||
| fdcea58a53 | |||
| ef4ffa0005 | |||
| 2e3d13331a | |||
| 448e753184 | |||
| 6b53f37030 | |||
| afcd03bddc | |||
| 7b16ef90f1 | |||
| e2852e7355 | |||
| 1a63257b12 | |||
| 66e405525b | |||
| 59815cefce | |||
| 785ad399e9 | |||
| 3f9a809c32 | |||
| c74d60b9fe | |||
| db48813181 | |||
| a596c0e226 | |||
| 462ef95904 | |||
| 52d4b83dba | |||
| aa347e5fe6 | |||
| ceba4162bb | |||
| 21560bccd3 | |||
| 1da40b84e7 | |||
| 6f11716b6f | |||
| 47fe61ef79 | |||
| 8a82da43c9 | |||
| cb60f74556 | |||
| 62b3d7a963 | |||
| b69e5acfe3 | |||
| d71853f105 | |||
| 490b5c77fc | |||
| 8ed04b5dd1 | |||
| 87d37a21aa | |||
| eee2569bff | |||
| dbec3f1fa1 | |||
| e870912fa2 | |||
| 99f50ebeb4 | |||
| cd62dfe3a9 | |||
| 7cdacf3083 | |||
| 0bec8125a4 | |||
| da32e3d39e | |||
| 47cdc7c5f0 | |||
| decb22a93d | |||
| d59b2924d3 | |||
| c05b4ce776 | |||
| 3a53446a2b | |||
| d204dd2dbe | |||
| 0dbb0f5c14 | |||
| e452c2e89c | |||
| 6ea9fdbf77 | |||
| 8ff687b68c | |||
| bf1c179b7f | |||
| 16ac495084 | |||
| a506238ef6 | |||
| 33af98b6d6 | |||
| edfe179291 | |||
| 5f9702b2a4 | |||
| c56c304536 | |||
| 8090a52f5c | |||
| 19bca03aa2 | |||
| 0e6e225fb9 | |||
| 8ca82120e0 | |||
| 9ade52dbe2 | |||
| feef98b73c | |||
| 4a6c3e8f5d | |||
| f77713b7e0 | |||
| dc5bef16b4 | |||
| f3b1f37000 | |||
| df00aafdff | |||
| 7cf124b696 | |||
| 35fcbae8c6 | |||
| c8e6315a67 | |||
| 61be452402 | |||
| 0cbbd3a0d5 | |||
| c92a0bd493 | |||
| 755fd75512 | |||
| f8a40555af | |||
| 64d5e904e8 | |||
| 4e2d357318 | |||
| 264ec517f2 | |||
| b2e3be10d4 | |||
| 246833329f | |||
| 43700302c6 | |||
| 54ecbb2bc8 | |||
| 9eb2f29d4a | |||
| 97264c77dd | |||
| b17f3bc07b | |||
| a15f472898 | |||
| 0785256b2f | |||
| 95e250d4bd | |||
| dbad9fd208 | |||
| 657b1c6455 | |||
| 23dc5696d9 | |||
| a56bf87476 | |||
| c2745de60c | |||
| 710373d286 | |||
| 0599320bd8 | |||
| 8921be18de | |||
| 6ff75f157b | |||
| 15d9d9d06a | |||
| 894dce7cd8 | |||
| 34031ebea9 | |||
| b2757d9a21 | |||
| 655b4aacb7 | |||
| fb4455b396 | |||
| 677b03c36d | |||
| 85aa4b65dc | |||
| 0b61755ea3 | |||
| 3bcd30e811 | |||
| 121e3540cc | |||
| 0d8dee2878 | |||
| 3a6d0c1d5b | |||
| 16c6376b3f | |||
| 487dbf8140 | |||
| e95f8d2922 | |||
| 52b40ffb03 | |||
| d50b51e312 | |||
| 03b9edc36e | |||
| 824bc09d11 | |||
| 441e210533 | |||
| c329ed83ef | |||
| 48f3c08395 | |||
| c60926476a | |||
| e64b81eec4 | |||
| 5a3ad6b7c9 | |||
| 1410c466b7 | |||
| 8ffbecc7c3 | |||
| e6ab8a6d61 | |||
| 8567402969 | |||
| 4cc43b4ddc | |||
| bec385d310 | |||
| 878b33c56f | |||
| f46902869f | |||
| 617ba84577 | |||
| 3290260ef0 | |||
| fff50657d2 | |||
| 695559879e | |||
| 54f87f1ff7 | |||
| e24954068a | |||
| 500b495994 | |||
| 4b5cb5fa2e | |||
| f02e231406 | |||
| 19691b4bde | |||
| f146d09607 | |||
| 7d2ea7e7e1 | |||
| 8c9481d4c4 | |||
| ec905cb073 | |||
| 7006d0a80e | |||
| 69049a4b0f | |||
| 194747a80c | |||
| 7b14606d92 |
@@ -1,36 +0,0 @@
|
||||
Juergen Hoeller <jhoeller@vmware.com>
|
||||
Juergen Hoeller <jhoeller@vmware.com> <jhoeller@pivotal.io>
|
||||
Juergen Hoeller <jhoeller@vmware.com> <jhoeller@gopivotal.com>
|
||||
Rossen Stoyanchev <rstoyanchev@vmware.com>
|
||||
Rossen Stoyanchev <rstoyanchev@vmware.com> <rstoyanchev@pivotal.io>
|
||||
Rossen Stoyanchev <rstoyanchev@vmware.com> <rstoyanchev@gopivotal.com>
|
||||
Phillip Webb <pwebb@vmware.com>
|
||||
Phillip Webb <pwebb@vmware.com> <pwebb@pivotal.io>
|
||||
Phillip Webb <pwebb@vmware.com> <pwebb@gopivotal.com>
|
||||
Chris Beams <cbeams@vmware.com>
|
||||
Chris Beams <cbeams@vmware.com> <cbeams@pivotal.io>
|
||||
Chris Beams <cbeams@vmware.com> <cbeams@gopivotal.com>
|
||||
Arjen Poutsma <poutsmaa@vmware.com>
|
||||
Arjen Poutsma <poutsmaa@vmware.com> <apoutsma@pivotal.io>
|
||||
Arjen Poutsma <poutsmaa@vmware.com> <apoutsma@gopivotal.com>
|
||||
Arjen Poutsma <poutsmaa@vmware.com> <poutsma@mac.com>
|
||||
Arjen Poutsma <poutsmaa@vmware.com> <apoutsma@vmware.com>
|
||||
Oliver Drotbohm <odrotbohm@vmware.com>
|
||||
Oliver Drotbohm <odrotbohm@vmware.com> <ogierke@vmware.com>
|
||||
Oliver Drotbohm <odrotbohm@vmware.com> <ogierke@pivotal.io>
|
||||
Oliver Drotbohm <odrotbohm@vmware.com> <ogierke@gopivotal.com>
|
||||
Dave Syer <dsyer@vmware.com>
|
||||
Dave Syer <dsyer@vmware.com> <dsyer@pivotal.io>
|
||||
Dave Syer <dsyer@vmware.com> <dsyer@gopivotal.com>
|
||||
Dave Syer <dsyer@vmware.com> <david_syer@hotmail.com>
|
||||
Andy Clement <aclement@vmware.com>
|
||||
Andy Clement <aclement@vmware.com> <aclement@pivotal.io>
|
||||
Andy Clement <aclement@vmware.com> <aclement@gopivotal.com>
|
||||
Andy Clement <aclement@vmware.com> <andrew.clement@gmail.com>
|
||||
Sam Brannen <sbrannen@vmware.com>
|
||||
Sam Brannen <sbrannen@vmware.com> <sbrannen@pivotal.io>
|
||||
Sam Brannen <sbrannen@vmware.com> <sam@sambrannen.com>
|
||||
Simon Basle <sbasle@vmware.com>
|
||||
Simon Baslé <sbasle@vmware.com>
|
||||
<dmitry.katsubo@gmail.com> <dmitry.katsubo@gmai.com>
|
||||
Nick Williams <nicholas@nicholaswilliams.net>
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# <img src="framework-docs/src/docs/spring-framework.png" width="80" height="80"> Spring Framework [](https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-6.0.x?groups=Build") [](https://ge.spring.io/scans?search.rootProjectNames=spring)
|
||||
# <img src="framework-docs/src/docs/spring-framework.png" width="80" height="80"> Spring Framework [](https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-6.1.x?groups=Build") [](https://ge.spring.io/scans?search.rootProjectNames=spring)
|
||||
|
||||
This is the home of the Spring Framework: the foundation for all [Spring projects](https://spring.io/projects). Collectively the Spring Framework and the family of Spring projects are often referred to simply as "Spring".
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+3
-6
@@ -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
|
||||
@@ -16,6 +16,8 @@ ext {
|
||||
javaProjects = subprojects.findAll { !it.name.startsWith("framework-") }
|
||||
}
|
||||
|
||||
description = "Spring Framework"
|
||||
|
||||
configure(allprojects) { project ->
|
||||
apply plugin: "org.springframework.build.localdev"
|
||||
group = "org.springframework"
|
||||
@@ -116,8 +118,3 @@ configure([rootProject] + javaProjects) { project ->
|
||||
configure(moduleProjects) { project ->
|
||||
apply from: "${rootDir}/gradle/spring-module.gradle"
|
||||
}
|
||||
|
||||
configure(rootProject) {
|
||||
description = "Spring Framework"
|
||||
apply plugin: 'org.springframework.build.api-diff'
|
||||
}
|
||||
|
||||
@@ -22,21 +22,6 @@ but doesn't affect the classpath of dependent projects.
|
||||
This plugin does not provide a `provided` configuration, as the native `compileOnly` and `testCompileOnly`
|
||||
configurations are preferred.
|
||||
|
||||
### API Diff
|
||||
|
||||
This plugin uses the [Gradle JApiCmp](https://github.com/melix/japicmp-gradle-plugin) plugin
|
||||
to generate API Diff reports for each Spring Framework module. This plugin is applied once on the root
|
||||
project and creates tasks in each framework module. Unlike previous versions of this part of the build,
|
||||
there is no need for checking out a specific tag. The plugin will fetch the JARs we want to compare the
|
||||
current working version with. You can generate the reports for all modules or a single module:
|
||||
|
||||
```
|
||||
./gradlew apiDiff -PbaselineVersion=5.1.0.RELEASE
|
||||
./gradlew :spring-core:apiDiff -PbaselineVersion=5.1.0.RELEASE
|
||||
```
|
||||
|
||||
The reports are located under `build/reports/api-diff/$OLDVERSION_to_$NEWVERSION/`.
|
||||
|
||||
|
||||
### RuntimeHints Java Agent
|
||||
|
||||
|
||||
@@ -21,18 +21,13 @@ dependencies {
|
||||
checkstyle "io.spring.javaformat:spring-javaformat-checkstyle:${javaFormatVersion}"
|
||||
implementation "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}"
|
||||
implementation "org.jetbrains.kotlin:kotlin-compiler-embeddable:${kotlinVersion}"
|
||||
implementation "me.champeau.gradle:japicmp-gradle-plugin:0.3.0"
|
||||
implementation "org.gradle:test-retry-gradle-plugin:1.4.1"
|
||||
implementation "org.gradle:test-retry-gradle-plugin:1.5.6"
|
||||
implementation "io.spring.javaformat:spring-javaformat-gradle-plugin:${javaFormatVersion}"
|
||||
implementation "io.spring.nohttp:nohttp-gradle:0.0.11"
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
apiDiffPlugin {
|
||||
id = "org.springframework.build.api-diff"
|
||||
implementationClass = "org.springframework.build.api.ApiDiffPlugin"
|
||||
}
|
||||
conventionsPlugin {
|
||||
id = "org.springframework.build.conventions"
|
||||
implementationClass = "org.springframework.build.ConventionsPlugin"
|
||||
|
||||
@@ -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,142 +0,0 @@
|
||||
/*
|
||||
* 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.build.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import me.champeau.gradle.japicmp.JapicmpPlugin;
|
||||
import me.champeau.gradle.japicmp.JapicmpTask;
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
|
||||
import org.gradle.api.tasks.TaskProvider;
|
||||
import org.gradle.jvm.tasks.Jar;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* {@link Plugin} that applies the {@code "japicmp-gradle-plugin"}
|
||||
* and create tasks for all subprojects named {@code "spring-*"}, diffing the public API one by one
|
||||
* and creating the reports in {@code "build/reports/api-diff/$OLDVERSION_to_$NEWVERSION/"}.
|
||||
* <p>{@code "./gradlew apiDiff -PbaselineVersion=5.1.0.RELEASE"} will output the
|
||||
* reports for the API diff between the baseline version and the current one for all modules.
|
||||
* You can limit the report to a single module with
|
||||
* {@code "./gradlew :spring-core:apiDiff -PbaselineVersion=5.1.0.RELEASE"}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
public class ApiDiffPlugin implements Plugin<Project> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ApiDiffPlugin.class);
|
||||
|
||||
public static final String TASK_NAME = "apiDiff";
|
||||
|
||||
private static final String BASELINE_VERSION_PROPERTY = "baselineVersion";
|
||||
|
||||
private static final List<String> PACKAGE_INCLUDES = Collections.singletonList("org.springframework.*");
|
||||
|
||||
private static final URI SPRING_MILESTONE_REPOSITORY = URI.create("https://repo.spring.io/milestone");
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
if (project.hasProperty(BASELINE_VERSION_PROPERTY) && project.equals(project.getRootProject())) {
|
||||
project.getPluginManager().apply(JapicmpPlugin.class);
|
||||
project.getPlugins().withType(JapicmpPlugin.class,
|
||||
plugin -> applyApiDiffConventions(project));
|
||||
}
|
||||
}
|
||||
|
||||
private void applyApiDiffConventions(Project project) {
|
||||
String baselineVersion = project.property(BASELINE_VERSION_PROPERTY).toString();
|
||||
project.subprojects(subProject -> {
|
||||
if (subProject.getName().startsWith("spring-")) {
|
||||
createApiDiffTask(baselineVersion, subProject);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void createApiDiffTask(String baselineVersion, Project project) {
|
||||
if (isProjectEligible(project)) {
|
||||
// Add Spring Milestone repository for generating diffs against previous milestones
|
||||
project.getRootProject()
|
||||
.getRepositories()
|
||||
.maven(mavenArtifactRepository -> mavenArtifactRepository.setUrl(SPRING_MILESTONE_REPOSITORY));
|
||||
JapicmpTask apiDiff = project.getTasks().create(TASK_NAME, JapicmpTask.class);
|
||||
apiDiff.setDescription("Generates an API diff report with japicmp");
|
||||
apiDiff.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP);
|
||||
|
||||
apiDiff.setOldClasspath(createBaselineConfiguration(baselineVersion, project));
|
||||
TaskProvider<Jar> jar = project.getTasks().withType(Jar.class).named("jar");
|
||||
apiDiff.setNewArchives(project.getLayout().files(jar.get().getArchiveFile().get().getAsFile()));
|
||||
apiDiff.setNewClasspath(getRuntimeClassPath(project));
|
||||
apiDiff.setPackageIncludes(PACKAGE_INCLUDES);
|
||||
apiDiff.setOnlyModified(true);
|
||||
apiDiff.setIgnoreMissingClasses(true);
|
||||
// Ignore Kotlin metadata annotations since they contain
|
||||
// illegal HTML characters and fail the report generation
|
||||
apiDiff.setAnnotationExcludes(Collections.singletonList("@kotlin.Metadata"));
|
||||
|
||||
apiDiff.setHtmlOutputFile(getOutputFile(baselineVersion, project));
|
||||
|
||||
apiDiff.dependsOn(project.getTasks().getByName("jar"));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isProjectEligible(Project project) {
|
||||
return project.getPlugins().hasPlugin(JavaPlugin.class)
|
||||
&& project.getPlugins().hasPlugin(MavenPublishPlugin.class);
|
||||
}
|
||||
|
||||
private Configuration createBaselineConfiguration(String baselineVersion, Project project) {
|
||||
String baseline = String.join(":",
|
||||
project.getGroup().toString(), project.getName(), baselineVersion);
|
||||
Dependency baselineDependency = project.getDependencies().create(baseline + "@jar");
|
||||
Configuration baselineConfiguration = project.getRootProject().getConfigurations().detachedConfiguration(baselineDependency);
|
||||
try {
|
||||
// eagerly resolve the baseline configuration to check whether this is a new Spring module
|
||||
baselineConfiguration.resolve();
|
||||
return baselineConfiguration;
|
||||
}
|
||||
catch (GradleException exception) {
|
||||
logger.warn("Could not resolve {} - assuming this is a new Spring module.", baseline);
|
||||
}
|
||||
return project.getRootProject().getConfigurations().detachedConfiguration();
|
||||
}
|
||||
|
||||
private Configuration getRuntimeClassPath(Project project) {
|
||||
return project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME);
|
||||
}
|
||||
|
||||
private File getOutputFile(String baseLineVersion, Project project) {
|
||||
String buildDirectoryPath = project.getRootProject()
|
||||
.getLayout().getBuildDirectory().getAsFile().get().getAbsolutePath();
|
||||
Path outDir = Paths.get(buildDirectoryPath, "reports", "api-diff",
|
||||
baseLineVersion + "_to_" + project.getRootProject().getVersion());
|
||||
return project.file(outDir.resolve(project.getName() + ".html").toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:jammy-20231004
|
||||
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/19/GPL/openjdk-22-ea+19_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
|
||||
|
||||
@@ -27,8 +27,8 @@ javadoc {
|
||||
author = true
|
||||
header = rootProject.description
|
||||
use = true
|
||||
overview = "$rootProject.rootDir/framework-docs/src/docs/api/overview.html"
|
||||
destinationDir = file("${project.buildDir}/docs/javadoc-api")
|
||||
overview = project.relativePath("$rootProject.rootDir/framework-docs/src/docs/api/overview.html")
|
||||
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")
|
||||
}
|
||||
|
||||
|
||||
@@ -17,16 +17,73 @@ asciidoc:
|
||||
# FIXME: the copyright is not removed
|
||||
# FIXME: The package is not renamed
|
||||
chomp: 'all'
|
||||
fold: 'all'
|
||||
include-java: 'example$docs-src/main/java/org/springframework/docs'
|
||||
spring-framework-main-code: 'https://github.com/spring-projects/spring-framework/tree/main'
|
||||
spring-site: 'https://spring.io'
|
||||
spring-site-blog: '{spring-site}/blog'
|
||||
spring-site-cve: "{spring-site}/security"
|
||||
spring-site-guides: '{spring-site}/guides'
|
||||
spring-site-projects: '{spring-site}/projects'
|
||||
spring-site-tools: "{spring-site}/tools"
|
||||
spring-org: 'spring-projects'
|
||||
spring-github-org: "https://github.com/{spring-org}"
|
||||
spring-framework-github: "https://github.com/{spring-org}/spring-framework"
|
||||
spring-framework-code: '{spring-framework-github}/tree/main'
|
||||
spring-framework-issues: '{spring-framework-github}/issues'
|
||||
spring-framework-wiki: '{spring-framework-github}/wiki'
|
||||
# Docs
|
||||
docs-site: 'https://docs.spring.io'
|
||||
docs-spring: "{docs-site}/spring-framework/docs/{spring-version}"
|
||||
docs-spring-framework: '{docs-site}/spring-framework/docs/{spring-version}'
|
||||
api-spring-framework: '{docs-spring-framework}/javadoc-api/org/springframework'
|
||||
docs-graalvm: 'https://www.graalvm.org/22.3/reference-manual'
|
||||
docs-spring-boot: '{docs-site}/spring-boot/docs/current/reference'
|
||||
spring-framework-docs-root: '{docs-site}/spring-framework/docs'
|
||||
spring-framework-api: '{spring-framework-docs-root}/{spring-version}/javadoc-api/org/springframework'
|
||||
spring-framework-api-kdoc: '{spring-framework-docs-root}/{spring-version}/kdoc-api'
|
||||
spring-framework-reference: '{spring-framework-docs-root}/{spring-version}/reference'
|
||||
#
|
||||
# Other Spring portfolio projects
|
||||
spring-boot-docs: '{docs-site}/spring-boot/docs/current/reference/html'
|
||||
spring-boot-issues: '{spring-github-org}/spring-boot/issues'
|
||||
# TODO add more projects / links or just build up on {docs-site}?
|
||||
# TODO rename the below using new conventions
|
||||
docs-spring-gemfire: '{docs-site}/spring-gemfire/docs/current/reference'
|
||||
docs-spring-security: '{docs-site}/spring-security/reference'
|
||||
gh-rsocket: 'https://github.com/rsocket'
|
||||
gh-rsocket-extensions: '{gh-rsocket}/rsocket/blob/master/Extensions'
|
||||
gh-rsocket-java: '{gh-rsocket}/rsocket-java{gh-rsocket}/rsocket-java'
|
||||
docs-spring-session: '{docs-site}/spring-session/reference'
|
||||
#
|
||||
# External projects URLs and related attributes
|
||||
aspectj-site: 'https://www.eclipse.org/aspectj'
|
||||
aspectj-docs: "{aspectj-site}/doc/released"
|
||||
aspectj-api: "{aspectj-docs}/runtime-api"
|
||||
aspectj-docs-devguide: "{aspectj-docs}/devguide"
|
||||
aspectj-docs-progguide: "{aspectj-docs}/progguide"
|
||||
assertj-docs: 'https://assertj.github.io/doc'
|
||||
baeldung-blog: 'https://www.baeldung.com'
|
||||
bean-validation-site: 'https://beanvalidation.org'
|
||||
graalvm-docs: 'https://www.graalvm.org/22.3/reference-manual'
|
||||
hibernate-validator-site: 'https://hibernate.org/validator/'
|
||||
jackson-docs: 'https://fasterxml.github.io'
|
||||
jackson-github-org: 'https://github.com/FasterXML'
|
||||
java-api: 'https://docs.oracle.com/en/java/javase/17/docs/api'
|
||||
java-tutorial: 'https://docs.oracle.com/javase/tutorial'
|
||||
JSR: 'https://www.jcp.org/en/jsr/detail?id='
|
||||
kotlin-site: 'https://kotlinlang.org'
|
||||
kotlin-docs: '{kotlin-site}/docs'
|
||||
kotlin-api: '{kotlin-site}/api/latest'
|
||||
kotlin-coroutines-api: '{kotlin-site}/api/kotlinx.coroutines'
|
||||
kotlin-github-org: 'https://github.com/Kotlin'
|
||||
kotlin-issues: 'https://youtrack.jetbrains.com/issue'
|
||||
reactive-streams-site: 'https://www.reactive-streams.org'
|
||||
reactive-streams-spec: 'https://github.com/reactive-streams/reactive-streams-jvm/blob/master/README.md#specification'
|
||||
reactor-github-org: 'https://github.com/reactor'
|
||||
reactor-site: 'https://projectreactor.io'
|
||||
rsocket-github-org: 'https://github.com/rsocket'
|
||||
rsocket-java: '{rsocket-github-org}/rsocket-java'
|
||||
rsocket-java-code: '{rsocket-java}/tree/master/'
|
||||
rsocket-protocol-extensions: '{rsocket-github-org}/rsocket/tree/master/Extensions'
|
||||
rsocket-site: 'https://rsocket.io'
|
||||
rfc-site: 'https://datatracker.ietf.org/doc/html'
|
||||
sockjs-client: 'https://github.com/sockjs/sockjs-client'
|
||||
sockjs-protocol: 'https://github.com/sockjs/sockjs-protocol'
|
||||
sockjs-protocol-site: "https://sockjs.github.io/sockjs-protocol"
|
||||
stackoverflow-site: 'https://stackoverflow.com'
|
||||
stackoverflow-questions: '{stackoverflow-site}/questions'
|
||||
stackoverflow-spring-tag: "{stackoverflow-questions}/tagged/spring"
|
||||
stackoverflow-spring-kotlin-tags: "{stackoverflow-spring-tag}+kotlin"
|
||||
testcontainers-site: 'https://www.testcontainers.org'
|
||||
@@ -421,6 +421,7 @@
|
||||
*** xref:integration/cache/specific-config.adoc[]
|
||||
** xref:integration/observability.adoc[]
|
||||
** xref:integration/checkpoint-restore.adoc[]
|
||||
** xref:integration/class-data-sharing.adoc[]
|
||||
** xref:integration/appendix.adoc[]
|
||||
* xref:languages.adoc[]
|
||||
** xref:languages/kotlin.adoc[]
|
||||
@@ -438,4 +439,4 @@
|
||||
** xref:languages/groovy.adoc[]
|
||||
** xref:languages/dynamic.adoc[]
|
||||
* xref:appendix.adoc[]
|
||||
* https://github.com/spring-projects/spring-framework/wiki[Wiki]
|
||||
* {spring-framework-wiki}[Wiki]
|
||||
@@ -8,7 +8,7 @@ within the core Spring Framework.
|
||||
[[appendix-spring-properties]]
|
||||
== Spring Properties
|
||||
|
||||
{api-spring-framework}/core/SpringProperties.html[`SpringProperties`] is a static holder
|
||||
{spring-framework-api}/core/SpringProperties.html[`SpringProperties`] is a static holder
|
||||
for properties that control certain low-level aspects of the Spring Framework. Users can
|
||||
configure these properties via JVM system properties or programmatically via the
|
||||
`SpringProperties.setProperty(String key, String value)` method. The latter may be
|
||||
@@ -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
|
||||
{api-spring-framework}++/beans/StandardBeanInfoFactory.html#IGNORE_BEANINFO_PROPERTY_NAME++[`CachedIntrospectionResults`]
|
||||
{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].
|
||||
@@ -36,7 +74,7 @@ xref:core/expressions/evaluation.adoc#expressions-compiler-configuration[Spring
|
||||
| Instructs Spring to ignore operating system environment variables if a Spring
|
||||
`Environment` property -- for example, a placeholder in a configuration String -- isn't
|
||||
resolvable otherwise. See
|
||||
{api-spring-framework}++/core/env/AbstractEnvironment.html#IGNORE_GETENV_PROPERTY_NAME++[`AbstractEnvironment`]
|
||||
{spring-framework-api}++/core/env/AbstractEnvironment.html#IGNORE_GETENV_PROPERTY_NAME++[`AbstractEnvironment`]
|
||||
for details.
|
||||
|
||||
| `spring.jdbc.getParameterType.ignore`
|
||||
@@ -47,12 +85,12 @@ See the note in xref:data-access/jdbc/advanced.adoc#jdbc-batch-list[Batch Operat
|
||||
| Instructs Spring to ignore a default JNDI environment, as an optimization for scenarios
|
||||
where nothing is ever to be found for such JNDI fallback searches to begin with, avoiding
|
||||
the repeated JNDI lookup overhead. See
|
||||
{api-spring-framework}++/jndi/JndiLocatorDelegate.html#IGNORE_JNDI_PROPERTY_NAME++[`JndiLocatorDelegate`]
|
||||
{spring-framework-api}++/jndi/JndiLocatorDelegate.html#IGNORE_JNDI_PROPERTY_NAME++[`JndiLocatorDelegate`]
|
||||
for details.
|
||||
|
||||
| `spring.objenesis.ignore`
|
||||
| Instructs Spring to ignore Objenesis, not even attempting to use it. See
|
||||
{api-spring-framework}++/objenesis/SpringObjenesis.html#IGNORE_OBJENESIS_PROPERTY_NAME++[`SpringObjenesis`]
|
||||
{spring-framework-api}++/objenesis/SpringObjenesis.html#IGNORE_OBJENESIS_PROPERTY_NAME++[`SpringObjenesis`]
|
||||
for details.
|
||||
|
||||
| `spring.test.aot.processing.failOnError`
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
// Spring Portfolio
|
||||
:docs-site: https://docs.spring.io
|
||||
:docs-spring-boot: {docs-site}/spring-boot/docs/current/reference
|
||||
:docs-spring-gemfire: {docs-site}/spring-gemfire/docs/current/reference
|
||||
:docs-spring-security: {docs-site}/spring-security/reference
|
||||
// spring-asciidoctor-backends Settings
|
||||
:chomp: default headers packages
|
||||
:fold: all
|
||||
// Spring Framework
|
||||
:docs-spring-framework: {docs-site}/spring-framework/docs/{spring-version}
|
||||
:api-spring-framework: {docs-spring-framework}/javadoc-api/org/springframework
|
||||
:docs-java: {docdir}/../../main/java/org/springframework/docs
|
||||
:docs-kotlin: {docdir}/../../main/kotlin/org/springframework/docs
|
||||
:docs-resources: {docdir}/../../main/resources
|
||||
:spring-framework-main-code: https://github.com/spring-projects/spring-framework/tree/main
|
||||
// Third-party Links
|
||||
:docs-graalvm: https://www.graalvm.org/22.3/reference-manual
|
||||
:gh-rsocket: https://github.com/rsocket
|
||||
:gh-rsocket-extensions: {gh-rsocket}/rsocket/blob/master/Extensions
|
||||
:gh-rsocket-java: {gh-rsocket}/rsocket-java
|
||||
@@ -12,5 +12,5 @@ support for new custom advice types be added without changing the core framework
|
||||
The only constraint on a custom `Advice` type is that it must implement the
|
||||
`org.aopalliance.aop.Advice` marker interface.
|
||||
|
||||
See the {api-spring-framework}/aop/framework/adapter/package-summary.html[`org.springframework.aop.framework.adapter`]
|
||||
See the {spring-framework-api}/aop/framework/adapter/package-summary.html[`org.springframework.aop.framework.adapter`]
|
||||
javadoc for further information.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -119,7 +119,7 @@ The following listing shows an example configuration:
|
||||
|
||||
Note that the target object (`businessObjectTarget` in the preceding example) must be a
|
||||
prototype. This lets the `PoolingTargetSource` implementation create new instances
|
||||
of the target to grow the pool as necessary. See the {api-spring-framework}/aop/target/AbstractPoolingTargetSource.html[javadoc of
|
||||
of the target to grow the pool as necessary. See the {spring-framework-api}/aop/target/AbstractPoolingTargetSource.html[javadoc of
|
||||
`AbstractPoolingTargetSource`] and the concrete subclass you wish to use for information
|
||||
about its properties. `maxSize` is the most basic and is always guaranteed to be present.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -52,7 +52,7 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
See the {api-spring-framework}/aop/aspectj/annotation/AspectJProxyFactory.html[javadoc] for more information.
|
||||
See the {spring-framework-api}/aop/aspectj/annotation/AspectJProxyFactory.html[javadoc] for more information.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
@AspectJ refers to a style of declaring aspects as regular Java classes annotated with
|
||||
annotations. The @AspectJ style was introduced by the
|
||||
https://www.eclipse.org/aspectj[AspectJ project] as part of the AspectJ 5 release. Spring
|
||||
{aspectj-site}[AspectJ project] as part of the AspectJ 5 release. Spring
|
||||
interprets the same annotations as AspectJ 5, using a library supplied by AspectJ
|
||||
for pointcut parsing and matching. The AOP runtime is still pure Spring AOP, though, and
|
||||
there is no dependency on the AspectJ compiler or weaver.
|
||||
|
||||
@@ -482,7 +482,7 @@ The `JoinPoint` interface provides a number of useful methods:
|
||||
* `getSignature()`: Returns a description of the method that is being advised.
|
||||
* `toString()`: Prints a useful description of the method being advised.
|
||||
|
||||
See the https://www.eclipse.org/aspectj/doc/released/runtime-api/org/aspectj/lang/JoinPoint.html[javadoc] for more detail.
|
||||
See the {aspectj-api}/org/aspectj/lang/JoinPoint.html[javadoc] for more detail.
|
||||
|
||||
[[aop-ataspectj-advice-params-passing]]
|
||||
=== Passing Parameters to Advice
|
||||
@@ -730,7 +730,7 @@ of determining parameter names, an exception will be thrown.
|
||||
flag for `javac`. Recommended approach on Java 8+.
|
||||
`AspectJAdviceParameterNameDiscoverer` :: Deduces parameter names from the pointcut
|
||||
expression, `returning`, and `throwing` clauses. See the
|
||||
{api-spring-framework}/aop/aspectj/AspectJAdviceParameterNameDiscoverer.html[javadoc]
|
||||
{spring-framework-api}/aop/aspectj/AspectJAdviceParameterNameDiscoverer.html[javadoc]
|
||||
for details on the algorithm used.
|
||||
|
||||
[[aop-ataspectj-advice-params-names-explicit]]
|
||||
|
||||
@@ -36,9 +36,9 @@ Kotlin::
|
||||
|
||||
The pointcut expression that forms the value of the `@Pointcut` annotation is a regular
|
||||
AspectJ pointcut expression. For a full discussion of AspectJ's pointcut language, see
|
||||
the https://www.eclipse.org/aspectj/doc/released/progguide/index.html[AspectJ
|
||||
the {aspectj-docs-progguide}/index.html[AspectJ
|
||||
Programming Guide] (and, for extensions, the
|
||||
https://www.eclipse.org/aspectj/doc/released/adk15notebook/index.html[AspectJ 5
|
||||
{aspectj-docs}/adk15notebook/index.html[AspectJ 5
|
||||
Developer's Notebook]) or one of the books on AspectJ (such as _Eclipse AspectJ_, by Colyer
|
||||
et al., or _AspectJ in Action_, by Ramnivas Laddad).
|
||||
|
||||
@@ -392,7 +392,7 @@ method that takes no parameters, whereas `(..)` matches any number (zero or more
|
||||
The `({asterisk})` pattern matches a method that takes one parameter of any type.
|
||||
`(*,String)` matches a method that takes two parameters. The first can be of any type, while the
|
||||
second must be a `String`. Consult the
|
||||
https://www.eclipse.org/aspectj/doc/released/progguide/semantics-pointcuts.html[Language
|
||||
{aspectj-docs-progguide}/semantics-pointcuts.html[Language
|
||||
Semantics] section of the AspectJ Programming Guide for more information.
|
||||
|
||||
The following examples show some common pointcut expressions:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
= Further Resources
|
||||
:page-section-summary-toc: 1
|
||||
|
||||
More information on AspectJ can be found on the https://www.eclipse.org/aspectj[AspectJ website].
|
||||
More information on AspectJ can be found on the {aspectj-site}[AspectJ website].
|
||||
|
||||
_Eclipse AspectJ_ by Adrian Colyer et. al. (Addison-Wesley, 2005) provides a
|
||||
comprehensive introduction and reference for the AspectJ language.
|
||||
|
||||
@@ -136,7 +136,7 @@ using Spring in accordance with the properties of the annotation". In this conte
|
||||
"initialization" refers to newly instantiated objects (for example, objects instantiated
|
||||
with the `new` operator) as well as to `Serializable` objects that are undergoing
|
||||
deserialization (for example, through
|
||||
https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html[readResolve()]).
|
||||
{java-api}/java.base/java/io/Serializable.html[readResolve()]).
|
||||
|
||||
[NOTE]
|
||||
=====
|
||||
@@ -168,14 +168,13 @@ Kotlin::
|
||||
|
||||
You can find more information about the language semantics of the various pointcut
|
||||
types in AspectJ
|
||||
https://www.eclipse.org/aspectj/doc/next/progguide/semantics-joinPoints.html[in this
|
||||
appendix] of the https://www.eclipse.org/aspectj/doc/next/progguide/index.html[AspectJ
|
||||
Programming Guide].
|
||||
{aspectj-docs-progguide}/semantics-joinPoints.html[in this appendix] of the
|
||||
{aspectj-docs-progguide}/index.html[AspectJ Programming Guide].
|
||||
=====
|
||||
|
||||
For this to work, the annotated types must be woven with the AspectJ weaver. You can
|
||||
either use a build-time Ant or Maven task to do this (see, for example, the
|
||||
https://www.eclipse.org/aspectj/doc/released/devguide/antTasks.html[AspectJ Development
|
||||
{aspectj-docs-devguide}/antTasks.html[AspectJ Development
|
||||
Environment Guide]) or load-time weaving (see xref:core/aop/using-aspectj.adoc#aop-aj-ltw[Load-time Weaving with AspectJ in the Spring Framework]). The
|
||||
`AnnotationBeanConfigurerAspect` itself needs to be configured by Spring (in order to obtain
|
||||
a reference to the bean factory that is to be used to configure new objects). If you
|
||||
@@ -399,7 +398,7 @@ The focus of this section is on configuring and using LTW in the specific contex
|
||||
Spring Framework. This section is not a general introduction to LTW. For full details on
|
||||
the specifics of LTW and configuring LTW with only AspectJ (with Spring not being
|
||||
involved at all), see the
|
||||
https://www.eclipse.org/aspectj/doc/released/devguide/ltw.html[LTW section of the AspectJ
|
||||
{aspectj-docs-devguide}/ltw.html[LTW section of the AspectJ
|
||||
Development Environment Guide].
|
||||
|
||||
The value that the Spring Framework brings to AspectJ LTW is in enabling much
|
||||
@@ -421,7 +420,7 @@ who typically are in charge of the deployment configuration, such as the launch
|
||||
Now that the sales pitch is over, let us first walk through a quick example of AspectJ
|
||||
LTW that uses Spring, followed by detailed specifics about elements introduced in the
|
||||
example. For a complete example, see the
|
||||
https://github.com/spring-projects/spring-petclinic[Petclinic sample application].
|
||||
{spring-github-org}/spring-petclinic[Petclinic sample application].
|
||||
|
||||
|
||||
[[aop-aj-ltw-first-example]]
|
||||
@@ -534,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
|
||||
@@ -621,7 +625,7 @@ java -javaagent:C:/projects/xyz/lib/spring-instrument.jar com.xyz.Main
|
||||
----
|
||||
|
||||
The `-javaagent` is a flag for specifying and enabling
|
||||
https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/package-summary.html[agents
|
||||
{java-api}/java.instrument/java/lang/instrument/package-summary.html[agents
|
||||
to instrument programs that run on the JVM]. The Spring Framework ships with such an
|
||||
agent, the `InstrumentationSavingAgent`, which is packaged in the
|
||||
`spring-instrument.jar` that was supplied as the value of the `-javaagent` argument in
|
||||
@@ -715,13 +719,32 @@ 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
|
||||
https://www.eclipse.org/aspectj/doc/released/devguide/ltw-configuration.html[AspectJ reference
|
||||
{aspectj-docs-devguide}/ltw-configuration.html[AspectJ reference
|
||||
documentation]. Because the `aop.xml` file is 100% AspectJ, we do not describe it further here.
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ Applying such optimizations early implies the following restrictions:
|
||||
* The beans defined in your application cannot change at runtime, meaning:
|
||||
** `@Profile`, in particular profile-specific configuration needs to be chosen at build time.
|
||||
** `Environment` properties that impact the presence of a bean (`@Conditional`) are only considered at build time.
|
||||
* Bean definitions with instance suppliers (lambdas or method references) cannot be transformed ahead-of-time (see related https://github.com/spring-projects/spring-framework/issues/29555[spring-framework#29555] issue).
|
||||
* Bean definitions with instance suppliers (lambdas or method references) cannot be transformed ahead-of-time (see related {spring-framework-issues}/29555[spring-framework#29555] issue).
|
||||
* Make sure that the bean type is as precise as possible.
|
||||
|
||||
TIP: See also the xref:core/aot.adoc#aot.bestpractices[] section.
|
||||
@@ -27,7 +27,7 @@ A Spring AOT processed application typically generates:
|
||||
|
||||
* Java source code
|
||||
* Bytecode (usually for dynamic proxies)
|
||||
* {api-spring-framework}/aot/hint/RuntimeHints.html[`RuntimeHints`] for the use of reflection, resource loading, serialization, and JDK proxies.
|
||||
* {spring-framework-api}/aot/hint/RuntimeHints.html[`RuntimeHints`] for the use of reflection, resource loading, serialization, and JDK proxies.
|
||||
|
||||
NOTE: At the moment, AOT is focused on allowing Spring applications to be deployed as native images using GraalVM.
|
||||
We intend to support more JVM-based use cases in future generations.
|
||||
@@ -35,7 +35,7 @@ We intend to support more JVM-based use cases in future generations.
|
||||
[[aot.basics]]
|
||||
== AOT engine overview
|
||||
|
||||
The entry point of the AOT engine for processing an `ApplicationContext` arrangement is `ApplicationContextAotGenerator`. It takes care of the following steps, based on a `GenericApplicationContext` that represents the application to optimize and a {api-spring-framework}/aot/generate/GenerationContext.html[`GenerationContext`]:
|
||||
The entry point of the AOT engine for processing an `ApplicationContext` arrangement is `ApplicationContextAotGenerator`. It takes care of the following steps, based on a `GenericApplicationContext` that represents the application to optimize and a {spring-framework-api}/aot/generate/GenerationContext.html[`GenerationContext`]:
|
||||
|
||||
* Refresh an `ApplicationContext` for AOT processing. Contrary to a traditional refresh, this version only creates bean definitions, not bean instances.
|
||||
* Invoke the available `BeanFactoryInitializationAotProcessor` implementations and apply their contributions against the `GenerationContext`.
|
||||
@@ -81,7 +81,7 @@ Once this part completes, the `BeanFactory` contains the bean definitions that a
|
||||
[[aot.bean-factory-initialization-contributions]]
|
||||
== Bean Factory Initialization AOT Contributions
|
||||
|
||||
Components that want to participate in this step can implement the {api-spring-framework}/beans/factory/aot/BeanFactoryInitializationAotProcessor.html[`BeanFactoryInitializationAotProcessor`] interface.
|
||||
Components that want to participate in this step can implement the {spring-framework-api}/beans/factory/aot/BeanFactoryInitializationAotProcessor.html[`BeanFactoryInitializationAotProcessor`] interface.
|
||||
Each implementation can return an AOT contribution, based on the state of the bean factory.
|
||||
|
||||
An AOT contribution is a component that contributes generated code that reproduces a particular behavior.
|
||||
@@ -156,6 +156,7 @@ Java::
|
||||
/**
|
||||
* Bean definitions for {@link DataSourceConfiguration}
|
||||
*/
|
||||
@Generated
|
||||
public class DataSourceConfiguration__BeanDefinitions {
|
||||
/**
|
||||
* Get the bean definition for 'dataSourceConfiguration'
|
||||
@@ -190,6 +191,9 @@ Java::
|
||||
|
||||
NOTE: The exact code generated may differ depending on the exact nature of your bean definitions.
|
||||
|
||||
TIP: Each generated class is annotated with `org.springframework.aot.generate.Generated` to
|
||||
identify them if they need to be excluded, for instance by static analysis tools.
|
||||
|
||||
The generated code above creates bean definitions equivalent to the `@Configuration` class, but in a direct way and without the use of reflection if at all possible.
|
||||
There is a bean definition for `dataSourceConfiguration` and one for `dataSourceBean`.
|
||||
When a `datasource` instance is required, a `BeanInstanceSupplier` is called.
|
||||
@@ -261,7 +265,7 @@ If you are registering bean definitions programmatically, consider using `RootBe
|
||||
The container is able to choose the most appropriate constructor to use based on several candidates.
|
||||
However, this is not a best practice and flagging the preferred constructor with `@Autowired` if necessary is preferred.
|
||||
|
||||
In case you are working on a code base that you can't modify, you can set the {api-spring-framework}/beans/factory/support/AbstractBeanDefinition.html#PREFERRED_CONSTRUCTORS_ATTRIBUTE[`preferredConstructors` attribute] on the related bean definition to indicate which constructor should be used.
|
||||
In case you are working on a code base that you can't modify, you can set the {spring-framework-api}/beans/factory/support/AbstractBeanDefinition.html#PREFERRED_CONSTRUCTORS_ATTRIBUTE[`preferredConstructors` attribute] on the related bean definition to indicate which constructor should be used.
|
||||
|
||||
[[aot.bestpractices.factory-bean]]
|
||||
=== FactoryBean
|
||||
@@ -379,7 +383,7 @@ For instance, GraalVM needs to know ahead of time if a component uses reflection
|
||||
Similarly, classpath resources are not shipped in a native image unless specified explicitly.
|
||||
Consequently, if the application needs to load a resource, it must be referenced from the corresponding GraalVM native image configuration file.
|
||||
|
||||
The {api-spring-framework}/aot/hint/RuntimeHints.html[`RuntimeHints`] API collects the need for reflection, resource loading, serialization, and JDK proxies at runtime.
|
||||
The {spring-framework-api}/aot/hint/RuntimeHints.html[`RuntimeHints`] API collects the need for reflection, resource loading, serialization, and JDK proxies at runtime.
|
||||
The following example makes sure that `config/app.properties` can be loaded from the classpath at runtime within a native image:
|
||||
|
||||
[tabs]
|
||||
@@ -417,7 +421,7 @@ It is also possible to register an implementation statically by adding an entry
|
||||
[[aot.hints.reflective]]
|
||||
=== `@Reflective`
|
||||
|
||||
{api-spring-framework}/aot/hint/annotation/Reflective.html[`@Reflective`] provides an idiomatic way to flag the need for reflection on an annotated element.
|
||||
{spring-framework-api}/aot/hint/annotation/Reflective.html[`@Reflective`] provides an idiomatic way to flag the need for reflection on an annotated element.
|
||||
For instance, `@EventListener` is meta-annotated with `@Reflective` since the underlying implementation invokes the annotated method using reflection.
|
||||
|
||||
By default, only Spring beans are considered and an invocation hint is registered for the annotated element.
|
||||
@@ -431,7 +435,7 @@ If components other than Spring beans need to be processed, a `BeanFactoryInitia
|
||||
[[aot.hints.register-reflection-for-binding]]
|
||||
=== `@RegisterReflectionForBinding`
|
||||
|
||||
{api-spring-framework}/aot/hint/annotation/RegisterReflectionForBinding.html[`@RegisterReflectionForBinding`] is a specialization of `@Reflective` that registers the need for serializing arbitrary types.
|
||||
{spring-framework-api}/aot/hint/annotation/RegisterReflectionForBinding.html[`@RegisterReflectionForBinding`] is a specialization of `@Reflective` that registers the need for serializing arbitrary types.
|
||||
A typical use case is the use of DTOs that the container cannot infer, such as using a web client within a method body.
|
||||
|
||||
`@RegisterReflectionForBinding` can be applied to any Spring bean at the class level, but it can also be applied directly to a method, field, or constructor to better indicate where the hints are actually required.
|
||||
@@ -467,7 +471,7 @@ include-code::./SpellCheckServiceTests[tag=hintspredicates]
|
||||
With `RuntimeHintsPredicates`, we can check for reflection, resource, serialization, or proxy generation hints.
|
||||
This approach works well for unit tests but implies that the runtime behavior of a component is well known.
|
||||
|
||||
You can learn more about the global runtime behavior of an application by running its test suite (or the app itself) with the {docs-graalvm}/native-image/metadata/AutomaticMetadataCollection/[GraalVM tracing agent].
|
||||
You can learn more about the global runtime behavior of an application by running its test suite (or the app itself) with the {graalvm-docs}/native-image/metadata/AutomaticMetadataCollection/[GraalVM tracing agent].
|
||||
This agent will record all relevant calls requiring GraalVM hints at runtime and write them out as JSON configuration files.
|
||||
|
||||
For more targeted discovery and testing, Spring Framework ships a dedicated module with core AOT testing utilities, `"org.springframework:spring-core-test"`.
|
||||
@@ -499,4 +503,4 @@ io.spring.runtimehintstesting.SampleReflectionRuntimeHintsTests#lambda$shouldReg
|
||||
|
||||
There are various ways to configure this Java agent in your build, so please refer to the documentation of your build tool and test execution plugin.
|
||||
The agent itself can be configured to instrument specific packages (by default, only `org.springframework` is instrumented).
|
||||
You'll find more details in the {spring-framework-main-code}/buildSrc/README.md[Spring Framework `buildSrc` README] file.
|
||||
You'll find more details in the {spring-framework-code}/buildSrc/README.md[Spring Framework `buildSrc` README] file.
|
||||
|
||||
@@ -765,7 +765,7 @@ want to add an additional attribute to the existing bean definition element.
|
||||
|
||||
By way of another example, suppose that you define a bean definition for a
|
||||
service object that (unknown to it) accesses a clustered
|
||||
https://jcp.org/en/jsr/detail?id=107[JCache], and you want to ensure that the
|
||||
{JSR}107[JCache], and you want to ensure that the
|
||||
named JCache instance is eagerly started within the surrounding cluster.
|
||||
The following listing shows such a definition:
|
||||
|
||||
|
||||
@@ -66,13 +66,13 @@ developer's intent ("`inject this constant value`"), and it reads better:
|
||||
[[xsd-schemas-util-frfb]]
|
||||
==== Setting a Bean Property or Constructor Argument from a Field Value
|
||||
|
||||
{api-spring-framework}/beans/factory/config/FieldRetrievingFactoryBean.html[`FieldRetrievingFactoryBean`]
|
||||
{spring-framework-api}/beans/factory/config/FieldRetrievingFactoryBean.html[`FieldRetrievingFactoryBean`]
|
||||
is a `FactoryBean` that retrieves a `static` or non-static field value. It is typically
|
||||
used for retrieving `public` `static` `final` constants, which may then be used to set a
|
||||
property value or constructor argument for another bean.
|
||||
|
||||
The following example shows how a `static` field is exposed, by using the
|
||||
{api-spring-framework}/beans/factory/config/FieldRetrievingFactoryBean.html#setStaticField(java.lang.String)[`staticField`]
|
||||
{spring-framework-api}/beans/factory/config/FieldRetrievingFactoryBean.html#setStaticField(java.lang.String)[`staticField`]
|
||||
property:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
@@ -109,7 +109,7 @@ to be specified for the bean reference, as the following example shows:
|
||||
|
||||
You can also access a non-static (instance) field of another bean, as
|
||||
described in the API documentation for the
|
||||
{api-spring-framework}/beans/factory/config/FieldRetrievingFactoryBean.html[`FieldRetrievingFactoryBean`]
|
||||
{spring-framework-api}/beans/factory/config/FieldRetrievingFactoryBean.html[`FieldRetrievingFactoryBean`]
|
||||
class.
|
||||
|
||||
Injecting enumeration values into beans as either property or constructor arguments is
|
||||
|
||||
@@ -17,7 +17,7 @@ No matter the choice, Spring can accommodate both styles and even mix them toget
|
||||
It is worth pointing out that through its xref:core/beans/java.adoc[JavaConfig] option, Spring lets
|
||||
annotations be used in a non-invasive way, without touching the target components'
|
||||
source code and that, in terms of tooling, all configuration styles are supported by
|
||||
https://spring.io/tools[Spring Tools] for Eclipse, Visual Studio Code, and Theia.
|
||||
{spring-site-tools}[Spring Tools] for Eclipse, Visual Studio Code, and Theia.
|
||||
****
|
||||
|
||||
An alternative to XML setup is provided by annotation-based configuration, which relies
|
||||
@@ -62,11 +62,11 @@ configuration (notice the inclusion of the `context` namespace):
|
||||
|
||||
The `<context:annotation-config/>` element implicitly registers the following post-processors:
|
||||
|
||||
* {api-spring-framework}/context/annotation/ConfigurationClassPostProcessor.html[`ConfigurationClassPostProcessor`]
|
||||
* {api-spring-framework}/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html[`AutowiredAnnotationBeanPostProcessor`]
|
||||
* {api-spring-framework}/context/annotation/CommonAnnotationBeanPostProcessor.html[`CommonAnnotationBeanPostProcessor`]
|
||||
* {api-spring-framework}/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.html[`PersistenceAnnotationBeanPostProcessor`]
|
||||
* {api-spring-framework}/context/event/EventListenerMethodProcessor.html[`EventListenerMethodProcessor`]
|
||||
* {spring-framework-api}/context/annotation/ConfigurationClassPostProcessor.html[`ConfigurationClassPostProcessor`]
|
||||
* {spring-framework-api}/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html[`AutowiredAnnotationBeanPostProcessor`]
|
||||
* {spring-framework-api}/context/annotation/CommonAnnotationBeanPostProcessor.html[`CommonAnnotationBeanPostProcessor`]
|
||||
* {spring-framework-api}/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.html[`PersistenceAnnotationBeanPostProcessor`]
|
||||
* {spring-framework-api}/context/event/EventListenerMethodProcessor.html[`EventListenerMethodProcessor`]
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
|
||||
+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
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[[beans-custom-autowire-configurer]]
|
||||
= Using `CustomAutowireConfigurer`
|
||||
|
||||
{api-spring-framework}/beans/factory/annotation/CustomAutowireConfigurer.html[`CustomAutowireConfigurer`]
|
||||
{spring-framework-api}/beans/factory/annotation/CustomAutowireConfigurer.html[`CustomAutowireConfigurer`]
|
||||
is a `BeanFactoryPostProcessor` that lets you register your own custom qualifier
|
||||
annotation types, even if they are not annotated with Spring's `@Qualifier` annotation.
|
||||
The following example shows how to use `CustomAutowireConfigurer`:
|
||||
|
||||
@@ -84,7 +84,7 @@ Kotlin::
|
||||
NOTE: The name provided with the annotation is resolved as a bean name by the
|
||||
`ApplicationContext` of which the `CommonAnnotationBeanPostProcessor` is aware.
|
||||
The names can be resolved through JNDI if you configure Spring's
|
||||
{api-spring-framework}/jndi/support/SimpleJndiBeanFactory.html[`SimpleJndiBeanFactory`]
|
||||
{spring-framework-api}/jndi/support/SimpleJndiBeanFactory.html[`SimpleJndiBeanFactory`]
|
||||
explicitly. However, we recommend that you rely on the default behavior and
|
||||
use Spring's JNDI lookup capabilities to preserve the level of indirection.
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ between those objects.
|
||||
Several implementations of the `ApplicationContext` interface are supplied
|
||||
with Spring. In stand-alone applications, it is common to create an
|
||||
instance of
|
||||
{api-spring-framework}/context/support/ClassPathXmlApplicationContext.html[`ClassPathXmlApplicationContext`]
|
||||
or {api-spring-framework}/context/support/FileSystemXmlApplicationContext.html[`FileSystemXmlApplicationContext`].
|
||||
{spring-framework-api}/context/support/ClassPathXmlApplicationContext.html[`ClassPathXmlApplicationContext`]
|
||||
or {spring-framework-api}/context/support/FileSystemXmlApplicationContext.html[`FileSystemXmlApplicationContext`].
|
||||
While XML has been the traditional format for defining configuration metadata, you can
|
||||
instruct the container to use Java annotations or code as the metadata format by
|
||||
providing a small amount of XML configuration to declaratively enable support for these
|
||||
@@ -24,7 +24,7 @@ more instances of a Spring IoC container. For example, in a web application scen
|
||||
simple eight (or so) lines of boilerplate web descriptor XML in the `web.xml` file
|
||||
of the application typically suffices (see
|
||||
xref:core/beans/context-introduction.adoc#context-create[Convenient ApplicationContext Instantiation for Web Applications]).
|
||||
If you use the https://spring.io/tools[Spring Tools for Eclipse] (an Eclipse-powered
|
||||
If you use the {spring-site-tools}[Spring Tools for Eclipse] (an Eclipse-powered
|
||||
development environment), you can easily create this boilerplate configuration with a
|
||||
few mouse clicks or keystrokes.
|
||||
|
||||
@@ -61,10 +61,10 @@ For information about using other forms of metadata with the Spring container, s
|
||||
annotation-based configuration metadata.
|
||||
* xref:core/beans/java.adoc[Java-based configuration]: define beans external to your application
|
||||
classes by using Java rather than XML files. To use these features, see the
|
||||
{api-spring-framework}/context/annotation/Configuration.html[`@Configuration`],
|
||||
{api-spring-framework}/context/annotation/Bean.html[`@Bean`],
|
||||
{api-spring-framework}/context/annotation/Import.html[`@Import`],
|
||||
and {api-spring-framework}/context/annotation/DependsOn.html[`@DependsOn`] annotations.
|
||||
{spring-framework-api}/context/annotation/Configuration.html[`@Configuration`],
|
||||
{spring-framework-api}/context/annotation/Bean.html[`@Bean`],
|
||||
{spring-framework-api}/context/annotation/Import.html[`@Import`],
|
||||
and {spring-framework-api}/context/annotation/DependsOn.html[`@DependsOn`] annotations.
|
||||
|
||||
Spring configuration consists of at least one and typically more than one bean
|
||||
definition that the container must manage. XML-based configuration metadata configures these
|
||||
|
||||
@@ -191,7 +191,7 @@ Kotlin::
|
||||
======
|
||||
|
||||
For further details, see the
|
||||
https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model[Spring Annotation Programming Model]
|
||||
{spring-framework-wiki}/Spring-Annotation-Programming-Model[Spring Annotation Programming Model]
|
||||
wiki page.
|
||||
|
||||
|
||||
@@ -315,7 +315,7 @@ entries in the classpath. When you build JARs with Ant, make sure that you do no
|
||||
activate the files-only switch of the JAR task. Also, classpath directories may not be
|
||||
exposed based on security policies in some environments -- for example, standalone apps on
|
||||
JDK 1.7.0_45 and higher (which requires 'Trusted-Library' setup in your manifests -- see
|
||||
https://stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources).
|
||||
{stackoverflow-questions}/19394570/java-jre-7u45-breaks-classloader-getresources).
|
||||
|
||||
On JDK 9's module path (Jigsaw), Spring's classpath scanning generally works as expected.
|
||||
However, make sure that your component classes are exported in your `module-info`
|
||||
@@ -743,7 +743,7 @@ Kotlin::
|
||||
|
||||
If you do not want to rely on the default bean-naming strategy, you can provide a custom
|
||||
bean-naming strategy. First, implement the
|
||||
{api-spring-framework}/beans/factory/support/BeanNameGenerator.html[`BeanNameGenerator`]
|
||||
{spring-framework-api}/beans/factory/support/BeanNameGenerator.html[`BeanNameGenerator`]
|
||||
interface, and be sure to include a default no-arg constructor. Then, provide the fully
|
||||
qualified class name when configuring the scanner, as the following example annotation
|
||||
and bean definition show.
|
||||
@@ -840,7 +840,7 @@ possibly also declaring a custom scoped-proxy mode.
|
||||
|
||||
NOTE: To provide a custom strategy for scope resolution rather than relying on the
|
||||
annotation-based approach, you can implement the
|
||||
{api-spring-framework}/context/annotation/ScopeMetadataResolver.html[`ScopeMetadataResolver`]
|
||||
{spring-framework-api}/context/annotation/ScopeMetadataResolver.html[`ScopeMetadataResolver`]
|
||||
interface. Be sure to include a default no-arg constructor. Then you can provide the
|
||||
fully qualified class name when configuring the scanner, as the following example of both
|
||||
an annotation and a bean definition shows:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
As discussed in the xref:web/webmvc-view/mvc-xslt.adoc#mvc-view-xslt-beandefs[chapter introduction], the `org.springframework.beans.factory`
|
||||
package provides basic functionality for managing and manipulating beans, including in a
|
||||
programmatic way. The `org.springframework.context` package adds the
|
||||
{api-spring-framework}/context/ApplicationContext.html[`ApplicationContext`]
|
||||
{spring-framework-api}/context/ApplicationContext.html[`ApplicationContext`]
|
||||
interface, which extends the `BeanFactory` interface, in addition to extending other
|
||||
interfaces to provide additional functionality in a more application
|
||||
framework-oriented style. Many people use the `ApplicationContext` in a completely
|
||||
@@ -269,7 +269,7 @@ file format but is more flexible than the standard JDK based
|
||||
`ResourceBundleMessageSource` implementation. In particular, it allows for reading
|
||||
files from any Spring resource location (not only from the classpath) and supports hot
|
||||
reloading of bundle property files (while efficiently caching them in between).
|
||||
See the {api-spring-framework}/context/support/ReloadableResourceBundleMessageSource.html[`ReloadableResourceBundleMessageSource`]
|
||||
See the {spring-framework-api}/context/support/ReloadableResourceBundleMessageSource.html[`ReloadableResourceBundleMessageSource`]
|
||||
javadoc for details.
|
||||
|
||||
|
||||
@@ -485,8 +485,8 @@ This means that the `publishEvent()` method blocks until all listeners have fini
|
||||
One advantage of this synchronous and single-threaded approach is that, when a listener receives an event,
|
||||
it operates inside the transaction context of the publisher if a transaction context is available.
|
||||
If another strategy for event publication becomes necessary, e.g. asynchronous event processing by default,
|
||||
see the javadoc for Spring's {api-spring-framework}/context/event/ApplicationEventMulticaster.html[`ApplicationEventMulticaster`] interface
|
||||
and {api-spring-framework}/context/event/SimpleApplicationEventMulticaster.html[`SimpleApplicationEventMulticaster`] implementation
|
||||
see the javadoc for Spring's {spring-framework-api}/context/event/ApplicationEventMulticaster.html[`ApplicationEventMulticaster`] interface
|
||||
and {spring-framework-api}/context/event/SimpleApplicationEventMulticaster.html[`SimpleApplicationEventMulticaster`] implementation
|
||||
for configuration options which can be applied to a custom "applicationEventMulticaster" bean definition.
|
||||
In these cases, ThreadLocals and logging context are not propagated for the event processing.
|
||||
See xref:integration/observability.adoc#observability.application-events[the `@EventListener` Observability section]
|
||||
@@ -529,7 +529,7 @@ notify appropriate parties.
|
||||
NOTE: Spring's eventing mechanism is designed for simple communication between Spring beans
|
||||
within the same application context. However, for more sophisticated enterprise
|
||||
integration needs, the separately maintained
|
||||
https://projects.spring.io/spring-integration/[Spring Integration] project provides
|
||||
{spring-site-projects}/spring-integration/[Spring Integration] project provides
|
||||
complete support for building lightweight,
|
||||
https://www.enterpriseintegrationpatterns.com[pattern-oriented], event-driven
|
||||
architectures that build upon the well-known Spring programming model.
|
||||
@@ -742,11 +742,11 @@ Be aware of the following limitations when using asynchronous events:
|
||||
|
||||
* If an asynchronous event listener throws an `Exception`, it is not propagated to the
|
||||
caller. See
|
||||
{api-spring-framework}/aop/interceptor/AsyncUncaughtExceptionHandler.html[`AsyncUncaughtExceptionHandler`]
|
||||
{spring-framework-api}/aop/interceptor/AsyncUncaughtExceptionHandler.html[`AsyncUncaughtExceptionHandler`]
|
||||
for more details.
|
||||
* Asynchronous event listener methods cannot publish a subsequent event by returning a
|
||||
value. If you need to publish another event as the result of the processing, inject an
|
||||
{api-spring-framework}/context/ApplicationEventPublisher.html[`ApplicationEventPublisher`]
|
||||
{spring-framework-api}/context/ApplicationEventPublisher.html[`ApplicationEventPublisher`]
|
||||
to publish the event manually.
|
||||
* ThreadLocals and logging context are not propagated by default for the event processing.
|
||||
See xref:integration/observability.adoc#observability.application-events[the `@EventListener` Observability section]
|
||||
@@ -1040,7 +1040,7 @@ and JMX support facilities. Application components can also interact with the ap
|
||||
server's JCA `WorkManager` through Spring's `TaskExecutor` abstraction.
|
||||
|
||||
See the javadoc of the
|
||||
{api-spring-framework}/jca/context/SpringContextResourceAdapter.html[`SpringContextResourceAdapter`]
|
||||
{spring-framework-api}/jca/context/SpringContextResourceAdapter.html[`SpringContextResourceAdapter`]
|
||||
class for the configuration details involved in RAR deployment.
|
||||
|
||||
For a simple deployment of a Spring ApplicationContext as a Jakarta EE RAR file:
|
||||
@@ -1050,7 +1050,7 @@ all application classes into a RAR file (which is a standard JAR file with a dif
|
||||
file extension).
|
||||
. Add all required library JARs into the root of the RAR archive.
|
||||
. Add a
|
||||
`META-INF/ra.xml` deployment descriptor (as shown in the {api-spring-framework}/jca/context/SpringContextResourceAdapter.html[javadoc for `SpringContextResourceAdapter`])
|
||||
`META-INF/ra.xml` deployment descriptor (as shown in the {spring-framework-api}/jca/context/SpringContextResourceAdapter.html[javadoc for `SpringContextResourceAdapter`])
|
||||
and the corresponding Spring XML bean definition file(s) (typically
|
||||
`META-INF/applicationContext.xml`).
|
||||
. Drop the resulting RAR file into your
|
||||
|
||||
@@ -44,7 +44,7 @@ weaver instance. This is particularly useful in combination with
|
||||
xref:data-access/orm/jpa.adoc[Spring's JPA support] where load-time weaving may be
|
||||
necessary for JPA class transformation.
|
||||
Consult the
|
||||
{api-spring-framework}/orm/jpa/LocalContainerEntityManagerFactoryBean.html[`LocalContainerEntityManagerFactoryBean`]
|
||||
{spring-framework-api}/orm/jpa/LocalContainerEntityManagerFactoryBean.html[`LocalContainerEntityManagerFactoryBean`]
|
||||
javadoc for more detail. For more on AspectJ load-time weaving, see xref:core/aop/using-aspectj.adoc#aop-aj-ltw[Load-time Weaving with AspectJ in the Spring Framework].
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -99,7 +99,7 @@ container, lets you handle this use case cleanly.
|
||||
|
||||
****
|
||||
You can read more about the motivation for Method Injection in
|
||||
https://spring.io/blog/2004/08/06/method-injection/[this blog entry].
|
||||
{spring-site-blog}/2004/08/06/method-injection/[this blog entry].
|
||||
****
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ XML configuration:
|
||||
|
||||
The preceding XML is more succinct. However, typos are discovered at runtime rather than
|
||||
design time, unless you use an IDE (such as https://www.jetbrains.com/idea/[IntelliJ
|
||||
IDEA] or the https://spring.io/tools[Spring Tools for Eclipse])
|
||||
IDEA] or the {spring-site-tools}[Spring Tools for Eclipse])
|
||||
that supports automatic property completion when you create bean definitions. Such IDE
|
||||
assistance is highly recommended.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[[beans-environment]]
|
||||
= Environment Abstraction
|
||||
|
||||
The {api-spring-framework}/core/env/Environment.html[`Environment`] interface
|
||||
The {spring-framework-api}/core/env/Environment.html[`Environment`] interface
|
||||
is an abstraction integrated in the container that models two key
|
||||
aspects of the application environment: xref:core/beans/environment.adoc#beans-definition-profiles[profiles]
|
||||
and xref:core/beans/environment.adoc#beans-property-source-abstraction[properties].
|
||||
@@ -118,7 +118,7 @@ situation B. We start by updating our configuration to reflect this need.
|
||||
[[beans-definition-profiles-java]]
|
||||
=== Using `@Profile`
|
||||
|
||||
The {api-spring-framework}/context/annotation/Profile.html[`@Profile`]
|
||||
The {spring-framework-api}/context/annotation/Profile.html[`@Profile`]
|
||||
annotation lets you indicate that a component is eligible for registration
|
||||
when one or more specified profiles are active. Using our preceding example, we
|
||||
can rewrite the `dataSource` configuration as follows:
|
||||
@@ -516,8 +516,8 @@ as the following example shows:
|
||||
[[beans-definition-profiles-default]]
|
||||
=== Default Profile
|
||||
|
||||
The default profile represents the profile that is enabled by default. Consider the
|
||||
following example:
|
||||
The default profile represents the profile that is enabled if no profile is active. Consider
|
||||
the following example:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
@@ -558,9 +558,9 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
If no profile is active, the `dataSource` is created. You can see this
|
||||
as a way to provide a default definition for one or more beans. If any
|
||||
profile is enabled, the default profile does not apply.
|
||||
If xref:#beans-definition-profiles-enable[no profile is active], the `dataSource` is
|
||||
created. You can see this as a way to provide a default definition for one or more
|
||||
beans. If any profile is enabled, the default profile does not apply.
|
||||
|
||||
The name of the default profile is `default`. You can change the name of
|
||||
the default profile by using `setDefaultProfiles()` on the `Environment` or,
|
||||
@@ -599,17 +599,17 @@ Kotlin::
|
||||
|
||||
In the preceding snippet, we see a high-level way of asking Spring whether the `my-property` property is
|
||||
defined for the current environment. To answer this question, the `Environment` object performs
|
||||
a search over a set of {api-spring-framework}/core/env/PropertySource.html[`PropertySource`]
|
||||
a search over a set of {spring-framework-api}/core/env/PropertySource.html[`PropertySource`]
|
||||
objects. A `PropertySource` is a simple abstraction over any source of key-value pairs, and
|
||||
Spring's {api-spring-framework}/core/env/StandardEnvironment.html[`StandardEnvironment`]
|
||||
Spring's {spring-framework-api}/core/env/StandardEnvironment.html[`StandardEnvironment`]
|
||||
is configured with two PropertySource objects -- one representing the set of JVM system properties
|
||||
(`System.getProperties()`) and one representing the set of system environment variables
|
||||
(`System.getenv()`).
|
||||
|
||||
NOTE: These default property sources are present for `StandardEnvironment`, for use in standalone
|
||||
applications. {api-spring-framework}/web/context/support/StandardServletEnvironment.html[`StandardServletEnvironment`]
|
||||
applications. {spring-framework-api}/web/context/support/StandardServletEnvironment.html[`StandardServletEnvironment`]
|
||||
is populated with additional default property sources including servlet config, servlet
|
||||
context parameters, and a {api-spring-framework}/jndi/JndiPropertySource.html[`JndiPropertySource`]
|
||||
context parameters, and a {spring-framework-api}/jndi/JndiPropertySource.html[`JndiPropertySource`]
|
||||
if JNDI is available.
|
||||
|
||||
Concretely, when you use the `StandardEnvironment`, the call to `env.containsProperty("my-property")`
|
||||
@@ -663,7 +663,7 @@ Kotlin::
|
||||
In the preceding code, `MyPropertySource` has been added with highest precedence in the
|
||||
search. If it contains a `my-property` property, the property is detected and returned, in favor of
|
||||
any `my-property` property in any other `PropertySource`. The
|
||||
{api-spring-framework}/core/env/MutablePropertySources.html[`MutablePropertySources`]
|
||||
{spring-framework-api}/core/env/MutablePropertySources.html[`MutablePropertySources`]
|
||||
API exposes a number of methods that allow for precise manipulation of the set of
|
||||
property sources.
|
||||
|
||||
@@ -672,7 +672,7 @@ property sources.
|
||||
[[beans-using-propertysource]]
|
||||
== Using `@PropertySource`
|
||||
|
||||
The {api-spring-framework}/context/annotation/PropertySource.html[`@PropertySource`]
|
||||
The {spring-framework-api}/context/annotation/PropertySource.html[`@PropertySource`]
|
||||
annotation provides a convenient and declarative mechanism for adding a `PropertySource`
|
||||
to Spring's `Environment`.
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ in which these `BeanPostProcessor` instances run by setting the `order` property
|
||||
You can set this property only if the `BeanPostProcessor` implements the `Ordered`
|
||||
interface. If you write your own `BeanPostProcessor`, you should consider implementing
|
||||
the `Ordered` interface, too. For further details, see the javadoc of the
|
||||
{api-spring-framework}/beans/factory/config/BeanPostProcessor.html[`BeanPostProcessor`]
|
||||
and {api-spring-framework}/core/Ordered.html[`Ordered`] interfaces. See also the note on
|
||||
{spring-framework-api}/beans/factory/config/BeanPostProcessor.html[`BeanPostProcessor`]
|
||||
and {spring-framework-api}/core/Ordered.html[`Ordered`] interfaces. See also the note on
|
||||
xref:core/beans/factory-extension.adoc#beans-factory-programmatically-registering-beanpostprocessors[programmatic registration of `BeanPostProcessor` instances].
|
||||
|
||||
[NOTE]
|
||||
@@ -272,8 +272,8 @@ which these `BeanFactoryPostProcessor` instances run by setting the `order` prop
|
||||
However, you can only set this property if the `BeanFactoryPostProcessor` implements the
|
||||
`Ordered` interface. If you write your own `BeanFactoryPostProcessor`, you should
|
||||
consider implementing the `Ordered` interface, too. See the javadoc of the
|
||||
{api-spring-framework}/beans/factory/config/BeanFactoryPostProcessor.html[`BeanFactoryPostProcessor`]
|
||||
and {api-spring-framework}/core/Ordered.html[`Ordered`] interfaces for more details.
|
||||
{spring-framework-api}/beans/factory/config/BeanFactoryPostProcessor.html[`BeanFactoryPostProcessor`]
|
||||
and {spring-framework-api}/core/Ordered.html[`Ordered`] interfaces for more details.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
|
||||
@@ -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`
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ The following table describes the supported scopes:
|
||||
|
||||
NOTE: A thread scope is available but is not registered by default. For more information,
|
||||
see the documentation for
|
||||
{api-spring-framework}/context/support/SimpleThreadScope.html[`SimpleThreadScope`].
|
||||
{spring-framework-api}/context/support/SimpleThreadScope.html[`SimpleThreadScope`].
|
||||
For instructions on how to register this or any other custom scope, see
|
||||
xref:core/beans/factory-scopes.adoc#beans-factory-scopes-custom-using[Using a Custom Scope].
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -559,7 +569,7 @@ To integrate your custom scopes into the Spring container, you need to implement
|
||||
`org.springframework.beans.factory.config.Scope` interface, which is described in this
|
||||
section. For an idea of how to implement your own scopes, see the `Scope`
|
||||
implementations that are supplied with the Spring Framework itself and the
|
||||
{api-spring-framework}/beans/factory/config/Scope.html[`Scope`] javadoc,
|
||||
{spring-framework-api}/beans/factory/config/Scope.html[`Scope`] javadoc,
|
||||
which explains the methods you need to implement in more detail.
|
||||
|
||||
The `Scope` interface has four methods to get objects from the scope, remove them from
|
||||
@@ -629,7 +639,7 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
See the {api-spring-framework}/beans/factory/config/Scope.html#registerDestructionCallback[javadoc]
|
||||
See the {spring-framework-api}/beans/factory/config/Scope.html#registerDestructionCallback[javadoc]
|
||||
or a Spring scope implementation for more information on destruction callbacks.
|
||||
|
||||
The following method obtains the conversation identifier for the underlying scope:
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
[[beans-introduction]]
|
||||
= Introduction to the Spring IoC Container and Beans
|
||||
|
||||
This chapter covers the Spring Framework implementation of the Inversion of Control
|
||||
(IoC) principle. IoC is also known as dependency injection (DI). It is a process whereby
|
||||
objects define their dependencies (that is, the other objects they work with) only through
|
||||
constructor arguments, arguments to a factory method, or properties that are set on the
|
||||
object instance after it is constructed or returned from a factory method. The container
|
||||
This chapter covers the Spring Framework implementation of the Inversion of Control (IoC)
|
||||
principle. Dependency injection (DI) is a specialized form of IoC, whereby objects define
|
||||
their dependencies (that is, the other objects they work with) only through constructor
|
||||
arguments, arguments to a factory method, or properties that are set on the object
|
||||
instance after it is constructed or returned from a factory method. The IoC container
|
||||
then injects those dependencies when it creates the bean. This process is fundamentally
|
||||
the inverse (hence the name, Inversion of Control) of the bean itself
|
||||
controlling the instantiation or location of its dependencies by using direct
|
||||
construction of classes or a mechanism such as the Service Locator pattern.
|
||||
the inverse (hence the name, Inversion of Control) of the bean itself controlling the
|
||||
instantiation or location of its dependencies by using direct construction of classes or
|
||||
a mechanism such as the Service Locator pattern.
|
||||
|
||||
The `org.springframework.beans` and `org.springframework.context` packages are the basis
|
||||
for Spring Framework's IoC container. The
|
||||
{api-spring-framework}/beans/factory/BeanFactory.html[`BeanFactory`]
|
||||
{spring-framework-api}/beans/factory/BeanFactory.html[`BeanFactory`]
|
||||
interface provides an advanced configuration mechanism capable of managing any type of
|
||||
object.
|
||||
{api-spring-framework}/context/ApplicationContext.html[`ApplicationContext`]
|
||||
{spring-framework-api}/context/ApplicationContext.html[`ApplicationContext`]
|
||||
is a sub-interface of `BeanFactory`. It adds:
|
||||
|
||||
* Easier integration with Spring's AOP features
|
||||
|
||||
@@ -3,17 +3,5 @@
|
||||
:page-section-summary-toc: 1
|
||||
|
||||
This section covers how to use annotations in your Java code to configure the Spring
|
||||
container. It includes the following topics:
|
||||
|
||||
* xref:core/beans/java/basic-concepts.adoc[Basic Concepts: `@Bean` and `@Configuration`]
|
||||
* xref:core/beans/java/instantiating-container.adoc[Instantiating the Spring Container by Using `AnnotationConfigApplicationContext`]
|
||||
* xref:core/beans/java/bean-annotation.adoc[Using the `@Bean` Annotation]
|
||||
* xref:core/beans/java/configuration-annotation.adoc[Using the `@Configuration` annotation]
|
||||
* xref:core/beans/java/composing-configuration-classes.adoc[Composing Java-based Configurations]
|
||||
* xref:core/beans/environment.adoc#beans-definition-profiles[Bean Definition Profiles]
|
||||
* xref:core/beans/environment.adoc#beans-property-source-abstraction[`PropertySource` Abstraction]
|
||||
* xref:core/beans/environment.adoc#beans-using-propertysource[Using `@PropertySource`]
|
||||
* xref:core/beans/environment.adoc#beans-placeholder-resolution-in-statements[Placeholder Resolution in Statements]
|
||||
|
||||
|
||||
container.
|
||||
|
||||
|
||||
@@ -552,7 +552,7 @@ Sometimes, it is helpful to provide a more detailed textual description of a bea
|
||||
be particularly useful when beans are exposed (perhaps through JMX) for monitoring purposes.
|
||||
|
||||
To add a description to a `@Bean`, you can use the
|
||||
{api-spring-framework}/context/annotation/Description.html[`@Description`]
|
||||
{spring-framework-api}/context/annotation/Description.html[`@Description`]
|
||||
annotation, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
|
||||
+4
-4
@@ -225,7 +225,7 @@ Also, be particularly careful with `BeanPostProcessor` and `BeanFactoryPostProce
|
||||
through `@Bean`. Those should usually be declared as `static @Bean` methods, not triggering the
|
||||
instantiation of their containing configuration class. Otherwise, `@Autowired` and `@Value` may not
|
||||
work on the configuration class itself, since it is possible to create it as a bean instance earlier than
|
||||
{api-spring-framework}/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html[`AutowiredAnnotationBeanPostProcessor`].
|
||||
{spring-framework-api}/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html[`AutowiredAnnotationBeanPostProcessor`].
|
||||
====
|
||||
|
||||
The following example shows how one bean can be autowired to another bean:
|
||||
@@ -338,7 +338,7 @@ modularity, but determining exactly where the autowired bean definitions are dec
|
||||
still somewhat ambiguous. For example, as a developer looking at `ServiceConfig`, how do
|
||||
you know exactly where the `@Autowired AccountRepository` bean is declared? It is not
|
||||
explicit in the code, and this may be just fine. Remember that the
|
||||
https://spring.io/tools[Spring Tools for Eclipse] provides tooling that
|
||||
{spring-site-tools}[Spring Tools for Eclipse] provides tooling that
|
||||
can render graphs showing how everything is wired, which may be all you need. Also,
|
||||
your Java IDE can easily find all declarations and uses of the `AccountRepository` type
|
||||
and quickly show you the location of `@Bean` methods that return that type.
|
||||
@@ -519,7 +519,7 @@ profile has been enabled in the Spring `Environment` (see xref:core/beans/enviro
|
||||
for details).
|
||||
|
||||
The `@Profile` annotation is actually implemented by using a much more flexible annotation
|
||||
called {api-spring-framework}/context/annotation/Conditional.html[`@Conditional`].
|
||||
called {spring-framework-api}/context/annotation/Conditional.html[`@Conditional`].
|
||||
The `@Conditional` annotation indicates specific
|
||||
`org.springframework.context.annotation.Condition` implementations that should be
|
||||
consulted before a `@Bean` is registered.
|
||||
@@ -570,7 +570,7 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
See the {api-spring-framework}/context/annotation/Conditional.html[`@Conditional`]
|
||||
See the {spring-framework-api}/context/annotation/Conditional.html[`@Conditional`]
|
||||
javadoc for more detail.
|
||||
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ init-param):
|
||||
|
||||
NOTE: For programmatic use cases, a `GenericWebApplicationContext` can be used as an
|
||||
alternative to `AnnotationConfigWebApplicationContext`. See the
|
||||
{api-spring-framework}/web/context/support/GenericWebApplicationContext.html[`GenericWebApplicationContext`]
|
||||
{spring-framework-api}/web/context/support/GenericWebApplicationContext.html[`GenericWebApplicationContext`]
|
||||
javadoc for details.
|
||||
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ alternate between read and write.
|
||||
== `PooledDataBuffer`
|
||||
|
||||
As explained in the Javadoc for
|
||||
https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html[ByteBuffer],
|
||||
{java-api}/java.base/java/nio/ByteBuffer.html[ByteBuffer],
|
||||
byte buffers can be direct or non-direct. Direct buffers may reside outside the Java heap
|
||||
which eliminates the need for copying for native I/O operations. That makes direct buffers
|
||||
particularly useful for receiving and sending data over a socket, but they're also more
|
||||
|
||||
@@ -11,7 +11,7 @@ EL, to name a few -- the Spring Expression Language was created to provide the S
|
||||
community with a single well supported expression language that can be used across all
|
||||
the products in the Spring portfolio. Its language features are driven by the
|
||||
requirements of the projects in the Spring portfolio, including tooling requirements
|
||||
for code completion support within the https://spring.io/tools[Spring Tools for Eclipse].
|
||||
for code completion support within the {spring-site-tools}[Spring Tools for Eclipse].
|
||||
That said, SpEL is based on a technology-agnostic API that lets other expression language
|
||||
implementations be integrated, should the need arise.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -2,24 +2,4 @@
|
||||
= Language Reference
|
||||
:page-section-summary-toc: 1
|
||||
|
||||
This section describes how the Spring Expression Language works. It covers the following
|
||||
topics:
|
||||
|
||||
* xref:core/expressions/language-ref/literal.adoc[Literal Expressions]
|
||||
* xref:core/expressions/language-ref/properties-arrays.adoc[Properties, Arrays, Lists, Maps, and Indexers]
|
||||
* xref:core/expressions/language-ref/inline-lists.adoc[Inline Lists]
|
||||
* xref:core/expressions/language-ref/inline-maps.adoc[Inline Maps]
|
||||
* xref:core/expressions/language-ref/array-construction.adoc[Array Construction]
|
||||
* xref:core/expressions/language-ref/methods.adoc[Methods]
|
||||
* xref:core/expressions/language-ref/operators.adoc[Operators]
|
||||
* xref:core/expressions/language-ref/types.adoc[Types]
|
||||
* xref:core/expressions/language-ref/constructors.adoc[Constructors]
|
||||
* xref:core/expressions/language-ref/variables.adoc[Variables]
|
||||
* xref:core/expressions/language-ref/functions.adoc[User-Defined Functions]
|
||||
* xref:core/expressions/language-ref/bean-references.adoc[Bean References]
|
||||
* xref:core/expressions/language-ref/operator-ternary.adoc[Ternary Operator (If-Then-Else)]
|
||||
* xref:core/expressions/language-ref/operator-elvis.adoc[The Elvis Operator]
|
||||
* xref:core/expressions/language-ref/operator-safe-navigation.adoc[Safe Navigation Operator]
|
||||
|
||||
|
||||
|
||||
This section describes how the Spring Expression Language works.
|
||||
|
||||
+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]
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
[[expressions-ref-variables]]
|
||||
= Variables
|
||||
|
||||
You can reference variables in the expression by using the `#variableName` syntax. Variables
|
||||
are set by using the `setVariable` method on `EvaluationContext` implementations.
|
||||
You can reference variables in an expression by using the `#variableName` syntax. Variables
|
||||
are set by using the `setVariable()` method in `EvaluationContext` implementations.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
@@ -29,7 +29,7 @@ Java::
|
||||
context.setVariable("newName", "Mike Tesla");
|
||||
|
||||
parser.parseExpression("name = #newName").getValue(context, tesla);
|
||||
System.out.println(tesla.getName()) // "Mike Tesla"
|
||||
System.out.println(tesla.getName()); // "Mike Tesla"
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
@@ -53,8 +53,10 @@ Kotlin::
|
||||
The `#this` variable is always defined and refers to the current evaluation object
|
||||
(against which unqualified references are resolved). The `#root` variable is always
|
||||
defined and refers to the root context object. Although `#this` may vary as components of
|
||||
an expression are evaluated, `#root` always refers to the root. The following examples
|
||||
show how to use the `#this` and `#root` variables:
|
||||
an expression are evaluated, `#root` always refers to the root.
|
||||
|
||||
The following example shows how to use the `#this` variable in conjunction with
|
||||
xref:core/expressions/language-ref/collection-selection.adoc[collection selection].
|
||||
|
||||
[tabs]
|
||||
======
|
||||
@@ -62,40 +64,95 @@ Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
// create an array of integers
|
||||
List<Integer> primes = new ArrayList<>();
|
||||
primes.addAll(Arrays.asList(2,3,5,7,11,13,17));
|
||||
// Create a list of prime integers.
|
||||
List<Integer> primes = List.of(2, 3, 5, 7, 11, 13, 17);
|
||||
|
||||
// create parser and set variable 'primes' as the array of integers
|
||||
// Create parser and set variable 'primes' as the list of integers.
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataAccess();
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
|
||||
context.setVariable("primes", primes);
|
||||
|
||||
// all prime numbers > 10 from the list (using selection ?{...})
|
||||
// evaluates to [11, 13, 17]
|
||||
List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression(
|
||||
"#primes.?[#this>10]").getValue(context);
|
||||
// Select all prime numbers > 10 from the list (using selection ?{...}).
|
||||
String expression = "#primes.?[#this > 10]";
|
||||
|
||||
// Evaluates to a list containing [11, 13, 17].
|
||||
List<Integer> primesGreaterThanTen =
|
||||
parser.parseExpression(expression).getValue(context, List.class);
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
// create an array of integers
|
||||
val primes = ArrayList<Int>()
|
||||
primes.addAll(listOf(2, 3, 5, 7, 11, 13, 17))
|
||||
// Create a list of prime integers.
|
||||
val primes = listOf(2, 3, 5, 7, 11, 13, 17)
|
||||
|
||||
// create parser and set variable 'primes' as the array of integers
|
||||
// Create parser and set variable 'primes' as the list of integers.
|
||||
val parser = SpelExpressionParser()
|
||||
val context = SimpleEvaluationContext.forReadOnlyDataAccess()
|
||||
val context = SimpleEvaluationContext.forReadWriteDataBinding().build()
|
||||
context.setVariable("primes", primes)
|
||||
|
||||
// all prime numbers > 10 from the list (using selection ?{...})
|
||||
// evaluates to [11, 13, 17]
|
||||
val primesGreaterThanTen = parser.parseExpression(
|
||||
"#primes.?[#this>10]").getValue(context) as List<Int>
|
||||
// Select all prime numbers > 10 from the list (using selection ?{...}).
|
||||
val expression = "#primes.?[#this > 10]"
|
||||
|
||||
// Evaluates to a list containing [11, 13, 17].
|
||||
val primesGreaterThanTen = parser.parseExpression(expression)
|
||||
.getValue(context) as List<Int>
|
||||
----
|
||||
======
|
||||
|
||||
The following example shows how to use the `#this` and `#root` variables together in
|
||||
conjunction with
|
||||
xref:core/expressions/language-ref/collection-projection.adoc[collection projection].
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
// Create parser and evaluation context.
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
|
||||
|
||||
// Create an inventor to use as the root context object.
|
||||
Inventor tesla = new Inventor("Nikola Tesla");
|
||||
tesla.setInventions("Telephone repeater", "Tesla coil transformer");
|
||||
|
||||
// Iterate over all inventions of the Inventor referenced as the #root
|
||||
// object, and generate a list of strings whose contents take the form
|
||||
// "<inventor's name> invented the <invention>." (using projection !{...}).
|
||||
String expression = "#root.inventions.![#root.name + ' invented the ' + #this + '.']";
|
||||
|
||||
// Evaluates to a list containing:
|
||||
// "Nikola Tesla invented the Telephone repeater."
|
||||
// "Nikola Tesla invented the Tesla coil transformer."
|
||||
List<String> results = parser.parseExpression(expression)
|
||||
.getValue(context, tesla, List.class);
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
// Create parser and evaluation context.
|
||||
val parser = SpelExpressionParser()
|
||||
val context = SimpleEvaluationContext.forReadWriteDataBinding().build()
|
||||
|
||||
// Create an inventor to use as the root context object.
|
||||
val tesla = Inventor("Nikola Tesla")
|
||||
tesla.setInventions("Telephone repeater", "Tesla coil transformer")
|
||||
|
||||
// Iterate over all inventions of the Inventor referenced as the #root
|
||||
// object, and generate a list of strings whose contents take the form
|
||||
// "<inventor's name> invented the <invention>." (using projection !{...}).
|
||||
val expression = "#root.inventions.![#root.name + ' invented the ' + #this + '.']"
|
||||
|
||||
// Evaluates to a list containing:
|
||||
// "Nikola Tesla invented the Telephone repeater."
|
||||
// "Nikola Tesla invented the Tesla coil transformer."
|
||||
val results = parser.parseExpression(expression)
|
||||
.getValue(context, tesla, List::class.java)
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
@@ -5,14 +5,14 @@ Although Java does not let you express null-safety with its type system, the Spr
|
||||
provides the following annotations in the `org.springframework.lang` package to let you
|
||||
declare nullability of APIs and fields:
|
||||
|
||||
* {api-spring-framework}/lang/Nullable.html[`@Nullable`]: Annotation to indicate that a
|
||||
* {spring-framework-api}/lang/Nullable.html[`@Nullable`]: Annotation to indicate that a
|
||||
specific parameter, return value, or field can be `null`.
|
||||
* {api-spring-framework}/lang/NonNull.html[`@NonNull`]: Annotation to indicate that a specific
|
||||
* {spring-framework-api}/lang/NonNull.html[`@NonNull`]: Annotation to indicate that a specific
|
||||
parameter, return value, or field cannot be `null` (not needed on parameters, return values,
|
||||
and fields where `@NonNullApi` and `@NonNullFields` apply, respectively).
|
||||
* {api-spring-framework}/lang/NonNullApi.html[`@NonNullApi`]: Annotation at the package level
|
||||
* {spring-framework-api}/lang/NonNullApi.html[`@NonNullApi`]: Annotation at the package level
|
||||
that declares non-null as the default semantics for parameters and return values.
|
||||
* {api-spring-framework}/lang/NonNullFields.html[`@NonNullFields`]: Annotation at the package
|
||||
* {spring-framework-api}/lang/NonNullFields.html[`@NonNullFields`]: Annotation at the package
|
||||
level that declares non-null as the default semantics for fields.
|
||||
|
||||
The Spring Framework itself leverages these annotations, but they can also be used in any
|
||||
@@ -37,7 +37,7 @@ these annotations can be used by an IDE (such as IDEA or Eclipse) to provide use
|
||||
warnings related to null-safety in order to avoid `NullPointerException` at runtime.
|
||||
|
||||
They are also used to make Spring APIs null-safe in Kotlin projects, since Kotlin natively
|
||||
supports https://kotlinlang.org/docs/null-safety.html[null-safety]. More details
|
||||
supports {kotlin-docs}/null-safety.html[null-safety]. More details
|
||||
are available in the xref:languages/kotlin/null-safety.adoc[Kotlin support documentation].
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ are available in the xref:languages/kotlin/null-safety.adoc[Kotlin support docum
|
||||
[[jsr-305-meta-annotations]]
|
||||
== JSR-305 meta-annotations
|
||||
|
||||
Spring annotations are meta-annotated with https://jcp.org/en/jsr/detail?id=305[JSR 305]
|
||||
Spring annotations are meta-annotated with {JSR}305[JSR 305]
|
||||
annotations (a dormant but widespread JSR). JSR-305 meta-annotations let tooling vendors
|
||||
like IDEA or Kotlin provide null-safety support in a generic way, without having to
|
||||
hard-code support for Spring annotations.
|
||||
|
||||
@@ -37,7 +37,7 @@ such as a method to check for the existence of the resource being pointed to.
|
||||
Spring's `Resource` interface located in the `org.springframework.core.io.` package is
|
||||
meant to be a more capable interface for abstracting access to low-level resources. The
|
||||
following listing provides an overview of the `Resource` interface. See the
|
||||
{api-spring-framework}/core/io/Resource.html[`Resource`] javadoc for further details.
|
||||
{spring-framework-api}/core/io/Resource.html[`Resource`] javadoc for further details.
|
||||
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
@@ -104,7 +104,7 @@ resource (if the underlying implementation is compatible and supports that
|
||||
functionality).
|
||||
|
||||
Some implementations of the `Resource` interface also implement the extended
|
||||
{api-spring-framework}/core/io/WritableResource.html[`WritableResource`] interface
|
||||
{spring-framework-api}/core/io/WritableResource.html[`WritableResource`] interface
|
||||
for a resource that supports writing to it.
|
||||
|
||||
Spring itself uses the `Resource` abstraction extensively, as an argument type in
|
||||
@@ -143,7 +143,7 @@ Spring includes several built-in `Resource` implementations:
|
||||
|
||||
For a complete list of `Resource` implementations available in Spring, consult the
|
||||
"All Known Implementing Classes" section of the
|
||||
{api-spring-framework}/core/io/Resource.html[`Resource`] javadoc.
|
||||
{spring-framework-api}/core/io/Resource.html[`Resource`] javadoc.
|
||||
|
||||
|
||||
|
||||
@@ -763,7 +763,7 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
See the {api-spring-framework}/context/support/ClassPathXmlApplicationContext.html[`ClassPathXmlApplicationContext`]
|
||||
See the {spring-framework-api}/context/support/ClassPathXmlApplicationContext.html[`ClassPathXmlApplicationContext`]
|
||||
javadoc for details on the various constructors.
|
||||
|
||||
|
||||
@@ -903,7 +903,7 @@ entries in the classpath. When you build JARs with Ant, do not activate the `fil
|
||||
switch of the JAR task. Also, classpath directories may not get exposed based on security
|
||||
policies in some environments -- for example, stand-alone applications on JDK 1.7.0_45
|
||||
and higher (which requires 'Trusted-Library' to be set up in your manifests. See
|
||||
https://stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources).
|
||||
{stackoverflow-questions}/19394570/java-jre-7u45-breaks-classloader-getresources).
|
||||
|
||||
On JDK 9's module path (Jigsaw), Spring's classpath scanning generally works as expected.
|
||||
Putting resources into a dedicated directory is highly recommendable here as well,
|
||||
|
||||
@@ -9,7 +9,7 @@ known as _JUL_ or `java.util.logging`) if neither Log4j 2.x nor SLF4J is availab
|
||||
|
||||
Put Log4j 2.x or Logback (or another SLF4J provider) in your classpath, without any extra
|
||||
bridges, and let the framework auto-adapt to your choice. For further information see the
|
||||
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-logging[Spring
|
||||
{spring-boot-docs}/features.html#features.logging[Spring
|
||||
Boot Logging Reference Documentation].
|
||||
|
||||
[NOTE]
|
||||
|
||||
@@ -51,7 +51,7 @@ A JavaBean is a class with a default no-argument constructor and that follows
|
||||
a naming convention where (for example) a property named `bingoMadness` would
|
||||
have a setter method `setBingoMadness(..)` and a getter method `getBingoMadness()`. For
|
||||
more information about JavaBeans and the specification, see
|
||||
https://docs.oracle.com/javase/8/docs/api/java/beans/package-summary.html[javabeans].
|
||||
{java-api}/java.desktop/java/beans/package-summary.html[javabeans].
|
||||
|
||||
One quite important class in the beans package is the `BeanWrapper` interface and its
|
||||
corresponding implementation (`BeanWrapperImpl`). As quoted from the javadoc, the
|
||||
@@ -249,7 +249,7 @@ behavior can be achieved by registering custom editors of type
|
||||
`java.beans.PropertyEditor`. Registering custom editors on a `BeanWrapper` or,
|
||||
alternatively, in a specific IoC container (as mentioned in the previous chapter), gives it
|
||||
the knowledge of how to convert properties to the desired type. For more about
|
||||
`PropertyEditor`, see https://docs.oracle.com/javase/8/docs/api/java/beans/package-summary.html[the javadoc of the `java.beans` package from Oracle].
|
||||
`PropertyEditor`, see {java-api}/java.desktop/java/beans/package-summary.html[the javadoc of the `java.beans` package from Oracle].
|
||||
|
||||
A couple of examples where property editing is used in Spring:
|
||||
|
||||
@@ -355,7 +355,7 @@ com
|
||||
|
||||
Note that you can also use the standard `BeanInfo` JavaBeans mechanism here as well
|
||||
(described to some extent
|
||||
https://docs.oracle.com/javase/tutorial/javabeans/advanced/customization.html[here]). The
|
||||
{java-tutorial}/javabeans/advanced/customization.html[here]). The
|
||||
following example uses the `BeanInfo` mechanism to explicitly register one or more
|
||||
`PropertyEditor` instances with the properties of an associated class:
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
= Java Bean Validation
|
||||
|
||||
The Spring Framework provides support for the
|
||||
https://beanvalidation.org/[Java Bean Validation] API.
|
||||
{bean-validation-site}[Java Bean Validation] API.
|
||||
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ Kotlin::
|
||||
======
|
||||
|
||||
A Bean Validation validator then validates instances of this class based on the declared
|
||||
constraints. See https://beanvalidation.org/[Bean Validation] for general information about
|
||||
constraints. See {bean-validation-site}[Bean Validation] for general information about
|
||||
the API. See the https://hibernate.org/validator/[Hibernate Validator] documentation for
|
||||
specific constraints. To learn how to set up a bean validation provider as a Spring
|
||||
bean, keep reading.
|
||||
@@ -317,7 +317,7 @@ XML::
|
||||
To be eligible for Spring-driven method validation, target classes need to be annotated
|
||||
with Spring's `@Validated` annotation, which can optionally also declare the validation
|
||||
groups to use. See
|
||||
{api-spring-framework}/validation/beanvalidation/MethodValidationPostProcessor.html[`MethodValidationPostProcessor`]
|
||||
{spring-framework-api}/validation/beanvalidation/MethodValidationPostProcessor.html[`MethodValidationPostProcessor`]
|
||||
for setup details with the Hibernate Validator and Bean Validation providers.
|
||||
|
||||
[TIP]
|
||||
@@ -472,7 +472,7 @@ Max.degrees=You cannot provide more than {1} {0}
|
||||
The default `LocalValidatorFactoryBean` configuration suffices for most
|
||||
cases. There are a number of configuration options for various Bean Validation
|
||||
constructs, from message interpolation to traversal resolution. See the
|
||||
{api-spring-framework}/validation/beanvalidation/LocalValidatorFactoryBean.html[`LocalValidatorFactoryBean`]
|
||||
{spring-framework-api}/validation/beanvalidation/LocalValidatorFactoryBean.html[`LocalValidatorFactoryBean`]
|
||||
javadoc for more information on these options.
|
||||
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ of the field). This is done as a convenience to aid developers when targeting er
|
||||
|
||||
More information on the `MessageCodesResolver` and the default strategy can be found
|
||||
in the javadoc of
|
||||
{api-spring-framework}/validation/MessageCodesResolver.html[`MessageCodesResolver`] and
|
||||
{api-spring-framework}/validation/DefaultMessageCodesResolver.html[`DefaultMessageCodesResolver`],
|
||||
{spring-framework-api}/validation/MessageCodesResolver.html[`MessageCodesResolver`] and
|
||||
{spring-framework-api}/validation/DefaultMessageCodesResolver.html[`DefaultMessageCodesResolver`],
|
||||
respectively.
|
||||
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ Kotlin::
|
||||
======
|
||||
|
||||
The Spring team welcomes community-driven `Formatter` contributions. See
|
||||
https://github.com/spring-projects/spring-framework/issues[GitHub Issues] to contribute.
|
||||
{spring-framework-issues}[GitHub Issues] to contribute.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ Kotlin::
|
||||
|
||||
The `static` `rejectIfEmpty(..)` method on the `ValidationUtils` class is used to
|
||||
reject the `name` property if it is `null` or the empty string. Have a look at the
|
||||
{api-spring-framework}/validation/ValidationUtils.html[`ValidationUtils`] javadoc
|
||||
{spring-framework-api}/validation/ValidationUtils.html[`ValidationUtils`] javadoc
|
||||
to see what functionality it provides besides the example shown previously.
|
||||
|
||||
While it is certainly possible to implement a single `Validator` class to validate each
|
||||
@@ -193,7 +193,7 @@ Kotlin::
|
||||
Validation errors are reported to the `Errors` object passed to the validator. In the case
|
||||
of Spring Web MVC, you can use the `<spring:bind/>` tag to inspect the error messages, but
|
||||
you can also inspect the `Errors` object yourself. More information about the
|
||||
methods it offers can be found in the {api-spring-framework}/validation/Errors.html[javadoc].
|
||||
methods it offers can be found in the {spring-framework-api}/validation/Errors.html[javadoc].
|
||||
|
||||
Validators may also get locally invoked for the immediate validation of a given object,
|
||||
not involving a binding process. As of 6.1, this has been simplified through a new
|
||||
|
||||
@@ -199,7 +199,7 @@ participating in Spring managed transactions. It is generally preferable to writ
|
||||
own new code by using the higher level abstractions for resource management, such as
|
||||
`JdbcTemplate` or `DataSourceUtils`.
|
||||
|
||||
See the {api-spring-framework}/jdbc/datasource/TransactionAwareDataSourceProxy.html[`TransactionAwareDataSourceProxy`]
|
||||
See the {spring-framework-api}/jdbc/datasource/TransactionAwareDataSourceProxy.html[`TransactionAwareDataSourceProxy`]
|
||||
javadoc for more details.
|
||||
|
||||
|
||||
@@ -230,6 +230,19 @@ provided you stick to the required connection lookup pattern. Note that JTA does
|
||||
savepoints or custom isolation levels and has a different timeout mechanism but otherwise
|
||||
exposes similar behavior in terms of JDBC resources and JDBC commit/rollback management.
|
||||
|
||||
For JTA-style lazy retrieval of actual resource connections, Spring provides a
|
||||
corresponding `DataSource` proxy class for the target connection pool: see
|
||||
{spring-framework-api}/jdbc/datasource/LazyConnectionDataSourceProxy.html[`LazyConnectionDataSourceProxy`].
|
||||
This is particularly useful for potentially empty transactions without actual statement
|
||||
execution (never fetching an actual resource in such a scenario), and also in front of
|
||||
a routing `DataSource` which means to take the transaction-synchronized read-only flag
|
||||
and/or isolation level into account (e.g. `IsolationLevelDataSourceRouter`).
|
||||
|
||||
`LazyConnectionDataSourceProxy` also provides special support for a read-only connection
|
||||
pool to use during a read-only transaction, avoiding the overhead of switching the JDBC
|
||||
Connection's read-only flag at the beginning and end of every transaction when fetching
|
||||
it from the primary connection pool (which may be costly depending on the JDBC driver).
|
||||
|
||||
NOTE: As of 5.3, Spring provides an extended `JdbcTransactionManager` variant which adds
|
||||
exception translation capabilities on commit/rollback (aligned with `JdbcTemplate`).
|
||||
Where `DataSourceTransactionManager` will only ever throw `TransactionSystemException`
|
||||
|
||||
@@ -51,7 +51,7 @@ corresponding to the fully qualified class name of the template instance (typica
|
||||
|
||||
The following sections provide some examples of `JdbcTemplate` usage. These examples
|
||||
are not an exhaustive list of all of the functionality exposed by the `JdbcTemplate`.
|
||||
See the attendant {api-spring-framework}/jdbc/core/JdbcTemplate.html[javadoc] for that.
|
||||
See the attendant {spring-framework-api}/jdbc/core/JdbcTemplate.html[javadoc] for that.
|
||||
|
||||
[[jdbc-JdbcTemplate-examples-query]]
|
||||
=== Querying (`SELECT`)
|
||||
|
||||
@@ -83,7 +83,7 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
See the {api-spring-framework}/jdbc/datasource/embedded/EmbeddedDatabaseBuilder.html[javadoc for `EmbeddedDatabaseBuilder`]
|
||||
See the {spring-framework-api}/jdbc/datasource/embedded/EmbeddedDatabaseBuilder.html[javadoc for `EmbeddedDatabaseBuilder`]
|
||||
for further details on all supported options.
|
||||
|
||||
You can also use the `EmbeddedDatabaseBuilder` to create an embedded database by using Java
|
||||
@@ -288,7 +288,7 @@ You can extend Spring JDBC embedded database support in two ways:
|
||||
connection pool to manage embedded database connections.
|
||||
|
||||
We encourage you to contribute extensions to the Spring community at
|
||||
https://github.com/spring-projects/spring-framework/issues[GitHub Issues].
|
||||
{spring-framework-issues}[GitHub Issues].
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -407,6 +407,12 @@ exposes the Hibernate transaction as a JDBC transaction if you have set up the p
|
||||
`DataSource` for which the transactions are supposed to be exposed through the
|
||||
`dataSource` property of the `HibernateTransactionManager` class.
|
||||
|
||||
For JTA-style lazy retrieval of actual resource connections, Spring provides a
|
||||
corresponding `DataSource` proxy class for the target connection pool: see
|
||||
{spring-framework-api}/jdbc/datasource/LazyConnectionDataSourceProxy.html[`LazyConnectionDataSourceProxy`].
|
||||
This is particularly useful for Hibernate read-only transactions which can often
|
||||
be processed from a local cache rather than hitting the database.
|
||||
|
||||
|
||||
[[orm-hibernate-resources]]
|
||||
== Comparing Container-managed and Locally Defined Resources
|
||||
|
||||
@@ -58,8 +58,8 @@ The benefits of using the Spring Framework to create your ORM DAOs include:
|
||||
|
||||
TIP: For more comprehensive ORM support, including support for alternative database
|
||||
technologies such as MongoDB, you might want to check out the
|
||||
https://projects.spring.io/spring-data/[Spring Data] suite of projects. If you are
|
||||
a JPA user, the https://spring.io/guides/gs/accessing-data-jpa/[Getting Started Accessing
|
||||
{spring-site-projects}/spring-data/[Spring Data] suite of projects. If you are
|
||||
a JPA user, the {spring-site-guides}/gs/accessing-data-jpa/[Getting Started Accessing
|
||||
Data with JPA] guide from https://spring.io provides a great introduction.
|
||||
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ The `LoadTimeWeaver` interface is a Spring-provided class that lets JPA
|
||||
`ClassTransformer` instances be plugged in a specific manner, depending on whether the
|
||||
environment is a web container or application server. Hooking `ClassTransformers`
|
||||
through an
|
||||
https://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html[agent]
|
||||
{java-api}/java.instrument/java/lang/instrument/package-summary.html[agent]
|
||||
is typically not efficient. The agents work against the entire virtual machine and
|
||||
inspect every class that is loaded, which is usually undesirable in a production
|
||||
server environment.
|
||||
@@ -506,13 +506,20 @@ if you have not already done so, to get more detailed coverage of Spring's decla
|
||||
The recommended strategy for JPA is local transactions through JPA's native transaction
|
||||
support. Spring's `JpaTransactionManager` provides many capabilities known from local
|
||||
JDBC transactions (such as transaction-specific isolation levels and resource-level
|
||||
read-only optimizations) against any regular JDBC connection pool (no XA requirement).
|
||||
read-only optimizations) against any regular JDBC connection pool, without requiring
|
||||
a JTA transaction coordinator and XA-capable resources.
|
||||
|
||||
Spring JPA also lets a configured `JpaTransactionManager` expose a JPA transaction
|
||||
to JDBC access code that accesses the same `DataSource`, provided that the registered
|
||||
`JpaDialect` supports retrieval of the underlying JDBC `Connection`.
|
||||
Spring provides dialects for the EclipseLink and Hibernate JPA implementations.
|
||||
See the xref:data-access/orm/jpa.adoc#orm-jpa-dialect[next section] for details on the `JpaDialect` mechanism.
|
||||
`JpaDialect` supports retrieval of the underlying JDBC `Connection`. Spring provides
|
||||
dialects for the EclipseLink and Hibernate JPA implementations. See the
|
||||
xref:data-access/orm/jpa.adoc#orm-jpa-dialect[next section] for details on `JpaDialect`.
|
||||
|
||||
For JTA-style lazy retrieval of actual resource connections, Spring provides a
|
||||
corresponding `DataSource` proxy class for the target connection pool: see
|
||||
{spring-framework-api}/jdbc/datasource/LazyConnectionDataSourceProxy.html[`LazyConnectionDataSourceProxy`].
|
||||
This is particularly useful for JPA read-only transactions which can often
|
||||
be processed from a local cache rather than hitting the database.
|
||||
|
||||
|
||||
[[orm-jpa-dialect]]
|
||||
@@ -541,8 +548,8 @@ way of auto-configuring an `EntityManagerFactory` setup for Hibernate or Eclipse
|
||||
respectively. Note that those provider adapters are primarily designed for use with
|
||||
Spring-driven transaction management (that is, for use with `JpaTransactionManager`).
|
||||
|
||||
See the {api-spring-framework}/orm/jpa/JpaDialect.html[`JpaDialect`] and
|
||||
{api-spring-framework}/orm/jpa/JpaVendorAdapter.html[`JpaVendorAdapter`] javadoc for
|
||||
See the {spring-framework-api}/orm/jpa/JpaDialect.html[`JpaDialect`] and
|
||||
{spring-framework-api}/orm/jpa/JpaVendorAdapter.html[`JpaVendorAdapter`] javadoc for
|
||||
more details of its operations and how they are used within Spring's JPA support.
|
||||
|
||||
|
||||
|
||||
@@ -36,8 +36,8 @@ simpler.
|
||||
[[oxm-consistent-interfaces]]
|
||||
=== Consistent Interfaces
|
||||
|
||||
Spring's O-X mapping operates through two global interfaces: {api-spring-framework}/oxm/Marshaller.html[`Marshaller`] and
|
||||
{api-spring-framework}/oxm/Unmarshaller.html[`Unmarshaller`]. These abstractions let you switch O-X mapping frameworks
|
||||
Spring's O-X mapping operates through two global interfaces: {spring-framework-api}/oxm/Marshaller.html[`Marshaller`] and
|
||||
{spring-framework-api}/oxm/Unmarshaller.html[`Unmarshaller`]. These abstractions let you switch O-X mapping frameworks
|
||||
with relative ease, with little or no change required on the classes that do the
|
||||
marshalling. This approach has the additional benefit of making it possible to do XML
|
||||
marshalling with a mix-and-match approach (for example, some marshalling performed using JAXB
|
||||
@@ -557,7 +557,7 @@ set the `supportedClasses` property on the `XStreamMarshaller`, as the following
|
||||
Doing so ensures that only the registered classes are eligible for unmarshalling.
|
||||
|
||||
Additionally, you can register
|
||||
{api-spring-framework}/oxm/xstream/XStreamMarshaller.html#setConverters(com.thoughtworks.xstream.converters.ConverterMatcher...)[custom
|
||||
{spring-framework-api}/oxm/xstream/XStreamMarshaller.html#setConverters(com.thoughtworks.xstream.converters.ConverterMatcher...)[custom
|
||||
converters] to make sure that only your supported classes can be unmarshalled. You might
|
||||
want to add a `CatchAllConverter` as the last converter in the list, in addition to
|
||||
converters that explicitly support the domain classes that should be supported. As a
|
||||
|
||||
@@ -95,7 +95,7 @@ parameter to database bind marker translation.
|
||||
run.
|
||||
* `….namedParameters(false)`: Disable named parameter expansion. Enabled by default.
|
||||
|
||||
TIP: Dialects are resolved by {api-spring-framework}/r2dbc/core/binding/BindMarkersFactoryResolver.html[`BindMarkersFactoryResolver`]
|
||||
TIP: Dialects are resolved by {spring-framework-api}/r2dbc/core/binding/BindMarkersFactoryResolver.html[`BindMarkersFactoryResolver`]
|
||||
from a `ConnectionFactory`, typically by inspecting `ConnectionFactoryMetadata`.
|
||||
+
|
||||
You can let Spring auto-discover your `BindMarkersFactory` by registering a
|
||||
@@ -120,7 +120,7 @@ the reactive sequence to aid debugging.
|
||||
|
||||
The following sections provide some examples of `DatabaseClient` usage. These examples
|
||||
are not an exhaustive list of all of the functionality exposed by the `DatabaseClient`.
|
||||
See the attendant {api-spring-framework}/r2dbc/core/DatabaseClient.html[javadoc] for that.
|
||||
See the attendant {spring-framework-api}/r2dbc/core/DatabaseClient.html[javadoc] for that.
|
||||
|
||||
[[r2dbc-DatabaseClient-examples-statement]]
|
||||
==== Executing Statements
|
||||
@@ -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))
|
||||
----
|
||||
======
|
||||
|
||||
@@ -752,7 +748,7 @@ the same time, have this client participating in Spring managed transactions. It
|
||||
preferable to integrate a R2DBC client with proper access to `ConnectionFactoryUtils`
|
||||
for resource management.
|
||||
|
||||
See the {api-spring-framework}/r2dbc/connection/TransactionAwareConnectionFactoryProxy.html[`TransactionAwareConnectionFactoryProxy`]
|
||||
See the {spring-framework-api}/r2dbc/connection/TransactionAwareConnectionFactoryProxy.html[`TransactionAwareConnectionFactoryProxy`]
|
||||
javadoc for more details.
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ the JTA `UserTransaction` and `TransactionManager` objects) autodetects the loca
|
||||
the latter object, which varies by application server. Having access to the JTA
|
||||
`TransactionManager` allows for enhanced transaction semantics -- in particular,
|
||||
supporting transaction suspension. See the
|
||||
{api-spring-framework}/transaction/jta/JtaTransactionManager.html[`JtaTransactionManager`]
|
||||
{spring-framework-api}/transaction/jta/JtaTransactionManager.html[`JtaTransactionManager`]
|
||||
javadoc for details.
|
||||
|
||||
Spring's `JtaTransactionManager` is the standard choice to run on Jakarta EE application
|
||||
|
||||
+2
-2
@@ -85,7 +85,7 @@ subclass-level annotation.
|
||||
When a POJO class such as the one above is defined as a bean in a Spring context,
|
||||
you can make the bean instance transactional through an `@EnableTransactionManagement`
|
||||
annotation in a `@Configuration` class. See the
|
||||
{api-spring-framework}/transaction/annotation/EnableTransactionManagement.html[javadoc]
|
||||
{spring-framework-api}/transaction/annotation/EnableTransactionManagement.html[javadoc]
|
||||
for full details.
|
||||
|
||||
In XML configuration, the `<tx:annotation-driven/>` tag provides similar convenience:
|
||||
@@ -262,7 +262,7 @@ is modified) to support `@Transactional` runtime behavior on any kind of method.
|
||||
| XML Attribute| Annotation Attribute| Default| Description
|
||||
|
||||
| `transaction-manager`
|
||||
| N/A (see {api-spring-framework}/transaction/annotation/TransactionManagementConfigurer.html[`TransactionManagementConfigurer`] javadoc)
|
||||
| N/A (see {spring-framework-api}/transaction/annotation/TransactionManagementConfigurer.html[`TransactionManagementConfigurer`] javadoc)
|
||||
| `transactionManager`
|
||||
| Name of the transaction manager to use. Required only if the name of the transaction
|
||||
manager is not `transactionManager`, as in the preceding example.
|
||||
|
||||
@@ -57,8 +57,7 @@ transaction semantics given by the class annotation (if present). You can annota
|
||||
regardless of visibility.
|
||||
|
||||
To weave your applications with the `AnnotationTransactionAspect`, you must either build
|
||||
your application with AspectJ (see the
|
||||
https://www.eclipse.org/aspectj/doc/released/devguide/index.html[AspectJ Development
|
||||
your application with AspectJ (see the {aspectj-docs-devguide}/index.html[AspectJ Development
|
||||
Guide]) or use load-time weaving. See xref:core/aop/using-aspectj.adoc#aop-aj-ltw[Load-time weaving with AspectJ in the Spring Framework]
|
||||
for a discussion of load-time weaving with AspectJ.
|
||||
|
||||
|
||||
+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:
|
||||
|
||||
+1
-1
@@ -75,6 +75,6 @@ that it can roll back to. Such partial rollbacks let an inner transaction scope
|
||||
trigger a rollback for its scope, with the outer transaction being able to continue
|
||||
the physical transaction despite some operations having been rolled back. This setting
|
||||
is typically mapped onto JDBC savepoints, so it works only with JDBC resource
|
||||
transactions. See Spring's {api-spring-framework}/jdbc/datasource/DataSourceTransactionManager.html[`DataSourceTransactionManager`].
|
||||
transactions. See Spring's {spring-framework-api}/jdbc/datasource/DataSourceTransactionManager.html[`DataSourceTransactionManager`].
|
||||
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ For the former, listeners are guaranteed to see the current thread-bound transac
|
||||
Since the latter uses the Reactor context instead of thread-local variables, the transaction
|
||||
context needs to be included in the published event instance as the event source.
|
||||
See the
|
||||
{api-spring-framework}/transaction/reactive/TransactionalEventPublisher.html[`TransactionalEventPublisher`]
|
||||
{spring-framework-api}/transaction/reactive/TransactionalEventPublisher.html[`TransactionalEventPublisher`]
|
||||
javadoc for details.
|
||||
====
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ xref:integration.adoc[Integration] :: REST Clients, JMS, JCA, JMX,
|
||||
Email, Tasks, Scheduling, Caching, Observability, JVM Checkpoint Restore.
|
||||
xref:languages.adoc[Languages] :: Kotlin, Groovy, Dynamic Languages.
|
||||
xref:testing/appendix.adoc[Appendix] :: Spring properties.
|
||||
https://github.com/spring-projects/spring-framework/wiki[Wiki] :: What's New,
|
||||
{spring-framework-wiki}[Wiki] :: What's New,
|
||||
Upgrade Notes, Supported Versions, additional cross-version information.
|
||||
|
||||
Rod Johnson, Juergen Hoeller, Keith Donald, Colin Sampaleanu, Rob Harrop, Thomas Risberg,
|
||||
@@ -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
|
||||
|
||||
@@ -67,7 +67,7 @@ To provide a different default key generator, you need to implement the
|
||||
The default key generation strategy changed with the release of Spring 4.0. Earlier
|
||||
versions of Spring used a key generation strategy that, for multiple key parameters,
|
||||
considered only the `hashCode()` of parameters and not `equals()`. This could cause
|
||||
unexpected key collisions (see https://jira.spring.io/browse/SPR-10237[SPR-10237]
|
||||
unexpected key collisions (see {spring-framework-issues}/14870[spring-framework#14870]
|
||||
for background). The new `SimpleKeyGenerator` uses a compound key for such scenarios.
|
||||
|
||||
If you want to keep using the previous key strategy, you can configure the deprecated
|
||||
@@ -566,7 +566,7 @@ switching to `aspectj` mode in combination with compile-time or load-time weavin
|
||||
|
||||
NOTE: For more detail about advanced customizations (using Java configuration) that are
|
||||
required to implement `CachingConfigurer`, see the
|
||||
{api-spring-framework}/cache/annotation/CachingConfigurer.html[javadoc].
|
||||
{spring-framework-api}/cache/annotation/CachingConfigurer.html[javadoc].
|
||||
|
||||
[[cache-annotation-driven-settings]]
|
||||
.Cache annotation settings
|
||||
@@ -575,7 +575,7 @@ required to implement `CachingConfigurer`, see the
|
||||
| XML Attribute | Annotation Attribute | Default | Description
|
||||
|
||||
| `cache-manager`
|
||||
| N/A (see the {api-spring-framework}/cache/annotation/CachingConfigurer.html[`CachingConfigurer`] javadoc)
|
||||
| N/A (see the {spring-framework-api}/cache/annotation/CachingConfigurer.html[`CachingConfigurer`] javadoc)
|
||||
| `cacheManager`
|
||||
| The name of the cache manager to use. A default `CacheResolver` is initialized behind
|
||||
the scenes with this cache manager (or `cacheManager` if not set). For more
|
||||
@@ -583,19 +583,19 @@ required to implement `CachingConfigurer`, see the
|
||||
attribute.
|
||||
|
||||
| `cache-resolver`
|
||||
| N/A (see the {api-spring-framework}/cache/annotation/CachingConfigurer.html[`CachingConfigurer`] javadoc)
|
||||
| N/A (see the {spring-framework-api}/cache/annotation/CachingConfigurer.html[`CachingConfigurer`] javadoc)
|
||||
| A `SimpleCacheResolver` using the configured `cacheManager`.
|
||||
| The bean name of the CacheResolver that is to be used to resolve the backing caches.
|
||||
This attribute is not required and needs to be specified only as an alternative to
|
||||
the 'cache-manager' attribute.
|
||||
|
||||
| `key-generator`
|
||||
| N/A (see the {api-spring-framework}/cache/annotation/CachingConfigurer.html[`CachingConfigurer`] javadoc)
|
||||
| N/A (see the {spring-framework-api}/cache/annotation/CachingConfigurer.html[`CachingConfigurer`] javadoc)
|
||||
| `SimpleKeyGenerator`
|
||||
| Name of the custom key generator to use.
|
||||
|
||||
| `error-handler`
|
||||
| N/A (see the {api-spring-framework}/cache/annotation/CachingConfigurer.html[`CachingConfigurer`] javadoc)
|
||||
| N/A (see the {spring-framework-api}/cache/annotation/CachingConfigurer.html[`CachingConfigurer`] javadoc)
|
||||
| `SimpleCacheErrorHandler`
|
||||
| The name of the custom cache error handler to use. By default, any exception thrown during
|
||||
a cache related operation is thrown back at the client.
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
[[checkpoint-restore]]
|
||||
= JVM Checkpoint Restore
|
||||
|
||||
The Spring Framework integrates with checkpoint/restore as implemented by https://github.com/CRaC/docs[Project CRaC] in order to allow implementing systems capable to reduce the startup and warmup times of Spring-based Java applications with the JVM.
|
||||
The Spring Framework integrates with checkpoint/restore as implemented by https://github.com/CRaC/docs[Project CRaC] in order to allow implementing systems capable of reducing the startup and warmup times of Spring-based Java applications with the JVM.
|
||||
|
||||
Using this feature requires:
|
||||
|
||||
* A checkpoint/restore enabled JVM (Linux only for now).
|
||||
* The presence in the classpath of the https://github.com/CRaC/org.crac[`org.crac:crac`] library (version `1.4.0` and above are supported).
|
||||
* Specifying the required `java` command line parameters like `-XX:CRaCCheckpointTo=PATH` or `-XX:CRaCRestoreFrom=PATH`.
|
||||
* The presence of the https://github.com/CRaC/org.crac[`org.crac:crac`] library (version `1.4.0` and above are supported) in the classpath.
|
||||
* Specifying the required `java` command-line parameters like `-XX:CRaCCheckpointTo=PATH` or `-XX:CRaCRestoreFrom=PATH`.
|
||||
|
||||
WARNING: The files generated in the path specified by `-XX:CRaCCheckpointTo=PATH` when a checkpoint is requested contain a representation of the memory of the running JVM, which may contain secrets and other sensitive data. Using this feature should be done with the assumption that any value "seen" by the JVM, such as configuration properties coming from the environment, will be stored in those CRaC files. As a consequence, the security implications of where and how those files are generated, stored and accessed should be carefully assessed.
|
||||
WARNING: The files generated in the path specified by `-XX:CRaCCheckpointTo=PATH` when a checkpoint is requested contain a representation of the memory of the running JVM, which may contain secrets and other sensitive data. Using this feature should be done with the assumption that any value "seen" by the JVM, such as configuration properties coming from the environment, will be stored in those CRaC files. As a consequence, the security implications of where and how those files are generated, stored, and accessed should be carefully assessed.
|
||||
|
||||
Conceptually, checkpoint and restore match with xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-processor[Spring `Lifecycle` contract] for individual beans.
|
||||
Conceptually, checkpoint and restore align with the xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-processor[Spring `Lifecycle` contract] for individual beans.
|
||||
|
||||
== On demand checkpoint/restore of a running application
|
||||
== On-demand checkpoint/restore of a running application
|
||||
|
||||
A checkpoint can be created on demand, for example using a command like `jcmd application.jar JDK.checkpoint`. Before the creation of the checkpoint, Spring Framework
|
||||
stops all the running beans, giving them a chance to close resources if needed by implementing `Lifecycle.stop`. After restore, the same beans are restarted, with `Lifecycle.start` allowing to reopen resources when relevant. For libraries not depending on Spring, checkpoint/restore custom integration can be provided by implementing `org.crac.Resource` and registering the related instance.
|
||||
A checkpoint can be created on demand, for example using a command like `jcmd application.jar JDK.checkpoint`. Before the creation of the checkpoint, Spring stops all the running beans, giving them a chance to close resources if needed by implementing `Lifecycle.stop`. After restore, the same beans are restarted, with `Lifecycle.start` allowing beans to reopen resources when relevant. For libraries that do not depend on Spring, custom checkpoint/restore integration can be provided by implementing `org.crac.Resource` and registering the related instance.
|
||||
|
||||
WARNING: Leveraging checkpoint/restore of a running application typically requires additional lifecycle management to gracefully stop and start using resources like files or sockets and stop active threads.
|
||||
|
||||
@@ -24,8 +23,16 @@ NOTE: If the checkpoint is created on a warmed-up JVM, the restored JVM will be
|
||||
|
||||
== Automatic checkpoint/restore at startup
|
||||
|
||||
When the `-Dspring.context.checkpoint=onRefresh` Java system property is set, a checkpoint is created automatically during the startup at `LifecycleProcessor.onRefresh` level. At this phase, all non-lazy initialized singletons are instantiated, `InitializingBean.afterPropertiesSet` callbacks have been invoked, but not `Lifecycle.start` ones and `ContextRefreshedEvent` has not yet been published.
|
||||
When the `-Dspring.context.checkpoint=onRefresh` JVM system property is set, a checkpoint is created automatically at
|
||||
startup during the `LifecycleProcessor.onRefresh` phase. After this phase has completed, all non-lazy initialized singletons have been instantiated, and
|
||||
`InitializingBean#afterPropertiesSet` callbacks have been invoked; but the lifecycle has not started, and the
|
||||
`ContextRefreshedEvent` has not yet been published.
|
||||
|
||||
For testing purposes, it is also possible to leverage the `-Dspring.context.exit=onRefresh` JVM system property which
|
||||
triggers similar behavior, but instead of creating a checkpoint, it exits your Spring application at the same lifecycle
|
||||
phase without requiring the Project CraC dependency/JVM or Linux. This can be useful to check if connections to remote
|
||||
services are required when the beans are not started, and potentially refine the configuration to avoid that.
|
||||
|
||||
WARNING: As mentioned above, and especially in use cases where the CRaC files are shipped as part of a deployable artifact (a container image for example), operate with the assumption that any sensitive data "seen" by the JVM ends up in the CRaC files, and assess carefully the related security implications.
|
||||
|
||||
NOTE: Here checkpoint/restore is a way to "fast-forward" the startup of the application to a phase where the application context is about to start, but does not allow to have a fully warmed-up JVM.
|
||||
NOTE: Automatic checkpoint/restore is a way to "fast-forward" the startup of the application to a phase where the application context is about to start, but it does not allow to have a fully warmed-up JVM.
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
[[class-data-sharing]]
|
||||
= Class Data Sharing
|
||||
|
||||
Class Data Sharing (CDS) is a https://docs.oracle.com/en/java/javase/17/vm/class-data-sharing.html[JVM feature]
|
||||
that can help reduce the startup time and memory footprint of Java applications.
|
||||
|
||||
To use this feature, a CDS archive should be created for the particular classpath of the
|
||||
application. The Spring Framework provides a hook-point to ease the creation of the
|
||||
archive. Once the archive is available, users should opt in to use it via a JVM flag.
|
||||
|
||||
== Creating the CDS Archive
|
||||
|
||||
A CDS archive for an application can be created when the application exits. The Spring
|
||||
Framework provides a mode of operation where the process can exit automatically once the
|
||||
`ApplicationContext` has refreshed. In this mode, all non-lazy initialized singletons
|
||||
have been instantiated, and `InitializingBean#afterPropertiesSet` callbacks have been
|
||||
invoked; but the lifecycle has not started, and the `ContextRefreshedEvent` has not yet
|
||||
been published.
|
||||
|
||||
To create the archive, two additional JVM flags must be specified:
|
||||
|
||||
* `-XX:ArchiveClassesAtExit=application.jsa`: creates the CDS archive on exit
|
||||
* `-Dspring.context.exit=onRefresh`: starts and then immediately exits your Spring
|
||||
application as described above
|
||||
|
||||
To create a CDS archive, your JDK must have a base image. If you add the flags above to
|
||||
your startup script, you may get a warning that looks like this:
|
||||
|
||||
[source,shell,indent=0,subs="verbatim"]
|
||||
----
|
||||
-XX:ArchiveClassesAtExit is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info.
|
||||
----
|
||||
|
||||
The base CDS archive can be created by issuing the following command:
|
||||
|
||||
[source,shell,indent=0,subs="verbatim"]
|
||||
----
|
||||
$ java -Xshare:dump
|
||||
----
|
||||
|
||||
== Using the Archive
|
||||
|
||||
Once the archive is available, add `-XX:SharedArchiveFile=application.jsa` to your startup
|
||||
script to use it, assuming an `application.jsa` file in the working directory.
|
||||
|
||||
To figure out how effective the cache is, you can enable class loading logs by adding
|
||||
an extra attribute: `-Xlog:class+load:file=cds.log`. This creates a `cds.log` with every
|
||||
attempt to load a class and its source. Classes that are loaded from the cache should have
|
||||
a "shared objects file" source, as shown in the following example:
|
||||
|
||||
[source,shell,indent=0,subs="verbatim"]
|
||||
----
|
||||
[0.064s][info][class,load] org.springframework.core.env.EnvironmentCapable source: shared objects file (top)
|
||||
[0.064s][info][class,load] org.springframework.beans.factory.BeanFactory source: shared objects file (top)
|
||||
[0.064s][info][class,load] org.springframework.beans.factory.ListableBeanFactory source: shared objects file (top)
|
||||
[0.064s][info][class,load] org.springframework.beans.factory.HierarchicalBeanFactory source: shared objects file (top)
|
||||
[0.065s][info][class,load] org.springframework.context.MessageSource source: shared objects file (top)
|
||||
----
|
||||
|
||||
TIP: If you have a large number of classes that are not loaded from the cache, make sure that
|
||||
the JDK and classpath used by the commands that create the archive and start the application
|
||||
are identical. Note also that to effectively cache classes, the classpath should be specified
|
||||
as a list of JARs containing those classes, and avoid the usage of directories and `*`
|
||||
wildcard characters.
|
||||
@@ -26,7 +26,7 @@ interface. A simple value object that encapsulates the properties of a simple ma
|
||||
as `from` and `to` (plus many others) is the `SimpleMailMessage` class. This package
|
||||
also contains a hierarchy of checked exceptions that provide a higher level of
|
||||
abstraction over the lower level mail system exceptions, with the root exception being
|
||||
`MailException`. See the {api-spring-framework}/mail/MailException.html[javadoc]
|
||||
`MailException`. See the {spring-framework-api}/mail/MailException.html[javadoc]
|
||||
for more information on the rich mail exception hierarchy.
|
||||
|
||||
The `org.springframework.mail.javamail.JavaMailSender` interface adds specialized
|
||||
@@ -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(
|
||||
|
||||
@@ -64,7 +64,7 @@ You can customize the listener container factory to use for each annotation or y
|
||||
configure an explicit default by implementing the `JmsListenerConfigurer` interface.
|
||||
The default is required only if at least one endpoint is registered without a specific
|
||||
container factory. See the javadoc of classes that implement
|
||||
{api-spring-framework}/jms/annotation/JmsListenerConfigurer.html[`JmsListenerConfigurer`]
|
||||
{spring-framework-api}/jms/annotation/JmsListenerConfigurer.html[`JmsListenerConfigurer`]
|
||||
for details and examples.
|
||||
|
||||
If you prefer xref:integration/jms/namespace.adoc[XML configuration], you can use the `<jms:annotation-driven>`
|
||||
|
||||
@@ -64,9 +64,9 @@ In some environments, you can instead obtain the entire `ResourceAdapter` object
|
||||
(by using `<jee:jndi-lookup>`). The Spring-based message listeners can then interact with
|
||||
the server-hosted `ResourceAdapter`, which also use the server's built-in `WorkManager`.
|
||||
|
||||
See the javadoc for {api-spring-framework}/jms/listener/endpoint/JmsMessageEndpointManager.html[`JmsMessageEndpointManager`],
|
||||
{api-spring-framework}/jms/listener/endpoint/JmsActivationSpecConfig.html[`JmsActivationSpecConfig`],
|
||||
and {api-spring-framework}/jca/support/ResourceAdapterFactoryBean.html[`ResourceAdapterFactoryBean`]
|
||||
See the javadoc for {spring-framework-api}/jms/listener/endpoint/JmsMessageEndpointManager.html[`JmsMessageEndpointManager`],
|
||||
{spring-framework-api}/jms/listener/endpoint/JmsActivationSpecConfig.html[`JmsActivationSpecConfig`],
|
||||
and {spring-framework-api}/jca/support/ResourceAdapterFactoryBean.html[`ResourceAdapterFactoryBean`]
|
||||
for more details.
|
||||
|
||||
Spring also provides a generic JCA message endpoint manager that is not tied to JMS:
|
||||
@@ -74,7 +74,7 @@ Spring also provides a generic JCA message endpoint manager that is not tied to
|
||||
for using any message listener type (such as a JMS `MessageListener`) and any
|
||||
provider-specific `ActivationSpec` object. See your JCA provider's documentation to
|
||||
find out about the actual capabilities of your connector, and see the
|
||||
{api-spring-framework}/jca/endpoint/GenericMessageEndpointManager.html[`GenericMessageEndpointManager`]
|
||||
{spring-framework-api}/jca/endpoint/GenericMessageEndpointManager.html[`GenericMessageEndpointManager`]
|
||||
javadoc for the Spring-specific configuration details.
|
||||
|
||||
NOTE: JCA-based message endpoint management is very analogous to EJB 2.1 Message-Driven Beans.
|
||||
|
||||
@@ -113,7 +113,7 @@ as the following example shows:
|
||||
----
|
||||
|
||||
The following table describes all available attributes. See the class-level javadoc
|
||||
of the {api-spring-framework}/jms/listener/AbstractMessageListenerContainer.html[`AbstractMessageListenerContainer`]
|
||||
of the {spring-framework-api}/jms/listener/AbstractMessageListenerContainer.html[`AbstractMessageListenerContainer`]
|
||||
and its concrete subclasses for more details on the individual properties. The javadoc
|
||||
also provides a discussion of transaction choices and message redelivery scenarios.
|
||||
|
||||
@@ -254,7 +254,7 @@ The following table describes the available configuration options for the JCA va
|
||||
|
||||
| `activation-spec-factory`
|
||||
| A reference to the `JmsActivationSpecFactory`. The default is to autodetect the JMS
|
||||
provider and its `ActivationSpec` class (see {api-spring-framework}/jms/listener/endpoint/DefaultJmsActivationSpecFactory.html[`DefaultJmsActivationSpecFactory`]).
|
||||
provider and its `ActivationSpec` class (see {spring-framework-api}/jms/listener/endpoint/DefaultJmsActivationSpecFactory.html[`DefaultJmsActivationSpecFactory`]).
|
||||
|
||||
| `destination-resolver`
|
||||
| A reference to the `DestinationResolver` strategy for resolving JMS `Destinations`.
|
||||
|
||||
@@ -76,7 +76,7 @@ containers that ships with Spring (in this case, `DefaultMessageListenerContaine
|
||||
----
|
||||
|
||||
See the Spring javadoc of the various message listener containers (all of which implement
|
||||
{api-spring-framework}/jms/listener/MessageListenerContainer.html[MessageListenerContainer])
|
||||
{spring-framework-api}/jms/listener/MessageListenerContainer.html[MessageListenerContainer])
|
||||
for a full description of the features supported by each implementation.
|
||||
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@ use a proper cache level in such a case.
|
||||
This container also has recoverable capabilities when the broker goes down. By default,
|
||||
a simple `BackOff` implementation retries every five seconds. You can specify
|
||||
a custom `BackOff` implementation for more fine-grained recovery options. See
|
||||
{api-spring-framework}/util/backoff/ExponentialBackOff.html[`ExponentialBackOff`] for an example.
|
||||
{spring-framework-api}/util/backoff/ExponentialBackOff.html[`ExponentialBackOff`] for an example.
|
||||
|
||||
NOTE: Like its sibling (xref:integration/jms/using.adoc#jms-mdp-simple[`SimpleMessageListenerContainer`]),
|
||||
`DefaultMessageListenerContainer` supports native JMS transactions and allows for
|
||||
|
||||
@@ -246,7 +246,7 @@ instance. The `NotificationPublisherAware` interface supplies an instance of a
|
||||
which the bean can then use to publish `Notifications`.
|
||||
|
||||
As stated in the javadoc of the
|
||||
{api-spring-framework}/jmx/export/notification/NotificationPublisher.html[`NotificationPublisher`]
|
||||
{spring-framework-api}/jmx/export/notification/NotificationPublisher.html[`NotificationPublisher`]
|
||||
interface, managed beans that publish events through the `NotificationPublisher`
|
||||
mechanism are not responsible for the state management of notification listeners.
|
||||
Spring's JMX support takes care of handling all the JMX infrastructure issues.
|
||||
|
||||
@@ -6,10 +6,8 @@ This section contains links to further resources about JMX:
|
||||
|
||||
* The https://www.oracle.com/technetwork/java/javase/tech/javamanagement-140525.html[JMX
|
||||
homepage] at Oracle.
|
||||
* The https://jcp.org/aboutJava/communityprocess/final/jsr003/index3.html[JMX
|
||||
specification] (JSR-000003).
|
||||
* The https://jcp.org/aboutJava/communityprocess/final/jsr160/index.html[JMX Remote API
|
||||
specification] (JSR-000160).
|
||||
* The {JSR}003[JMX specification] (JSR-000003).
|
||||
* The {JSR}160[JMX Remote API specification] (JSR-000160).
|
||||
* The http://mx4j.sourceforge.net/[MX4J homepage]. (MX4J is an open-source implementation of
|
||||
various JMX specs.)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ Metrics can help you to track error rates, usage patterns, performance, and more
|
||||
Traces provide a holistic view of an entire system, crossing application boundaries; you can zoom in on particular user requests and follow their entire completion across applications.
|
||||
|
||||
Spring Framework instruments various parts of its own codebase to publish observations if an `ObservationRegistry` is configured.
|
||||
You can learn more about {docs-spring-boot}/html/actuator.html#actuator.metrics[configuring the observability infrastructure in Spring Boot].
|
||||
You can learn more about {spring-boot-docs}/actuator.html#actuator.metrics[configuring the observability infrastructure in Spring Boot].
|
||||
|
||||
|
||||
[[observability.list]]
|
||||
@@ -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).
|
||||
|
||||
@@ -344,7 +344,7 @@ The `spring-web` module contains the `HttpMessageConverter` interface for readin
|
||||
Concrete implementations for the main media (MIME) types are provided in the framework and are, by default, registered with the `RestClient` and `RestTemplate` on the client side and with `RequestMappingHandlerAdapter` on the server side (see xref:web/webmvc/mvc-config/message-converters.adoc[Configuring Message Converters]).
|
||||
|
||||
Several implementations of `HttpMessageConverter` are described below.
|
||||
Refer to the {api-spring-framework}/http/converter/HttpMessageConverter.html[`HttpMessageConverter` Javadoc] for the complete list.
|
||||
Refer to the {spring-framework-api}/http/converter/HttpMessageConverter.html[`HttpMessageConverter` Javadoc] for the complete list.
|
||||
For all converters, a default media type is used, but you can override it by setting the `supportedMediaTypes` property.
|
||||
|
||||
[[rest-message-converters-tbl]]
|
||||
@@ -384,7 +384,7 @@ When you need further control (for cases where custom JSON serializers/deseriali
|
||||
By default, this converter supports `application/json`.
|
||||
|
||||
| `MappingJackson2XmlHttpMessageConverter`
|
||||
| An `HttpMessageConverter` implementation that can read and write XML by using https://github.com/FasterXML/jackson-dataformat-xml[Jackson XML] extension's `XmlMapper`.
|
||||
| An `HttpMessageConverter` implementation that can read and write XML by using {jackson-github-org}/jackson-dataformat-xml[Jackson XML] extension's `XmlMapper`.
|
||||
You can customize XML mapping as needed through the use of JAXB or Jackson's provided annotations.
|
||||
When you need further control (for cases where custom XML serializers/deserializers need to be provided for specific types), you can inject a custom `XmlMapper` through the `ObjectMapper` property.
|
||||
By default, this converter supports `application/xml`.
|
||||
@@ -401,7 +401,7 @@ You can also set the message converters to use explicitly, by using `messageConv
|
||||
|
||||
==== Jackson JSON Views
|
||||
|
||||
To serialize only a subset of the object properties, you can specify a https://www.baeldung.com/jackson-json-view-annotation[Jackson JSON View], as the following example shows:
|
||||
To serialize only a subset of the object properties, you can specify a {baeldung-blog}/jackson-json-view-annotation[Jackson JSON View], as the following example shows:
|
||||
|
||||
[source,java,indent=0,subs="verbatim"]
|
||||
----
|
||||
@@ -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).
|
||||
|
||||
|
||||
|
||||
@@ -282,8 +284,8 @@ You can pick and choose the relevant annotations for your application. For examp
|
||||
if you need only support for `@Scheduled`, you can omit `@EnableAsync`. For more
|
||||
fine-grained control, you can additionally implement the `SchedulingConfigurer`
|
||||
interface, the `AsyncConfigurer` interface, or both. See the
|
||||
{api-spring-framework}/scheduling/annotation/SchedulingConfigurer.html[`SchedulingConfigurer`]
|
||||
and {api-spring-framework}/scheduling/annotation/AsyncConfigurer.html[`AsyncConfigurer`]
|
||||
{spring-framework-api}/scheduling/annotation/SchedulingConfigurer.html[`SchedulingConfigurer`]
|
||||
and {spring-framework-api}/scheduling/annotation/AsyncConfigurer.html[`AsyncConfigurer`]
|
||||
javadoc for full details.
|
||||
|
||||
If you prefer XML configuration, you can use the `<task:annotation-driven>` element,
|
||||
@@ -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"]
|
||||
@@ -722,7 +724,7 @@ In the preceding configuration, a `queue-capacity` value has also been provided.
|
||||
The configuration of the thread pool should also be considered in light of the
|
||||
executor's queue capacity. For the full description of the relationship between pool
|
||||
size and queue capacity, see the documentation for
|
||||
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ThreadPoolExecutor.html[`ThreadPoolExecutor`].
|
||||
{java-api}/java.base/java/util/concurrent/ThreadPoolExecutor.html[`ThreadPoolExecutor`].
|
||||
The main idea is that, when a task is submitted, the executor first tries to use a
|
||||
free thread if the number of active threads is currently less than the core size.
|
||||
If the core size has been reached, the task is added to the queue, as long as its
|
||||
@@ -1093,7 +1095,7 @@ we need to set up the `SchedulerFactoryBean`, as the following example shows:
|
||||
|
||||
More properties are available for the `SchedulerFactoryBean`, such as the calendars used by the
|
||||
job details, properties to customize Quartz with, and a Spring-provided JDBC DataSource. See
|
||||
the {api-spring-framework}/scheduling/quartz/SchedulerFactoryBean.html[`SchedulerFactoryBean`]
|
||||
the {spring-framework-api}/scheduling/quartz/SchedulerFactoryBean.html[`SchedulerFactoryBean`]
|
||||
javadoc for more information.
|
||||
|
||||
NOTE: `SchedulerFactoryBean` also recognizes a `quartz.properties` file in the classpath,
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
= Kotlin
|
||||
:page-section-summary-toc: 1
|
||||
|
||||
https://kotlinlang.org[Kotlin] is a statically typed language that targets the JVM
|
||||
{kotlin-site}[Kotlin] is a statically typed language that targets the JVM
|
||||
(and other platforms) which allows writing concise and elegant code while providing
|
||||
very good https://kotlinlang.org/docs/reference/java-interop.html[interoperability]
|
||||
very good {kotlin-docs}/java-interop.html[interoperability]
|
||||
with existing libraries written in Java.
|
||||
|
||||
The Spring Framework provides first-class support for Kotlin and lets developers write
|
||||
@@ -13,13 +13,13 @@ 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 https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-kotlin.html[dedicated Kotlin support].
|
||||
https://spring.io/guides/tutorials/spring-boot-kotlin/[This comprehensive tutorial]
|
||||
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].
|
||||
|
||||
Feel free to join the #spring channel of https://slack.kotlinlang.org/[Kotlin Slack]
|
||||
or ask a question with `spring` and `kotlin` as tags on
|
||||
https://stackoverflow.com/questions/tagged/spring+kotlin[Stackoverflow] if you need support.
|
||||
{stackoverflow-spring-kotlin-tags}[Stackoverflow] if you need support.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[[kotlin-annotations]]
|
||||
= Annotations
|
||||
|
||||
The Spring Framework also takes advantage of https://kotlinlang.org/docs/reference/null-safety.html[Kotlin null-safety]
|
||||
The Spring Framework also takes advantage of {kotlin-docs}/null-safety.html[Kotlin null-safety]
|
||||
to determine if an HTTP parameter is required without having to explicitly
|
||||
define the `required` attribute. That means `@RequestParam name: String?` is treated
|
||||
as not required and, conversely, `@RequestParam name: String` is treated as being required.
|
||||
@@ -20,9 +20,9 @@ type `Car` may or may not exist. The same behavior applies to autowired construc
|
||||
|
||||
NOTE: If you use bean validation on classes with properties or a primary constructor
|
||||
parameters, you may need to use
|
||||
https://kotlinlang.org/docs/reference/annotations.html#annotation-use-site-targets[annotation use-site targets],
|
||||
{kotlin-docs}/annotations.html#annotation-use-site-targets[annotation use-site targets],
|
||||
such as `@field:NotNull` or `@get:Size(min=5, max=15)`, as described in
|
||||
https://stackoverflow.com/a/35853200/1092077[this Stack Overflow response].
|
||||
{stackoverflow-site}/a/35853200/1092077[this Stack Overflow response].
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ the constructor parameters will be autowired by type:
|
||||
----
|
||||
|
||||
In order to allow a more declarative approach and cleaner syntax, Spring Framework provides
|
||||
a {docs-spring-framework}/kdoc-api/spring-context/org.springframework.context.support/-bean-definition-dsl/index.html[Kotlin bean definition DSL]
|
||||
a {spring-framework-api-kdoc}/spring-context/org.springframework.context.support/-bean-definition-dsl/index.html[Kotlin bean definition DSL]
|
||||
It declares an `ApplicationContextInitializer` through a clean declarative API,
|
||||
which lets you deal with profiles and `Environment` for customizing
|
||||
how beans are registered.
|
||||
@@ -104,10 +104,10 @@ as the following example shows:
|
||||
----
|
||||
|
||||
NOTE: Spring Boot is based on JavaConfig and
|
||||
https://github.com/spring-projects/spring-boot/issues/8115[does not yet provide specific support for functional bean definition],
|
||||
{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 https://stackoverflow.com/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 https://github.com/spring-projects/spring-fu[Spring Fu incubator].
|
||||
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}-experimental/spring-fu[Spring Fu incubator].
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ compiler flag to be enabled during compilation. (For completeness, we neverthele
|
||||
running the Kotlin compiler with its `-java-parameters` flag for standard Java parameter exposure.)
|
||||
|
||||
You can declare configuration classes as
|
||||
https://kotlinlang.org/docs/reference/nested-classes.html[top level or nested but not inner],
|
||||
{kotlin-docs}/nested-classes.html[top level or nested but not inner],
|
||||
since the later requires a reference to the outer class.
|
||||
|
||||
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
[[coroutines]]
|
||||
= Coroutines
|
||||
|
||||
Kotlin https://kotlinlang.org/docs/reference/coroutines-overview.html[Coroutines] are Kotlin
|
||||
Kotlin {kotlin-docs}/coroutines-overview.html[Coroutines] are Kotlin
|
||||
lightweight threads allowing to write non-blocking code in an imperative way. On language side,
|
||||
suspending functions provides an abstraction for asynchronous operations while on library side
|
||||
https://github.com/Kotlin/kotlinx.coroutines[kotlinx.coroutines] provides functions like
|
||||
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html[`async { }`]
|
||||
and types like https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html[`Flow`].
|
||||
{kotlin-github-org}/kotlinx.coroutines[kotlinx.coroutines] provides functions like
|
||||
{kotlin-coroutines-api}/kotlinx-coroutines-core/kotlinx.coroutines/async.html[`async { }`]
|
||||
and types like {kotlin-coroutines-api}/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html[`Flow`].
|
||||
|
||||
Spring Framework provides support for Coroutines on the following scope:
|
||||
|
||||
* https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/index.html[Deferred] and https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html[Flow] return values support in Spring MVC and WebFlux annotated `@Controller`
|
||||
* {kotlin-coroutines-api}/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/index.html[Deferred] and {kotlin-coroutines-api}/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html[Flow] return values support in Spring MVC and WebFlux annotated `@Controller`
|
||||
* Suspending function support in Spring MVC and WebFlux annotated `@Controller`
|
||||
* Extensions for WebFlux {docs-spring-framework}/kdoc-api/spring-webflux/org.springframework.web.reactive.function.client/index.html[client] and {docs-spring-framework}/kdoc-api/spring-webflux/org.springframework.web.reactive.function.server/index.html[server] functional API.
|
||||
* WebFlux.fn {docs-spring-framework}/kdoc-api/spring-webflux/org.springframework.web.reactive.function.server/co-router.html[coRouter { }] DSL
|
||||
* 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 {docs-spring-framework}/kdoc-api/spring-messaging/org.springframework.messaging.rsocket/index.html[`RSocketRequester`]
|
||||
* Extensions for {spring-framework-api-kdoc}/spring-messaging/org.springframework.messaging.rsocket/index.html[`RSocketRequester`]
|
||||
* Spring AOP
|
||||
|
||||
|
||||
|
||||
@@ -53,17 +55,17 @@ For input parameters:
|
||||
* If laziness is not needed, `fun handler(mono: Mono<T>)` becomes `fun handler(value: T)` since a suspending functions can be invoked to get the value parameter.
|
||||
* If laziness is needed, `fun handler(mono: Mono<T>)` becomes `fun handler(supplier: suspend () -> T)` or `fun handler(supplier: suspend () -> T?)`
|
||||
|
||||
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html[`Flow`] is `Flux` equivalent in Coroutines world, suitable for hot or cold stream, finite or infinite streams, with the following main differences:
|
||||
{kotlin-coroutines-api}/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html[`Flow`] is `Flux` equivalent in Coroutines world, suitable for hot or cold stream, finite or infinite streams, with the following main differences:
|
||||
|
||||
* `Flow` is push-based while `Flux` is push-pull hybrid
|
||||
* Backpressure is implemented via suspending functions
|
||||
* `Flow` has only a https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/collect.html[single suspending `collect` method] and operators are implemented as https://kotlinlang.org/docs/reference/extensions.html[extensions]
|
||||
* https://github.com/Kotlin/kotlinx.coroutines/tree/master/kotlinx-coroutines-core/common/src/flow/operators[Operators are easy to implement] thanks to Coroutines
|
||||
* `Flow` has only a {kotlin-coroutines-api}/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/collect.html[single suspending `collect` method] and operators are implemented as {kotlin-docs}/extensions.html[extensions]
|
||||
* {kotlin-github-org}/kotlinx.coroutines/tree/master/kotlinx-coroutines-core/common/src/flow/operators[Operators are easy to implement] thanks to Coroutines
|
||||
* Extensions allow to add custom operators to `Flow`
|
||||
* Collect operations are suspending functions
|
||||
* https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/map.html[`map` operator] supports asynchronous operation (no need for `flatMap`) since it takes a suspending function parameter
|
||||
* {kotlin-coroutines-api}/kotlinx-coroutines-core/kotlinx.coroutines.flow/map.html[`map` operator] supports asynchronous operation (no need for `flatMap`) since it takes a suspending function parameter
|
||||
|
||||
Read this blog post about https://spring.io/blog/2019/04/12/going-reactive-with-spring-coroutines-and-kotlin-flow[Going Reactive with Spring, Coroutines and Kotlin Flow]
|
||||
Read this blog post about {spring-site-blog}/2019/04/12/going-reactive-with-spring-coroutines-and-kotlin-flow[Going Reactive with Spring, Coroutines and Kotlin Flow]
|
||||
for more details, including how to run code concurrently with Coroutines.
|
||||
|
||||
|
||||
@@ -170,7 +172,7 @@ class CoroutinesViewController(banner: Banner) {
|
||||
[[webflux-fn]]
|
||||
== WebFlux.fn
|
||||
|
||||
Here is an example of Coroutines router defined via the {docs-spring-framework}/kdoc-api/spring-webflux/org.springframework.web.reactive.function.server/co-router.html[coRouter { }] DSL and related handlers.
|
||||
Here is an example of Coroutines router defined via the {spring-framework-api-kdoc}/spring-webflux/org.springframework.web.reactive.function.server/co-router.html[coRouter { }] DSL and related handlers.
|
||||
|
||||
[source,kotlin,indent=0]
|
||||
----
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[[kotlin-extensions]]
|
||||
= Extensions
|
||||
|
||||
Kotlin https://kotlinlang.org/docs/reference/extensions.html[extensions] provide the ability
|
||||
Kotlin {kotlin-docs}/extensions.html[extensions] provide the ability
|
||||
to extend existing classes with additional functionality. The Spring Framework Kotlin APIs
|
||||
use these extensions to add new Kotlin-specific conveniences to existing Spring APIs.
|
||||
|
||||
The {docs-spring-framework}/kdoc-api/[Spring Framework KDoc API] lists
|
||||
The {spring-framework-api-kdoc}/[Spring Framework KDoc API] lists
|
||||
and documents all available Kotlin extensions and DSLs.
|
||||
|
||||
NOTE: Keep in mind that Kotlin extensions need to be imported to be used. This means,
|
||||
@@ -13,8 +13,8 @@ for example, that the `GenericApplicationContext.registerBean` Kotlin extension
|
||||
is available only if `org.springframework.context.support.registerBean` is imported.
|
||||
That said, similar to static imports, an IDE should automatically suggest the import in most cases.
|
||||
|
||||
For example, https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters[Kotlin reified type parameters]
|
||||
provide a workaround for JVM https://docs.oracle.com/javase/tutorial/java/generics/erasure.html[generics type erasure],
|
||||
For example, {kotlin-docs}/inline-functions.html#reified-type-parameters[Kotlin reified type parameters]
|
||||
provide a workaround for JVM {java-tutorial}/java/generics/erasure.html[generics type erasure],
|
||||
and the Spring Framework provides some extensions to take advantage of this feature.
|
||||
This allows for a better Kotlin API `RestTemplate`, for the new `WebClient` from Spring
|
||||
WebFlux, and for various other APIs.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
= Getting Started
|
||||
|
||||
The easiest way to learn how to build a Spring application with Kotlin is to follow
|
||||
https://spring.io/guides/tutorials/spring-boot-kotlin/[the dedicated tutorial].
|
||||
{spring-site-guides}/tutorials/spring-boot-kotlin/[the dedicated tutorial].
|
||||
|
||||
|
||||
|
||||
@@ -10,22 +10,21 @@ https://spring.io/guides/tutorials/spring-boot-kotlin/[the dedicated tutorial].
|
||||
== `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.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
[[kotlin-null-safety]]
|
||||
= Null-safety
|
||||
|
||||
One of Kotlin's key features is https://kotlinlang.org/docs/reference/null-safety.html[null-safety],
|
||||
One of Kotlin's key features is {kotlin-docs}/null-safety.html[null-safety],
|
||||
which cleanly deals with `null` values at compile time rather than bumping into the famous
|
||||
`NullPointerException` at runtime. This makes applications safer through nullability
|
||||
declarations and expressing "`value or no value`" semantics without paying the cost of wrappers, such as `Optional`.
|
||||
(Kotlin allows using functional constructs with nullable values. See this
|
||||
https://www.baeldung.com/kotlin-null-safety[comprehensive guide to Kotlin null-safety].)
|
||||
{baeldung-blog}/kotlin-null-safety[comprehensive guide to Kotlin null-safety].)
|
||||
|
||||
Although Java does not let you express null-safety in its type-system, the Spring Framework
|
||||
provides xref:languages/kotlin/null-safety.adoc[null-safety of the whole Spring Framework API]
|
||||
via tooling-friendly annotations declared in the `org.springframework.lang` package.
|
||||
By default, types from Java APIs used in Kotlin are recognized as
|
||||
https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types[platform types],
|
||||
{kotlin-docs}/java-interop.html#null-safety-and-platform-types[platform types],
|
||||
for which null-checks are relaxed.
|
||||
https://kotlinlang.org/docs/reference/java-interop.html#jsr-305-support[Kotlin support for JSR-305 annotations]
|
||||
{kotlin-docs}/java-interop.html#jsr-305-support[Kotlin support for JSR-305 annotations]
|
||||
and Spring nullability annotations provide null-safety for the whole Spring Framework API to Kotlin developers,
|
||||
with the advantage of dealing with `null`-related issues at compile time.
|
||||
|
||||
@@ -30,7 +30,7 @@ API nullability declaration could evolve even between minor releases and that mo
|
||||
be added in the future.
|
||||
|
||||
NOTE: Generic type arguments, varargs, and array elements nullability are not supported yet,
|
||||
but should be in an upcoming release. See https://github.com/Kotlin/KEEP/issues/79[this discussion]
|
||||
but should be in an upcoming release. See {kotlin-github-org}/KEEP/issues/79[this discussion]
|
||||
for up-to-date information.
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user