mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
231 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| daf9551578 | |||
| 76a36dfd70 | |||
| 3d47da9746 | |||
| 519d7332eb | |||
| ec89834fa8 | |||
| b294371a46 | |||
| 1829b42b9c | |||
| 86d99790db | |||
| 3aaec98765 | |||
| ee4e79002b | |||
| ce90e4b11f | |||
| 224e647e1b | |||
| c0d399ab88 | |||
| 5c4497a96c | |||
| 0fadafa9bc | |||
| f161a419bd | |||
| 244f6ec390 | |||
| cca70d4ad2 | |||
| 96b44949a8 | |||
| 2555655ccf | |||
| ecfa498ea9 | |||
| e2646fe324 | |||
| a22818564b | |||
| c37ba027e7 | |||
| 2dd550d80f | |||
| 9ca396e424 | |||
| 2eb0ba3843 | |||
| cc48200b65 | |||
| 44150f2523 | |||
| a0a3fe41f6 | |||
| de18f74c53 | |||
| 89ecaea937 | |||
| 444877a475 | |||
| 57b62dd73a | |||
| 5f661f1b64 | |||
| b0137977d8 | |||
| 425ce8625a | |||
| 85c578b929 | |||
| cf727bd7c8 | |||
| e8f08b4158 | |||
| c6b485c31d | |||
| b8ddd2c690 | |||
| a42a6e0c6a | |||
| 8a93a88962 | |||
| fdcf4d50f0 | |||
| 3c023114fb | |||
| 8b5cbb7496 | |||
| a58fdeaf3f | |||
| e4bfdfa229 | |||
| 46867fad81 | |||
| 371dcc5c13 | |||
| dc032c1e33 | |||
| 626907bbfd | |||
| 8d51f47357 | |||
| fb0c78ae27 | |||
| 9f431e2eac | |||
| cba8f225d9 | |||
| 515152b645 | |||
| f6671e77e2 | |||
| b338fdd99d | |||
| 4e3f264f34 | |||
| 9e0b83ead3 | |||
| af4b1229a5 | |||
| 623ccd1a4f | |||
| 69068ba33d | |||
| f182f9a76b | |||
| 9d144487e7 | |||
| b07bc2cb99 | |||
| 57d4765131 | |||
| cbdec804a5 | |||
| 438b1011fe | |||
| c5e560574c | |||
| 589e58e400 | |||
| 6101419d80 | |||
| 63cd96fa5f | |||
| 923ec6a8e1 | |||
| 241a7dca02 | |||
| d675132ac0 | |||
| 2801c7e23e | |||
| d356e7a238 | |||
| df198987e0 | |||
| b6a246989f | |||
| 2a9afd6ede | |||
| 9c82638820 | |||
| b2069e4c37 | |||
| 659271cf61 | |||
| 39a6d4709f | |||
| d78d80b02a | |||
| 684b1e8a4b | |||
| 6f204bf4a3 | |||
| 5873e40782 | |||
| 153e553675 | |||
| 9ceb9efb2c | |||
| 9af3961b9b | |||
| fa04db3b03 | |||
| 1a05ed236e | |||
| 5a4a14c9c2 | |||
| aff0ce1a00 | |||
| cdfb77d5b0 | |||
| 41f4072670 | |||
| 49bb287800 | |||
| db6111fabe | |||
| 522a2e2e80 | |||
| 0c2375a08c | |||
| b7137c5baf | |||
| 315591f18e | |||
| 96a028a028 | |||
| 8b67472e35 | |||
| 3997551ba5 | |||
| e607f1c30f | |||
| 506c6f1777 | |||
| 6d6b788b25 | |||
| 01248c7753 | |||
| 40562e2485 | |||
| 52345c56a7 | |||
| e598df8c60 | |||
| 0c4ed55fd2 | |||
| 10faa7fdff | |||
| 2269c56d61 | |||
| 15c82d558d | |||
| b4646ce9b4 | |||
| 317a1f9909 | |||
| de6601fdac | |||
| 47dc1c4d93 | |||
| d8c77934ff | |||
| 99fbce1254 | |||
| d1e69a9677 | |||
| 8dc888e1b8 | |||
| 131f94fbc5 | |||
| d4f4c69318 | |||
| 74ab6625ac | |||
| 7c27183a4f | |||
| 526f67cd83 | |||
| 88f081b1cd | |||
| 5806a23bcf | |||
| 507399d9a8 | |||
| cd9a430869 | |||
| 0a933787a6 | |||
| 2bbea84830 | |||
| b9517b8ed7 | |||
| f41786b6af | |||
| 2d10d513e1 | |||
| c83fb69d9b | |||
| 566a42bec9 | |||
| b426ef2d1b | |||
| 728466dce0 | |||
| 455cb766a9 | |||
| c77993acac | |||
| f3d0f9427a | |||
| 688975e327 | |||
| b619e69130 | |||
| 972ba739aa | |||
| f87b5ee326 | |||
| 7768cee7a0 | |||
| 9042682b56 | |||
| 2d81a9fe9b | |||
| a3f7179ab3 | |||
| 50ef3b0a29 | |||
| 1c7e79026f | |||
| c8735efb9d | |||
| 999bbe3959 | |||
| acab61f9a7 | |||
| bfa81290b3 | |||
| 2c7ed5e5f1 | |||
| 474d520182 | |||
| 50bffe7ddc | |||
| 6d849bd9b0 | |||
| 8334388e20 | |||
| 757b713f22 | |||
| a065563484 | |||
| 6162d89042 | |||
| 5c537db2cc | |||
| 849553dc8e | |||
| 7240a5a669 | |||
| b00c387775 | |||
| 8396c071af | |||
| bb35e9f11c | |||
| a0319b1f91 | |||
| 5973a17253 | |||
| ed7243259b | |||
| a391db2ef5 | |||
| 957202523c | |||
| a3c9166da7 | |||
| 0c3dd8cb00 | |||
| 56d8ec25e8 | |||
| fb9db146f2 | |||
| dcf98bc55c | |||
| b9cd06a487 | |||
| 91ff706e8c | |||
| 103057de2a | |||
| b6d1e88563 | |||
| af1e9da3d7 | |||
| bc5e395a42 | |||
| 1ec3cb4d5f | |||
| 7b7126ae3d | |||
| 9f1332c716 | |||
| 2ff93f4207 | |||
| 3a6c7786a1 | |||
| 539a098f8c | |||
| ecfd78ff93 | |||
| 1e0a85368e | |||
| c49d5dc860 | |||
| 58af70f2e3 | |||
| c6e73b5d1d | |||
| f531cc9fdf | |||
| 1977f31821 | |||
| cf3ed229de | |||
| 154dad6587 | |||
| fd8b4d5936 | |||
| 13defc09f9 | |||
| 9e512315ab | |||
| c750efb0a6 | |||
| 0033edad45 | |||
| 183cd4c8cd | |||
| 6bd0ed8e79 | |||
| dcb7922a24 | |||
| 05a9cc26ae | |||
| 05beb4ad4d | |||
| 5236b35687 | |||
| 7482ccc18f | |||
| b3fb9f4e31 | |||
| add3b1a7f4 | |||
| 476aae5ce8 | |||
| be68a777b6 | |||
| 9a0bfd7306 | |||
| 91a0c28fa9 | |||
| c0e8a36592 | |||
| 836289315d | |||
| 08b77dd0ad | |||
| 5eb16a6a17 | |||
| d4705804cc |
@@ -24,14 +24,14 @@ runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Set Up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: ${{ inputs.java-early-access == 'true' && 'temurin' || (inputs.java-distribution || 'liberica') }}
|
||||
java-version: |
|
||||
${{ inputs.java-early-access == 'true' && format('{0}-ea', inputs.java-version) || inputs.java-version }}
|
||||
${{ inputs.java-toolchain == 'true' && '17' || '' }}
|
||||
- name: Set Up Gradle
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # v5.0.0
|
||||
with:
|
||||
cache-read-only: false
|
||||
develocity-access-key: ${{ inputs.develocity-access-key }}
|
||||
|
||||
@@ -17,14 +17,14 @@ runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Set Up JFrog CLI
|
||||
uses: jfrog/setup-jfrog-cli@f748a0599171a192a2668afee8d0497f7c1069df # v4.5.6
|
||||
uses: jfrog/setup-jfrog-cli@5b06f730cc5a6f55d78b30753f8583454b08c0aa # v4.8.1
|
||||
env:
|
||||
JF_ENV_SPRING: ${{ inputs.jfrog-cli-config-token }}
|
||||
- name: Download Release Artifacts
|
||||
shell: bash
|
||||
run: jf rt download --spec ${{ format('{0}/artifacts.spec', github.action_path) }} --spec-vars 'buildName=${{ format('spring-framework-{0}', inputs.spring-framework-version) }};buildNumber=${{ github.run_number }}'
|
||||
- name: Sync
|
||||
uses: spring-io/central-publish-action@0cdd90d12e6876341e82860d951e1bcddc1e51b6 # v0.2.0
|
||||
uses: spring-io/central-publish-action@0c03960e9b16fdfe70e2443e1d5393cbc3a35622 # v0.3.0
|
||||
with:
|
||||
token: ${{ inputs.central-token-password }}
|
||||
token-name: ${{ inputs.central-token-username }}
|
||||
|
||||
@@ -18,9 +18,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'liberica'
|
||||
java-version: 17
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
- name: Build and Publish
|
||||
id: build-and-publish
|
||||
uses: ./.github/actions/build
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
publish: true
|
||||
- name: Deploy
|
||||
uses: spring-io/artifactory-deploy-action@dc1913008c0599f0c4b1fdafb6ff3c502b3565ea # v0.0.2
|
||||
uses: spring-io/artifactory-deploy-action@926d7f7cc810569395346bf3a4d91b380b3e355b # v0.0.4
|
||||
with:
|
||||
artifact-properties: |
|
||||
/**/framework-api-*.zip::zip.name=spring-framework,zip.deployed=false
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
- name: Build
|
||||
id: build
|
||||
uses: ./.github/actions/build
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
uses: ./.github/actions/print-jvm-thread-dumps
|
||||
- name: Upload Build Reports
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: build-reports
|
||||
path: '**/build/reports/'
|
||||
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
git config --global core.longPaths true
|
||||
Stop-Service -name Docker
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
- name: Build
|
||||
id: build
|
||||
uses: ./.github/actions/build
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
ref: docs-build
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
- name: Build and Publish
|
||||
id: build-and-publish
|
||||
uses: ./.github/actions/build
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
publish: true
|
||||
- name: Stage Release
|
||||
uses: spring-io/artifactory-deploy-action@dc1913008c0599f0c4b1fdafb6ff3c502b3565ea # v0.0.2
|
||||
uses: spring-io/artifactory-deploy-action@926d7f7cc810569395346bf3a4d91b380b3e355b # v0.0.4
|
||||
with:
|
||||
artifact-properties: |
|
||||
/**/framework-api-*.zip::zip.name=spring-framework,zip.deployed=false
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@v6
|
||||
- name: Sync to Maven Central
|
||||
uses: ./.github/actions/sync-to-maven-central
|
||||
with:
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up JFrog CLI
|
||||
uses: jfrog/setup-jfrog-cli@dff217c085c17666e8849ebdbf29c8fe5e3995e6 # v4.5.2
|
||||
uses: jfrog/setup-jfrog-cli@5b06f730cc5a6f55d78b30753f8583454b08c0aa # v4.8.1
|
||||
env:
|
||||
JF_ENV_SPRING: ${{ secrets.JF_ARTIFACTORY_SPRING }}
|
||||
- name: Promote build
|
||||
@@ -85,7 +85,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@v6
|
||||
- name: Create GitHub Release
|
||||
uses: ./.github/actions/create-github-release
|
||||
with:
|
||||
|
||||
@@ -30,23 +30,23 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check Out Release Verification Tests
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: 'v0.0.2'
|
||||
repository: spring-projects/spring-framework-release-verification
|
||||
token: ${{ secrets.token }}
|
||||
- name: Check Out Send Notification Action
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: send-notification
|
||||
sparse-checkout: .github/actions/send-notification
|
||||
- name: Set Up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'liberica'
|
||||
java-version: 17
|
||||
- name: Set Up Gradle
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # v5.0.0
|
||||
with:
|
||||
cache-read-only: false
|
||||
- name: Configure Gradle Properties
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
run: ./gradlew spring-framework-release-verification-tests:test
|
||||
- name: Upload Build Reports on Failure
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: build-reports
|
||||
path: '**/build/reports/'
|
||||
|
||||
@@ -9,6 +9,7 @@ ivy-cache
|
||||
argfile*
|
||||
activemq-data/
|
||||
classes/
|
||||
.cursor/
|
||||
|
||||
# Log files
|
||||
jxl.log
|
||||
|
||||
+2
-6
@@ -91,14 +91,10 @@ configure([rootProject] + javaProjects) { project ->
|
||||
"https://fasterxml.github.io/jackson-core/javadoc/2.14/",
|
||||
"https://fasterxml.github.io/jackson-databind/javadoc/2.14/",
|
||||
"https://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.14/",
|
||||
"https://hc.apache.org/httpcomponents-client-5.5.x/current/httpclient5/apidocs/",
|
||||
//"https://hc.apache.org/httpcomponents-client-5.5.x/current/httpclient5/apidocs/",
|
||||
"https://projectreactor.io/docs/test/release/api/",
|
||||
"https://junit.org/junit4/javadoc/4.13.2/",
|
||||
// TODO Uncomment link to JUnit 5 docs once we execute Gradle with Java 18+.
|
||||
// See https://github.com/spring-projects/spring-framework/issues/27497
|
||||
//
|
||||
// "https://junit.org/junit5/docs/5.14.1/api/",
|
||||
"https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/",
|
||||
"https://www.reactive-streams.org/reactive-streams-1.0.4-javadoc/",
|
||||
//"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/",
|
||||
"https://r2dbc.io/spec/1.0.0.RELEASE/api/",
|
||||
// Previously there could be a split-package issue between JSR250 and JSR305 javax.annotation packages,
|
||||
|
||||
@@ -15,8 +15,8 @@ content:
|
||||
# https://docs.antora.org/antora/latest/playbook/content-refname-matching/
|
||||
# branches: We include snapshots for main, 6.2.x, and 7.0.x to 9.*.x.
|
||||
branches: ['main', '6.2.x', '{7..9}.+({0..9}).x']
|
||||
# tags: We effectively include all releases from 6.0.9 to 9.*.*.
|
||||
tags: ['v{6..9}.+({0..9}).+({0..9})?(-{RC,M}*)', '!(v6.0.{0..8})', '!(v6.0.0-{RC,M}{0..9})']
|
||||
# tags: include all releases from 6.2.0 to 9.*.*.
|
||||
tags: ['v6.2.+({0..9})', 'v{7..9}.+({0..9}).+({0..9})?(-{RC,M}*)']
|
||||
start_path: framework-docs
|
||||
asciidoc:
|
||||
extensions:
|
||||
@@ -38,4 +38,4 @@ runtime:
|
||||
failure_level: warn
|
||||
ui:
|
||||
bundle:
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.25/ui-bundle.zip
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.26/ui-bundle.zip
|
||||
|
||||
@@ -17,6 +17,10 @@ antora {
|
||||
]
|
||||
}
|
||||
|
||||
node {
|
||||
version = '24.15.0'
|
||||
}
|
||||
|
||||
tasks.named("generateAntoraYml") {
|
||||
asciidocAttributes = project.provider( {
|
||||
return ["spring-version": project.version ]
|
||||
|
||||
@@ -326,9 +326,9 @@
|
||||
*** xref:testing/testcontext-framework/application-events.adoc[]
|
||||
*** xref:testing/testcontext-framework/test-execution-events.adoc[]
|
||||
*** xref:testing/testcontext-framework/ctx-management.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/javaconfig.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/xml.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/groovy.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/javaconfig.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/mixed-config.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/context-customizers.adoc[]
|
||||
**** xref:testing/testcontext-framework/ctx-management/initializers.adoc[]
|
||||
|
||||
@@ -74,6 +74,11 @@ expressions used in XML bean definitions, `@Value`, etc.
|
||||
| The mode to use when compiling expressions for the
|
||||
xref:core/expressions/evaluation.adoc#expressions-compiler-configuration[Spring Expression Language].
|
||||
|
||||
| `spring.expression.maxOperations`
|
||||
| The default maximum number of operations permitted during
|
||||
xref:core/expressions/evaluation.adoc#expressions-parser-configuration[Spring Expression Language]
|
||||
expression evaluation.
|
||||
|
||||
| `spring.getenv.ignore`
|
||||
| Instructs Spring to ignore operating system environment variables if a Spring
|
||||
`Environment` property -- for example, a placeholder in a configuration String -- isn't
|
||||
|
||||
@@ -104,7 +104,7 @@ Note that pointcut definitions are generally matched against any intercepted met
|
||||
If a pointcut is strictly meant to be public-only, even in a CGLIB proxy scenario with
|
||||
potential non-public interactions through proxies, it needs to be defined accordingly.
|
||||
|
||||
If your interception needs include method calls or even constructors within the target
|
||||
If your interception needs to include method calls or even constructors within the target
|
||||
class, consider the use of Spring-driven xref:core/aop/using-aspectj.adoc#aop-aj-ltw[native AspectJ weaving] instead
|
||||
of Spring's proxy-based AOP framework. This constitutes a different mode of AOP usage
|
||||
with different characteristics, so be sure to make yourself familiar with weaving
|
||||
|
||||
@@ -378,7 +378,7 @@ The container also supports creating a bean with {spring-framework-api}++/beans/
|
||||
|
||||
. The custom arguments require dynamic introspection of a matching constructor or factory method.
|
||||
Those arguments cannot be detected by AOT, so the necessary reflection hints will have to be provided manually.
|
||||
. By-passing the instance supplier means that all other optimizations after creation are skipped as well.
|
||||
. Bypassing the instance supplier means that all other optimizations after creation are skipped as well.
|
||||
For instance, autowiring on fields and methods will be skipped as they are handled in the instance supplier.
|
||||
|
||||
Rather than having prototype-scoped beans created with custom arguments, we recommend a manual factory pattern where a bean is responsible for the creation of the instance.
|
||||
|
||||
+11
-11
@@ -151,17 +151,17 @@ injected into a `Set<MovieCatalog>` annotated with `@Qualifier("action")`.
|
||||
[TIP]
|
||||
====
|
||||
Letting qualifier values select against target bean names, within the type-matching
|
||||
candidates, does not require a `@Qualifier` annotation at the injection point.
|
||||
If there is no other resolution indicator (such as a qualifier or a primary marker),
|
||||
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 (either by bean name or by associated alias).
|
||||
candidates, does not require a `@Qualifier` annotation at the injection point. If there
|
||||
is no other resolution indicator (such as a qualifier, a primary marker, or a fallback
|
||||
marker), 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 (either by bean name or by associated alias).
|
||||
|
||||
Since version 6.1, this requires the `-parameters` Java compiler flag to be present.
|
||||
As of 6.2, the container applies fast shortcut resolution for bean name matches,
|
||||
bypassing the full type matching algorithm when the parameter name matches the
|
||||
bean name and no type, qualifier or primary conditions override the match. It is
|
||||
therefore recommendable for your parameter names to match the target bean names.
|
||||
Since version 6.1, this requires the `-parameters` Java compiler flag to be present. As
|
||||
of 6.2, the container applies fast shortcut resolution for bean name matches, bypassing
|
||||
the full type matching algorithm when the parameter name matches the bean name and no
|
||||
type, qualifier, primary, or fallback conditions override the match. It is therefore
|
||||
recommendable for your parameter names to match the target bean names.
|
||||
====
|
||||
|
||||
As an alternative for injection by name, consider the JSR-250 `@Resource` annotation
|
||||
@@ -274,7 +274,7 @@ Kotlin::
|
||||
Next, you can provide the information for the candidate bean definitions. You can add
|
||||
`<qualifier/>` tags as sub-elements of the `<bean/>` tag and then specify the `type` and
|
||||
`value` to match your custom qualifier annotations. The type is matched against the
|
||||
fully-qualified class name of the annotation. Alternately, as a convenience if no risk of
|
||||
fully-qualified class name of the annotation. Alternatively, as a convenience if no risk of
|
||||
conflicting names exists, you can use the short class name. The following example
|
||||
demonstrates both approaches:
|
||||
|
||||
|
||||
@@ -308,7 +308,8 @@ set of multiple matches for the specific bean type (as returned by the factory m
|
||||
|
||||
Note that the standard `jakarta.annotation.Priority` annotation is not available at the
|
||||
`@Bean` level, since it cannot be declared on methods. Its semantics can be modeled
|
||||
through `@Order` values in combination with `@Primary` on a single bean for each type.
|
||||
through `@Order` values in combination with `@Primary` or `@Fallback` on a single bean
|
||||
for each type.
|
||||
====
|
||||
|
||||
Even typed `Map` instances can be autowired as long as the expected key type is `String`.
|
||||
|
||||
+2
-1
@@ -27,4 +27,5 @@ with the `CustomAutowireConfigurer`
|
||||
|
||||
When multiple beans qualify as autowire candidates, the determination of a "`primary`" is
|
||||
as follows: If exactly one bean definition among the candidates has a `primary`
|
||||
attribute set to `true`, it is selected.
|
||||
attribute set to `true`, it is selected. For annotation-based configuration, see
|
||||
xref:core/beans/annotation-config/autowired-primary.adoc[Fine-tuning with `@Primary` or `@Fallback`].
|
||||
|
||||
@@ -575,7 +575,7 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
NOTE: Do not define such beans to be lazy as the `ApplicationContext` will honour that and will not register the method to listen to events.
|
||||
NOTE: Do not define such beans to be lazy as the `ApplicationContext` will honor that and will not register the method to listen to events.
|
||||
|
||||
The method signature once again declares the event type to which it listens,
|
||||
but, this time, with a flexible name and without implementing a specific listener interface.
|
||||
|
||||
@@ -67,6 +67,13 @@ interface, clearly indicating the post-processor nature of that bean. Otherwise,
|
||||
Since a `BeanPostProcessor` needs to be instantiated early in order to apply to the
|
||||
initialization of other beans in the context, this early type detection is critical.
|
||||
|
||||
Furthermore, when registering a `BeanPostProcessor` via an `@Bean` factory method,
|
||||
declare the method as `static` and ideally with no dependencies. Doing so avoids eager
|
||||
initialization of the configuration class and other beans, which would make them
|
||||
ineligible for full post-processing (such as auto-proxying). See the
|
||||
"BeanPostProcessor-returning `@Bean` methods" section in the
|
||||
{spring-framework-api}/context/annotation/Bean.html[`@Bean`] javadoc for details.
|
||||
|
||||
[[beans-factory-programmatically-registering-beanpostprocessors]]
|
||||
.Programmatically registering `BeanPostProcessor` instances
|
||||
NOTE: While the recommended approach for `BeanPostProcessor` registration is through
|
||||
@@ -80,7 +87,7 @@ of execution. Note also that `BeanPostProcessor` instances registered programmat
|
||||
are always processed before those registered through auto-detection, regardless of any
|
||||
explicit ordering.
|
||||
|
||||
.`BeanPostProcessor` instances and AOP auto-proxying
|
||||
.`BeanPostProcessor` instances and early initialization
|
||||
[NOTE]
|
||||
====
|
||||
Classes that implement the `BeanPostProcessor` interface are special and are treated
|
||||
@@ -90,17 +97,23 @@ of the `ApplicationContext`. Next, all `BeanPostProcessor` instances are registe
|
||||
in a sorted fashion and applied to all further beans in the container. Because AOP
|
||||
auto-proxying is implemented as a `BeanPostProcessor` itself, neither `BeanPostProcessor`
|
||||
instances nor the beans they directly reference are eligible for auto-proxying and,
|
||||
thus, do not have aspects woven into them.
|
||||
thus, do not have aspects woven into them. More generally, any bean that is instantiated
|
||||
during this early phase is not eligible for full post-processing by all
|
||||
`BeanPostProcessor` instances.
|
||||
|
||||
For any such bean, you should see an informational log message: `Bean someBean is not
|
||||
eligible for getting processed by all BeanPostProcessor interfaces (for example: not
|
||||
eligible for auto-proxying)`.
|
||||
For any such bean, you should see a WARN-level log message similar to the following.
|
||||
|
||||
If you have beans wired into your `BeanPostProcessor` by using autowiring or
|
||||
`@Resource` (which may fall back to autowiring), Spring might access unexpected beans
|
||||
when searching for type-matching dependency candidates and, therefore, make them
|
||||
ineligible for auto-proxying or other kinds of bean post-processing. For example, if you
|
||||
have a dependency annotated with `@Resource` where the field or setter name does not
|
||||
[quote]
|
||||
Bean 'someBean' of type [org.example.SomeType] is not eligible for getting processed by
|
||||
all BeanPostProcessors (for example: not eligible for auto-proxying).
|
||||
|
||||
To minimize the number of beans affected, register a `BeanPostProcessor` with a
|
||||
`static` `@Bean` method that has no dependencies (see the note above). If you have
|
||||
beans wired into your `BeanPostProcessor` by using autowiring or `@Resource` (which
|
||||
may fall back to autowiring), Spring might access unexpected beans when searching
|
||||
for type-matching dependency candidates and, therefore, make them ineligible for
|
||||
auto-proxying or other kinds of bean post-processing. For example, if you have a
|
||||
dependency annotated with `@Resource` where the field or setter name does not
|
||||
directly correspond to the declared name of a bean and no name attribute is used,
|
||||
Spring accesses other beans for matching them by type.
|
||||
====
|
||||
@@ -135,7 +148,7 @@ Java::
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
System.out.println("Bean '" + beanName + "' created : " + bean.toString());
|
||||
System.out.println("Bean '" + beanName + "' created : " + bean);
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
@@ -164,7 +177,48 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
The following `beans` element uses the `InstantiationTracingBeanPostProcessor`:
|
||||
You can register the `InstantiationTracingBeanPostProcessor` with Java configuration
|
||||
by using a `static` `@Bean` method (recommended to avoid eager initialization of the
|
||||
configuration class and other beans):
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
|
||||
----
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
|
||||
@Bean
|
||||
public static InstantiationTracingBeanPostProcessor instantiationTracingBeanPostProcessor() {
|
||||
return new InstantiationTracingBeanPostProcessor();
|
||||
}
|
||||
|
||||
// ... other bean definitions
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
|
||||
----
|
||||
@Configuration
|
||||
class AppConfig {
|
||||
|
||||
@Bean
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun instantiationTracingBeanPostProcessor() = InstantiationTracingBeanPostProcessor()
|
||||
}
|
||||
|
||||
// ... other bean definitions
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
Alternatively, the `InstantiationTracingBeanPostProcessor` can be registered via the
|
||||
`bean` element with XML configuration:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -192,7 +246,7 @@ The following `beans` element uses the `InstantiationTracingBeanPostProcessor`:
|
||||
----
|
||||
|
||||
Notice how the `InstantiationTracingBeanPostProcessor` is merely defined. It does not
|
||||
even have a name, and, because it is a bean, it can be dependency-injected as you would any
|
||||
even have a name, and, because it is a bean, it can be dependency-injected as with any
|
||||
other bean. (The preceding configuration also defines a bean that is backed by a Groovy
|
||||
script. The Spring dynamic language support is detailed in the chapter entitled
|
||||
xref:languages/dynamic.adoc[Dynamic Language Support].)
|
||||
@@ -301,6 +355,23 @@ implement the `BeanFactoryPostProcessor` interface. It uses these beans as bean
|
||||
post-processors, at the appropriate time. You can deploy these post-processor beans as
|
||||
you would any other bean.
|
||||
|
||||
When registering a `BeanFactoryPostProcessor` via an `@Bean` factory method in a
|
||||
`@Configuration` class, declare the method as `static` to avoid lifecycle conflicts
|
||||
with annotation processing (such as `@Autowired`, `@Value`, and `@PostConstruct`) in the
|
||||
configuration class. See the "BeanFactoryPostProcessor-returning `@Bean` methods"
|
||||
section in the {spring-framework-api}/context/annotation/Bean.html[`@Bean`] javadoc
|
||||
for details and an example.
|
||||
|
||||
For any non-static `@Bean` factory method with a `BeanFactoryPostProcessor` return type,
|
||||
you should see an INFO-level log message similar to the following.
|
||||
|
||||
[quote]
|
||||
@Bean method MyConfig.myBfpp is non-static and returns an object assignable to Spring's
|
||||
BeanFactoryPostProcessor interface. This will result in a failure to process annotations
|
||||
such as @Autowired, @Resource, and @PostConstruct within the method's declaring
|
||||
@Configuration class. Add the 'static' modifier to this method to avoid these container
|
||||
lifecycle issues; see @Bean javadoc for complete details.
|
||||
|
||||
NOTE: As with ``BeanPostProcessor``s , you typically do not want to configure
|
||||
``BeanFactoryPostProcessor``s for lazy initialization. If no other bean references a
|
||||
`Bean(Factory)PostProcessor`, that post-processor will not get instantiated at all.
|
||||
|
||||
@@ -395,6 +395,16 @@ set a JVM system property or Spring property named `spring.context.expression.ma
|
||||
to the maximum expression length needed by your application (see
|
||||
xref:appendix.adoc#appendix-spring-properties[Supported Spring Properties]).
|
||||
|
||||
Similarly, the number of operations performed during the evaluation of a SpEL expression
|
||||
cannot exceed 10,000 by default; however, the `maxOperations` value is configurable. If
|
||||
you create a `SpelExpressionParser` programmatically (the recommend approach), you can
|
||||
specify a custom `maxOperations` value when creating the `SpelParserConfiguration` that
|
||||
you provide to the `SpelExpressionParser`. If you are not able to configure an explicit
|
||||
value for `maxOperations` via `SpelParserConfiguration`, you can set a JVM system
|
||||
property or Spring property named `spring.expression.maxOperations` to the maximum number
|
||||
of operations required by your application (see
|
||||
xref:appendix.adoc#appendix-spring-properties[Supported Spring Properties]).
|
||||
|
||||
|
||||
[[expressions-spel-compilation]]
|
||||
== SpEL Compilation
|
||||
|
||||
@@ -2,4 +2,12 @@
|
||||
= Language Reference
|
||||
:page-section-summary-toc: 1
|
||||
|
||||
This section describes how the Spring Expression Language works.
|
||||
Spring Expression Language (SpEL) expressions are composed of a sequence of tokens such
|
||||
as literals, operators, method invocations, and so forth.
|
||||
|
||||
Whitespace can be used freely between tokens to format and improve the readability of
|
||||
expressions. Specifically, the `\s` (space), `\t` (tab), `\r` (carriage return), and `\n`
|
||||
(newline) characters are all valid separators between tokens. However, whitespace is
|
||||
ignored by the expression parser unless it is part of a string literal.
|
||||
|
||||
The following sections describe the features and syntax of SpEL.
|
||||
|
||||
@@ -53,7 +53,7 @@ Kotlin::
|
||||
val trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean::class.java)
|
||||
|
||||
// uses CustomValue:::compareTo
|
||||
val trueValue = parser.parseExpression("new CustomValue(1) < new CustomValue(2)").getValue(Boolean::class.java);
|
||||
val trueValue = parser.parseExpression("new CustomValue(1) < new CustomValue(2)").getValue(Boolean::class.java)
|
||||
----
|
||||
======
|
||||
|
||||
@@ -167,7 +167,7 @@ Kotlin::
|
||||
[CAUTION]
|
||||
====
|
||||
The syntax for the `between` operator is `<input> between {<range_begin>, <range_end>}`,
|
||||
which is effectively a shortcut for `<input> >= <range_begin> && <input> \<= <range_end>}`.
|
||||
which is effectively a shortcut for `<input> >= <range_begin> && <input> \<= <range_end>`.
|
||||
|
||||
Consequently, `1 between {1, 5}` evaluates to `true`, while `1 between {5, 1}` evaluates
|
||||
to `false`.
|
||||
@@ -312,13 +312,13 @@ Kotlin::
|
||||
|
||||
// evaluates to 'a'
|
||||
val ch = parser.parseExpression("'d' - 3")
|
||||
.getValue(Character::class.java);
|
||||
.getValue(Char::class.java)
|
||||
|
||||
// -- Repeat --
|
||||
|
||||
// evaluates to "abcabc"
|
||||
val repeated = parser.parseExpression("'abc' * 2")
|
||||
.getValue(String::class.java);
|
||||
.getValue(String::class.java)
|
||||
----
|
||||
======
|
||||
|
||||
@@ -485,7 +485,7 @@ Kotlin::
|
||||
|
||||
// -- Operator precedence --
|
||||
|
||||
val minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Int::class.java) // -21
|
||||
val minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Int::class.java) // -21
|
||||
----
|
||||
======
|
||||
|
||||
@@ -541,32 +541,7 @@ For example, if we want to overload the `ADD` operator to allow two lists to be
|
||||
concatenated using the `+` sign, we can implement a custom `OperatorOverloader` as
|
||||
follows.
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
pubic class ListConcatenation implements OperatorOverloader {
|
||||
|
||||
@Override
|
||||
public boolean overridesOperation(Operation operation, Object left, Object right) {
|
||||
return (operation == Operation.ADD &&
|
||||
left instanceof List && right instanceof List);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object operate(Operation operation, Object left, Object right) {
|
||||
if (operation == Operation.ADD &&
|
||||
left instanceof List list1 && right instanceof List list2) {
|
||||
|
||||
List result = new ArrayList(list1);
|
||||
result.addAll(list2);
|
||||
return result;
|
||||
}
|
||||
throw new UnsupportedOperationException(
|
||||
"No overload for operation %s and operands [%s] and [%s]"
|
||||
.formatted(operation, left, right));
|
||||
}
|
||||
}
|
||||
----
|
||||
include-code::./ListConcatenation[]
|
||||
|
||||
If we register `ListConcatenation` as the `OperatorOverloader` in a
|
||||
`StandardEvaluationContext`, we can then evaluate expressions like `{1, 2, 3} + {4, 5}`
|
||||
@@ -589,8 +564,8 @@ Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
StandardEvaluationContext context = StandardEvaluationContext()
|
||||
context.setOperatorOverloader(ListConcatenation())
|
||||
val context = StandardEvaluationContext()
|
||||
context.operatorOverloader = ListConcatenation()
|
||||
|
||||
// evaluates to a new list: [1, 2, 3, 4, 5]
|
||||
parser.parseExpression("{1, 2, 3} + {2 + 2, 5}").getValue(context, List::class.java)
|
||||
|
||||
+1
-1
@@ -270,7 +270,7 @@ is applicable for typical implementations of indexed structures.
|
||||
NOTE: `ReflectiveIndexAccessor` also implements `CompilableIndexAccessor` in order to
|
||||
support xref:core/expressions/evaluation.adoc#expressions-spel-compilation[compilation]
|
||||
to bytecode for read access. Note, however, that the configured read-method must be
|
||||
invokable via a `public` class or `public` interface for compilation to succeed.
|
||||
invocable via a `public` class or `public` interface for compilation to succeed.
|
||||
|
||||
The following code listings define a `Color` enum and `FruitMap` type that behaves like a
|
||||
map but does not implement the `java.util.Map` interface. Thus, if you want to index into
|
||||
|
||||
@@ -6,7 +6,7 @@ are set by using the `setVariable()` method in `EvaluationContext` implementatio
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Variable names must be begin with a letter (as defined below), an underscore, or a dollar
|
||||
Variable names must begin with a letter (as defined below), an underscore, or a dollar
|
||||
sign.
|
||||
|
||||
Variable names must be composed of one or more of the following supported types of
|
||||
|
||||
@@ -351,10 +351,10 @@ recognized and used as the `PropertyEditor` for `Something`-typed properties.
|
||||
[literal,subs="verbatim,quotes"]
|
||||
----
|
||||
com
|
||||
chank
|
||||
pop
|
||||
Something
|
||||
SomethingEditor // the PropertyEditor for the Something class
|
||||
└── example
|
||||
└── things
|
||||
├── *Something*
|
||||
└── *SomethingEditor* // the PropertyEditor for the Something class
|
||||
----
|
||||
|
||||
Note that you can also use the standard `BeanInfo` JavaBeans mechanism here as well
|
||||
@@ -366,10 +366,10 @@ following example uses the `BeanInfo` mechanism to explicitly register one or mo
|
||||
[literal,subs="verbatim,quotes"]
|
||||
----
|
||||
com
|
||||
chank
|
||||
pop
|
||||
Something
|
||||
SomethingBeanInfo // the BeanInfo for the Something class
|
||||
└── example
|
||||
└── things
|
||||
├── *Something*
|
||||
└── *SomethingBeanInfo* // the BeanInfo for the Something class
|
||||
----
|
||||
|
||||
The following Java source code for the referenced `SomethingBeanInfo` class
|
||||
|
||||
@@ -15,7 +15,7 @@ configuration options. You should instantiate the `SimpleJdbcInsert` in the data
|
||||
layer's initialization method. For this example, the initializing method is the
|
||||
`setDataSource` method. You do not need to subclass the `SimpleJdbcInsert` class. Instead,
|
||||
you can create a new instance and set the table name by using the `withTableName` method.
|
||||
Configuration methods for this class follow the `fluid` style that returns the instance
|
||||
Configuration methods for this class follow the `fluent` style that returns the instance
|
||||
of the `SimpleJdbcInsert`, which lets you chain all configuration methods. The following
|
||||
example uses only one configuration method (we show examples of multiple methods later):
|
||||
|
||||
@@ -349,11 +349,11 @@ parameters return the data read from the table.
|
||||
|
||||
You can declare `SimpleJdbcCall` in a manner similar to declaring `SimpleJdbcInsert`. You
|
||||
should instantiate and configure the class in the initialization method of your data-access
|
||||
layer. Compared to the `StoredProcedure` class, you need not create a subclass
|
||||
and you need not to declare parameters that can be looked up in the database metadata.
|
||||
The following example of a `SimpleJdbcCall` configuration uses the preceding stored
|
||||
procedure (the only configuration option, in addition to the `DataSource`, is the name
|
||||
of the stored procedure):
|
||||
layer. In contrast to the `StoredProcedure` class, you do not need to create a subclass,
|
||||
and you do not need to declare parameters that can be looked up in the database metadata.
|
||||
The following `SimpleJdbcCall` configuration example uses the preceding stored procedure.
|
||||
The only configuration option (other than the `DataSource`) is the name of the stored
|
||||
procedure.
|
||||
|
||||
[tabs]
|
||||
======
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ where all the underlying resources have to participate in the service-level tran
|
||||
|
||||
NOTE: By default, a participating transaction joins the characteristics of the outer scope,
|
||||
silently ignoring the local isolation level, timeout value, or read-only flag (if any).
|
||||
Consider switching the `validateExistingTransactions` flag to `true` on your transaction
|
||||
Consider switching the `validateExistingTransaction` flag to `true` on your transaction
|
||||
manager if you want isolation level declarations to be rejected when participating in
|
||||
an existing transaction with a different isolation level. This non-lenient mode also
|
||||
rejects read-only mismatches (that is, an inner read-write transaction that tries to participate
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
[[appendix]]
|
||||
= Appendix
|
||||
|
||||
|
||||
|
||||
|
||||
[[appendix.xsd-schemas]]
|
||||
== XML Schemas
|
||||
|
||||
This part of the appendix lists XML schemas related to integration technologies.
|
||||
|
||||
|
||||
|
||||
[[appendix.xsd-schemas-jee]]
|
||||
=== The `jee` Schema
|
||||
|
||||
@@ -172,7 +167,7 @@ different properties with `jee`:
|
||||
|
||||
The `<jee:local-slsb/>` element configures a reference to a local EJB Stateless Session Bean.
|
||||
|
||||
The following example shows how to configures a reference to a local EJB Stateless Session Bean
|
||||
The following example shows how to configure a reference to a local EJB Stateless Session Bean
|
||||
without `jee`:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
@@ -184,7 +179,7 @@ without `jee`:
|
||||
</bean>
|
||||
----
|
||||
|
||||
The following example shows how to configures a reference to a local EJB Stateless Session Bean
|
||||
The following example shows how to configure a reference to a local EJB Stateless Session Bean
|
||||
with `jee`:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
@@ -200,7 +195,7 @@ with `jee`:
|
||||
|
||||
The `<jee:local-slsb/>` element configures a reference to a local EJB Stateless Session Bean.
|
||||
|
||||
The following example shows how to configures a reference to a local EJB Stateless Session Bean
|
||||
The following example shows how to configure a reference to a local EJB Stateless Session Bean
|
||||
and a number of properties without `jee`:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
@@ -215,7 +210,7 @@ and a number of properties without `jee`:
|
||||
</bean>
|
||||
----
|
||||
|
||||
The following example shows how to configures a reference to a local EJB Stateless Session Bean
|
||||
The following example shows how to configure a reference to a local EJB Stateless Session Bean
|
||||
and a number of properties with `jee`:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
@@ -234,7 +229,7 @@ and a number of properties with `jee`:
|
||||
|
||||
The `<jee:remote-slsb/>` element configures a reference to a `remote` EJB Stateless Session Bean.
|
||||
|
||||
The following example shows how to configures a reference to a remote EJB Stateless Session Bean
|
||||
The following example shows how to configure a reference to a remote EJB Stateless Session Bean
|
||||
without `jee`:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
@@ -251,7 +246,7 @@ without `jee`:
|
||||
</bean>
|
||||
----
|
||||
|
||||
The following example shows how to configures a reference to a remote EJB Stateless Session Bean
|
||||
The following example shows how to configure a reference to a remote EJB Stateless Session Bean
|
||||
with `jee`:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
@@ -313,7 +308,7 @@ xref:integration/jmx/naming.adoc#jmx-context-mbeanexport[Configuring Annotation-
|
||||
=== The `cache` Schema
|
||||
|
||||
You can use the `cache` elements to enable support for Spring's `@CacheEvict`, `@CachePut`,
|
||||
and `@Caching` annotations. It it also supports declarative XML-based caching. See
|
||||
and `@Caching` annotations. The `cache` schema also supports declarative XML-based caching. See
|
||||
xref:integration/cache/annotations.adoc#cache-annotation-enable[Enabling Caching Annotations] and
|
||||
xref:integration/cache/declarative-xml.adoc[Declarative XML-based Caching] for details.
|
||||
|
||||
|
||||
@@ -13,4 +13,4 @@ running the Kotlin compiler with its `-java-parameters` flag for standard Java p
|
||||
|
||||
You can declare configuration classes as
|
||||
{kotlin-docs}/nested-classes.html[top level or nested but not inner],
|
||||
since the later requires a reference to the outer class.
|
||||
since the latter requires a reference to the outer class.
|
||||
|
||||
+1
-1
@@ -187,7 +187,7 @@ default mode may be set via the
|
||||
xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism.
|
||||
|
||||
The default mode may also be configured as a
|
||||
https://docs.junit.org/current/user-guide/#running-tests-config-params[JUnit Platform configuration parameter].
|
||||
https://docs.junit.org/current/running-tests/configuration-parameters.html[JUnit Platform configuration parameter].
|
||||
|
||||
If the `spring.test.constructor.autowire.mode` property is not set, test class
|
||||
constructors will not be automatically autowired.
|
||||
|
||||
+7
@@ -72,6 +72,13 @@ bean definition profiles programmatically by implementing a custom
|
||||
xref:testing/testcontext-framework/ctx-management/env-profiles.adoc#testcontext-ctx-management-env-profiles-ActiveProfilesResolver[`ActiveProfilesResolver`]
|
||||
and registering it by using the `resolver` attribute of `@ActiveProfiles`.
|
||||
|
||||
NOTE: When `@ActiveProfiles` is declared on a test class, the `spring.profiles.active`
|
||||
property (whether configured as a JVM system property or environment variable) is not
|
||||
taken into account by the TestContext Framework when determining active profiles. If
|
||||
you need to allow `spring.profiles.active` to override the profiles configured via
|
||||
`@ActiveProfiles`, you can implement a custom `ActiveProfilesResolver` as described in
|
||||
xref:testing/testcontext-framework/ctx-management/env-profiles.adoc[Context Configuration with Environment Profiles].
|
||||
|
||||
See xref:testing/testcontext-framework/ctx-management/env-profiles.adoc[Context Configuration with Environment Profiles],
|
||||
xref:testing/testcontext-framework/support-classes.adoc#testcontext-junit-jupiter-nested-test-configuration[`@Nested` test class configuration], and the
|
||||
{spring-framework-api}/test/context/ActiveProfiles.html[`@ActiveProfiles`] javadoc for
|
||||
|
||||
+143
@@ -130,6 +130,21 @@ Java::
|
||||
}
|
||||
----
|
||||
<1> Replace the bean with type `CustomService` with a Mockito mock.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@SpringJUnitConfig(TestConfig::class)
|
||||
class BeanOverrideTests {
|
||||
|
||||
@MockitoBean // <1>
|
||||
lateinit var customService: CustomService
|
||||
|
||||
// tests...
|
||||
}
|
||||
----
|
||||
<1> Replace the bean with type `CustomService` with a Mockito mock.
|
||||
======
|
||||
|
||||
In the example above, we are creating a mock for `CustomService`. If more than one bean
|
||||
@@ -158,6 +173,22 @@ Java::
|
||||
}
|
||||
----
|
||||
<1> Replace the bean named `service` with a Mockito mock.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@SpringJUnitConfig(TestConfig::class)
|
||||
class BeanOverrideTests {
|
||||
|
||||
@MockitoBean("service") // <1>
|
||||
lateinit var customService: CustomService
|
||||
|
||||
// tests...
|
||||
|
||||
}
|
||||
----
|
||||
<1> Replace the bean named `service` with a Mockito mock.
|
||||
======
|
||||
|
||||
The following `@SharedMocks` annotation registers two mocks by-type and one mock by-name.
|
||||
@@ -177,6 +208,19 @@ Java::
|
||||
----
|
||||
<1> Register `OrderService` and `UserService` mocks by-type.
|
||||
<2> Register `PrintingService` mock by-name.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@MockitoBean(types = [OrderService::class, UserService::class]) // <1>
|
||||
@MockitoBean(name = "ps1", types = [PrintingService::class]) // <2>
|
||||
annotation class SharedMocks
|
||||
----
|
||||
<1> Register `OrderService` and `UserService` mocks by-type.
|
||||
<2> Register `PrintingService` mock by-name.
|
||||
======
|
||||
|
||||
The following demonstrates how `@SharedMocks` can be used on a test class.
|
||||
@@ -207,6 +251,34 @@ Java::
|
||||
----
|
||||
<1> Register common mocks via the custom `@SharedMocks` annotation.
|
||||
<2> Optionally inject mocks to _stub_ or _verify_ them.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@SpringJUnitConfig(TestConfig::class)
|
||||
@SharedMocks // <1>
|
||||
class BeanOverrideTests {
|
||||
|
||||
@Autowired
|
||||
lateinit var orderService: OrderService // <2>
|
||||
|
||||
@Autowired
|
||||
lateinit var userService: UserService // <2>
|
||||
|
||||
@Autowired
|
||||
lateinit var ps1: PrintingService // <2>
|
||||
|
||||
// Inject other components that rely on the mocks.
|
||||
|
||||
@Test
|
||||
fun testThatDependsOnMocks() {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Register common mocks via the custom `@SharedMocks` annotation.
|
||||
<2> Optionally inject mocks to _stub_ or _verify_ them.
|
||||
======
|
||||
|
||||
TIP: The mocks can also be injected into `@Configuration` classes or other test-related
|
||||
@@ -236,6 +308,21 @@ Java::
|
||||
}
|
||||
----
|
||||
<1> Wrap the bean with type `CustomService` with a Mockito spy.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@SpringJUnitConfig(TestConfig::class)
|
||||
class BeanOverrideTests {
|
||||
|
||||
@MockitoSpyBean // <1>
|
||||
lateinit var customService: CustomService
|
||||
|
||||
// tests...
|
||||
}
|
||||
----
|
||||
<1> Wrap the bean with type `CustomService` with a Mockito spy.
|
||||
======
|
||||
|
||||
In the example above, we are wrapping the bean with type `CustomService`. If more than
|
||||
@@ -261,6 +348,21 @@ Java::
|
||||
}
|
||||
----
|
||||
<1> Wrap the bean named `service` with a Mockito spy.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@SpringJUnitConfig(TestConfig::class)
|
||||
class BeanOverrideTests {
|
||||
|
||||
@MockitoSpyBean("service") // <1>
|
||||
lateinit var customService: CustomService
|
||||
|
||||
// tests...
|
||||
}
|
||||
----
|
||||
<1> Wrap the bean named `service` with a Mockito spy.
|
||||
======
|
||||
|
||||
The following `@SharedSpies` annotation registers two spies by-type and one spy by-name.
|
||||
@@ -280,6 +382,19 @@ Java::
|
||||
----
|
||||
<1> Register `OrderService` and `UserService` spies by-type.
|
||||
<2> Register `PrintingService` spy by-name.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@MockitoSpyBean(types = [OrderService::class, UserService::class]) // <1>
|
||||
@MockitoSpyBean(name = "ps1", types = [PrintingService::class]) // <2>
|
||||
annotation class SharedSpies
|
||||
----
|
||||
<1> Register `OrderService` and `UserService` spies by-type.
|
||||
<2> Register `PrintingService` spy by-name.
|
||||
======
|
||||
|
||||
The following demonstrates how `@SharedSpies` can be used on a test class.
|
||||
@@ -310,6 +425,34 @@ Java::
|
||||
----
|
||||
<1> Register common spies via the custom `@SharedSpies` annotation.
|
||||
<2> Optionally inject spies to _stub_ or _verify_ them.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@SpringJUnitConfig(TestConfig::class)
|
||||
@SharedSpies // <1>
|
||||
class BeanOverrideTests {
|
||||
|
||||
@Autowired
|
||||
lateinit var orderService: OrderService // <2>
|
||||
|
||||
@Autowired
|
||||
lateinit var userService: UserService // <2>
|
||||
|
||||
@Autowired
|
||||
lateinit var ps1: PrintingService // <2>
|
||||
|
||||
// Inject other components that rely on the spies.
|
||||
|
||||
@Test
|
||||
fun testThatDependsOnMocks() {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Register common spies via the custom `@SharedSpies` annotation.
|
||||
<2> Optionally inject spies to _stub_ or _verify_ them.
|
||||
======
|
||||
|
||||
TIP: The spies can also be injected into `@Configuration` classes or other test-related
|
||||
|
||||
+43
@@ -73,6 +73,27 @@ Java::
|
||||
----
|
||||
<1> Mark a field for overriding the bean with type `CustomService`.
|
||||
<2> The result of this static method will be used as the instance and injected into the field.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
class OverrideBeanTests {
|
||||
@TestBean // <1>
|
||||
lateinit var customService: CustomService
|
||||
|
||||
// test case body...
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun customService(): CustomService { // <2>
|
||||
return MyFakeCustomService()
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Mark a field for overriding the bean with type `CustomService`.
|
||||
<2> The result of this static method will be used as the instance and injected into the field.
|
||||
======
|
||||
|
||||
In the example above, we are overriding the bean with type `CustomService`. If more than
|
||||
@@ -102,6 +123,28 @@ Java::
|
||||
<1> Mark a field for overriding the bean with name `service`, and specify that the
|
||||
factory method is named `createCustomService`.
|
||||
<2> The result of this static method will be used as the instance and injected into the field.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
class OverrideBeanTests {
|
||||
@TestBean(name = "service", methodName = "createCustomService") // <1>
|
||||
lateinit var customService: CustomService
|
||||
|
||||
// test case body...
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun createCustomService(): CustomService { // <2>
|
||||
return MyFakeCustomService()
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Mark a field for overriding the bean with name `service`, and specify that the
|
||||
factory method is named `createCustomService`.
|
||||
<2> The result of this static method will be used as the instance and injected into the field.
|
||||
======
|
||||
|
||||
[TIP]
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
In the previous sections, we have seen how to use MockMvc in conjunction with the raw
|
||||
HtmlUnit APIs. In this section, we use additional abstractions within the Selenium
|
||||
https://docs.seleniumhq.org/projects/webdriver/[WebDriver] to make things even easier.
|
||||
https://www.selenium.dev/documentation/webdriver/[WebDriver] to make things even easier.
|
||||
|
||||
[[mockmvc-server-htmlunit-webdriver-why]]
|
||||
== Why WebDriver and MockMvc?
|
||||
@@ -12,8 +12,8 @@ We can already use HtmlUnit and MockMvc, so why would we want to use WebDriver?
|
||||
Selenium WebDriver provides a very elegant API that lets us easily organize our code. To
|
||||
better show how it works, we explore an example in this section.
|
||||
|
||||
NOTE: Despite being a part of https://docs.seleniumhq.org/[Selenium], WebDriver does not
|
||||
require a Selenium Server to run your tests.
|
||||
NOTE: Despite being a part of https://www.selenium.dev/documentation/[Selenium],
|
||||
WebDriver does not require a Selenium Server to run your tests.
|
||||
|
||||
Suppose we need to ensure that a message is created properly. The tests involve finding
|
||||
the HTML form input elements, filling them out, and making various assertions.
|
||||
@@ -308,7 +308,7 @@ interested. These are of type `WebElement`. WebDriver's
|
||||
https://github.com/SeleniumHQ/selenium/wiki/PageFactory[`PageFactory`] lets us remove a
|
||||
lot of code from the HtmlUnit version of `CreateMessagePage` by automatically resolving
|
||||
each `WebElement`. The
|
||||
https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/PageFactory.html#initElements-org.openqa.selenium.WebDriver-java.lang.Class-[`PageFactory#initElements(WebDriver,Class<T>)`]
|
||||
https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/PageFactory.html#initElements-org.openqa.selenium.WebDriver-java.lang.Class-[`PageFactory#initElements(WebDriver,Class<T>)`]
|
||||
method automatically resolves each `WebElement` by using the field name and looking it up
|
||||
by the `id` or `name` of the element within the HTML page.
|
||||
<3> We can use the
|
||||
@@ -352,7 +352,7 @@ interested. These are of type `WebElement`. WebDriver's
|
||||
https://github.com/SeleniumHQ/selenium/wiki/PageFactory[`PageFactory`] lets us remove a
|
||||
lot of code from the HtmlUnit version of `CreateMessagePage` by automatically resolving
|
||||
each `WebElement`. The
|
||||
https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/PageFactory.html#initElements-org.openqa.selenium.WebDriver-java.lang.Class-[`PageFactory#initElements(WebDriver,Class<T>)`]
|
||||
https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/PageFactory.html#initElements-org.openqa.selenium.WebDriver-java.lang.Class-[`PageFactory#initElements(WebDriver,Class<T>)`]
|
||||
method automatically resolves each `WebElement` by using the field name and looking it up
|
||||
by the `id` or `name` of the element within the HTML page.
|
||||
<3> We can use the
|
||||
|
||||
@@ -19,6 +19,6 @@ meta-annotation. If a bootstrapper is not explicitly configured by using
|
||||
`WebTestContextBootstrapper` is used, depending on the presence of `@WebAppConfiguration`.
|
||||
|
||||
Since the `TestContextBootstrapper` SPI is likely to change in the future (to accommodate
|
||||
new requirements), we strongly encourage implementers not to implement this interface
|
||||
new requirements), we strongly encourage implementors not to implement this interface
|
||||
directly but rather to extend `AbstractTestContextBootstrapper` or one of its concrete
|
||||
subclasses instead.
|
||||
|
||||
+13
-14
@@ -49,7 +49,6 @@ Kotlin::
|
||||
<1> Injecting the `ApplicationContext`.
|
||||
======
|
||||
|
||||
|
||||
Similarly, if your test is configured to load a `WebApplicationContext`, you can inject
|
||||
the web application context into your test, as follows:
|
||||
|
||||
@@ -87,7 +86,6 @@ Kotlin::
|
||||
<2> Injecting the `WebApplicationContext`.
|
||||
======
|
||||
|
||||
|
||||
Dependency injection by using `@Autowired` is provided by the
|
||||
`DependencyInjectionTestExecutionListener`, which is configured by default
|
||||
(see xref:testing/testcontext-framework/fixture-di.adoc[Dependency Injection of Test Fixtures]).
|
||||
@@ -96,22 +94,23 @@ Dependency injection by using `@Autowired` is provided by the
|
||||
Test classes that use the TestContext framework do not need to extend any particular
|
||||
class or implement a specific interface to configure their application context. Instead,
|
||||
configuration is achieved by declaring the `@ContextConfiguration` annotation at the
|
||||
class level. If your test class does not explicitly declare application context resource
|
||||
locations or component classes, the configured `ContextLoader` determines how to load a
|
||||
context from a default location or default configuration classes. In addition to context
|
||||
resource locations and component classes, an application context can also be configured
|
||||
through application context initializers.
|
||||
class level. If your test class does not explicitly declare component classes or resource
|
||||
locations, the configured `ContextLoader` determines how to load a context from _default_
|
||||
configuration classes or a _default_ location. In addition to component classes and
|
||||
context resource locations, an application context can also be configured through
|
||||
xref:testing/testcontext-framework/ctx-management/context-customizers.adoc[context customizers]
|
||||
or xref:testing/testcontext-framework/ctx-management/initializers.adoc[context initializers].
|
||||
|
||||
The following sections explain how to use Spring's `@ContextConfiguration` annotation to
|
||||
configure a test `ApplicationContext` by using XML configuration files, Groovy scripts,
|
||||
component classes (typically `@Configuration` classes), or context initializers.
|
||||
Alternatively, you can implement and configure your own custom `SmartContextLoader` for
|
||||
advanced use cases.
|
||||
The following sections explain how to use `@ContextConfiguration` and related annotations
|
||||
to configure a test `ApplicationContext` by using component classes (typically
|
||||
`@Configuration` classes), XML configuration files, Groovy scripts, context customizers,
|
||||
or context initializers. Alternatively, you can implement and configure your own custom
|
||||
`SmartContextLoader` for advanced use cases.
|
||||
|
||||
* xref:testing/testcontext-framework/ctx-management/javaconfig.adoc[Context Configuration with Component Classes]
|
||||
* xref:testing/testcontext-framework/ctx-management/xml.adoc[Context Configuration with XML resources]
|
||||
* xref:testing/testcontext-framework/ctx-management/groovy.adoc[Context Configuration with Groovy Scripts]
|
||||
* xref:testing/testcontext-framework/ctx-management/javaconfig.adoc[Context Configuration with Component Classes]
|
||||
* xref:testing/testcontext-framework/ctx-management/mixed-config.adoc[Mixing XML, Groovy Scripts, and Component Classes]
|
||||
* xref:testing/testcontext-framework/ctx-management/mixed-config.adoc[Mixing Component Classes, XML, and Groovy Scripts]
|
||||
* xref:testing/testcontext-framework/ctx-management/context-customizers.adoc[Context Configuration with Context Customizers]
|
||||
* xref:testing/testcontext-framework/ctx-management/initializers.adoc[Context Configuration with Context Initializers]
|
||||
* xref:testing/testcontext-framework/ctx-management/inheritance.adoc[Context Configuration Inheritance]
|
||||
|
||||
+82
@@ -543,3 +543,85 @@ Kotlin::
|
||||
----
|
||||
======
|
||||
|
||||
The following example demonstrates how to implement and register a custom
|
||||
`SystemPropertyOverrideActiveProfilesResolver` that allows the `spring.profiles.active`
|
||||
property (when configured as a JVM system property) to override profiles configured via
|
||||
`@ActiveProfiles`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
// profiles resolved programmatically via a custom resolver that
|
||||
// allows "spring.profiles.active" to override @ActiveProfiles
|
||||
@ActiveProfiles(
|
||||
resolver = SystemPropertyOverrideActiveProfilesResolver.class,
|
||||
inheritProfiles = false)
|
||||
class TransferServiceTest extends AbstractIntegrationTest {
|
||||
// test body
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
// profiles resolved programmatically via a custom resolver that
|
||||
// allows "spring.profiles.active" to override @ActiveProfiles
|
||||
@ActiveProfiles(
|
||||
resolver = SystemPropertyOverrideActiveProfilesResolver::class,
|
||||
inheritProfiles = false)
|
||||
class TransferServiceTest : AbstractIntegrationTest() {
|
||||
// test body
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary",fold="-imports"]
|
||||
----
|
||||
import org.springframework.core.env.AbstractEnvironment;
|
||||
import org.springframework.test.context.support.DefaultActiveProfilesResolver;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public class SystemPropertyOverrideActiveProfilesResolver extends DefaultActiveProfilesResolver {
|
||||
|
||||
@Override
|
||||
public String[] resolve(Class<?> testClass) {
|
||||
String profiles = System.getProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME);
|
||||
if (StringUtils.hasText(profiles)) {
|
||||
return StringUtils.commaDelimitedListToStringArray(
|
||||
StringUtils.trimAllWhitespace(profiles));
|
||||
}
|
||||
return super.resolve(testClass);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",fold="-imports"]
|
||||
----
|
||||
import org.springframework.core.env.AbstractEnvironment
|
||||
import org.springframework.test.context.support.DefaultActiveProfilesResolver
|
||||
import org.springframework.util.StringUtils
|
||||
|
||||
class SystemPropertyOverrideActiveProfilesResolver : DefaultActiveProfilesResolver() {
|
||||
|
||||
override fun resolve(testClass: Class<*>): Array<String> {
|
||||
val profiles = System.getProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME)
|
||||
if (StringUtils.hasText(profiles)) {
|
||||
return StringUtils.commaDelimitedListToStringArray(
|
||||
StringUtils.trimAllWhitespace(profiles)
|
||||
)
|
||||
}
|
||||
return super.resolve(testClass)
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
+21
-22
@@ -1,33 +1,32 @@
|
||||
[[testcontext-ctx-management-mixed-config]]
|
||||
= Mixing XML, Groovy Scripts, and Component Classes
|
||||
= Mixing Component Classes, XML, and Groovy Scripts
|
||||
|
||||
It may sometimes be desirable to mix XML configuration files, Groovy scripts, and
|
||||
component classes (typically `@Configuration` classes) to configure an
|
||||
`ApplicationContext` for your tests. For example, if you use XML configuration in
|
||||
production, you may decide that you want to use `@Configuration` classes to configure
|
||||
It may sometimes be desirable to mix component classes (typically `@Configuration`
|
||||
classes), XML configuration files, or Groovy scripts to configure an `ApplicationContext`
|
||||
for your tests. For example, if you use XML configuration in production for legacy
|
||||
reasons, you may decide that you want to use `@Configuration` classes to configure
|
||||
specific Spring-managed components for your tests, or vice versa.
|
||||
|
||||
Furthermore, some third-party frameworks (such as Spring Boot) provide first-class
|
||||
support for loading an `ApplicationContext` from different types of resources
|
||||
simultaneously (for example, XML configuration files, Groovy scripts, and
|
||||
`@Configuration` classes). The Spring Framework, historically, has not supported this for
|
||||
standard deployments. Consequently, most of the `SmartContextLoader` implementations that
|
||||
the Spring Framework delivers in the `spring-test` module support only one resource type
|
||||
for each test context. However, this does not mean that you cannot use both. One
|
||||
exception to the general rule is that the `GenericGroovyXmlContextLoader` and
|
||||
simultaneously (for example, `@Configuration` classes, XML configuration files, and
|
||||
Groovy scripts). The Spring Framework, historically, has not supported this for standard
|
||||
deployments. Consequently, most of the `SmartContextLoader` implementations that the
|
||||
Spring Framework delivers in the `spring-test` module support only one resource type for
|
||||
each test context. However, this does not mean that you cannot use a mixture of resource
|
||||
types. One exception to the general rule is that the `GenericGroovyXmlContextLoader` and
|
||||
`GenericGroovyXmlWebContextLoader` support both XML configuration files and Groovy
|
||||
scripts simultaneously. Furthermore, third-party frameworks may choose to support the
|
||||
declaration of both `locations` and `classes` through `@ContextConfiguration`, and, with
|
||||
declaration of both `classes` and `locations` through `@ContextConfiguration`, and, with
|
||||
the standard testing support in the TestContext framework, you have the following options.
|
||||
|
||||
If you want to use resource locations (for example, XML or Groovy) and `@Configuration`
|
||||
classes to configure your tests, you must pick one as the entry point, and that one must
|
||||
include or import the other. For example, in XML or Groovy scripts, you can include
|
||||
`@Configuration` classes by using component scanning or defining them as normal Spring
|
||||
beans, whereas, in a `@Configuration` class, you can use `@ImportResource` to import XML
|
||||
configuration files or Groovy scripts. Note that this behavior is semantically equivalent
|
||||
If you want to use `@Configuration` classes and resource locations (for example, XML or
|
||||
Groovy) to configure your tests, you must pick one as the entry point, and that one must
|
||||
import or include the other. For example, in a `@Configuration` class, you can use
|
||||
`@ImportResource` to import XML configuration files or Groovy scripts; whereas, in XML or
|
||||
Groovy scripts, you can include `@Configuration` classes by using component scanning or
|
||||
defining them as normal Spring beans. Note that this behavior is semantically equivalent
|
||||
to how you configure your application in production: In production configuration, you
|
||||
define either a set of XML or Groovy resource locations or a set of `@Configuration`
|
||||
classes from which your production `ApplicationContext` is loaded, but you still have the
|
||||
freedom to include or import the other type of configuration.
|
||||
|
||||
define either a set of `@Configuration` classes or a set of XML or Groovy resource
|
||||
locations from which your production `ApplicationContext` is loaded, but you still have
|
||||
the freedom to import or include the other type of configuration.
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@ TestNG:
|
||||
* Dependency injection for test constructors, test methods, and test lifecycle callback
|
||||
methods. See xref:testing/testcontext-framework/support-classes.adoc#testcontext-junit-jupiter-di[Dependency
|
||||
Injection with the `SpringExtension`] for further details.
|
||||
* Powerful support for link:https://docs.junit.org/current/user-guide/#extensions-conditions[conditional
|
||||
* Powerful support for link:https://docs.junit.org/current/extensions/conditional-test-execution.html[conditional
|
||||
test execution] based on SpEL expressions, environment variables, system properties,
|
||||
and so on. See the documentation for `@EnabledIf` and `@DisabledIf` in
|
||||
xref:testing/annotations/integration-junit-jupiter.adoc[Spring JUnit Jupiter Testing Annotations]
|
||||
@@ -160,7 +160,7 @@ for further details.
|
||||
=== Dependency Injection with the `SpringExtension`
|
||||
|
||||
The `SpringExtension` implements the
|
||||
link:https://docs.junit.org/current/user-guide/#extensions-parameter-resolution[`ParameterResolver`]
|
||||
link:https://docs.junit.org/current/extensions/parameter-resolution.html[`ParameterResolver`]
|
||||
extension API from JUnit Jupiter, which lets Spring provide dependency injection for test
|
||||
constructors, test methods, and test lifecycle callback methods.
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ any `@RequestMapping` method to render an RFC 9457 response. This is processed a
|
||||
- The `status` property of `ProblemDetail` determines the HTTP status.
|
||||
- The `instance` property of `ProblemDetail` is set from the current URL path, if not
|
||||
already set.
|
||||
- For content negotiation, the Jackson `HttpMessageConverter` prefers
|
||||
"application/problem+json" over "application/json" when rendering a `ProblemDetail`,
|
||||
and also falls back on it if no compatible media type is found.
|
||||
- The Jackson JSON and XML message converters use "application/problem+json" or
|
||||
"application/problem+xml" respectively as the producible media types for `ProblemDetail`
|
||||
to ensure they are favored for content negotiation.
|
||||
|
||||
To enable RFC 9457 responses for Spring WebFlux exceptions and for any
|
||||
`ErrorResponseException`, extend `ResponseEntityExceptionHandler` and declare it as an
|
||||
|
||||
@@ -251,7 +251,8 @@ Kotlin::
|
||||
======
|
||||
|
||||
TIP: If you need to have a `LocalValidatorFactoryBean` injected somewhere, create a bean and
|
||||
mark it with `@Primary` in order to avoid conflict with the one declared in the MVC config.
|
||||
mark it with `@Primary`, or mark the one declared in the MVC config with `@Fallback`, in
|
||||
order to avoid conflict.
|
||||
|
||||
|
||||
[[webflux-config-content-negotiation]]
|
||||
|
||||
@@ -418,16 +418,23 @@ See the section on xref:web/webflux-cors.adoc[CORS] and the xref:web/webflux-cor
|
||||
You may want your controller endpoints to match routes with or without a trailing slash in the URL path.
|
||||
For example, both "GET /home" and "GET /home/" should be handled by a controller method annotated with `@GetMapping("/home")`.
|
||||
|
||||
Adding trailing slash variants to all mapping declarations is not the best way to handle this use case.
|
||||
The `UrlHandlerFilter` web filter has been designed for this purpose. It can be configured to:
|
||||
Spring provides `UrlHandlerFilter` that removes the trailing slash from URL paths to ensure a consistent view of paths with or without a trailing slash.
|
||||
This is important to avoid a mismatch between URL-based authorization decisions and web framework request mappings.
|
||||
The filter can remove the trailing slash in one of a couple of ways:
|
||||
|
||||
* respond with an HTTP redirect status when receiving URLs with trailing slashes, sending browsers to the non-trailing slash URL variant.
|
||||
* mutate the request to act as if the request was sent without a trailing slash and continue the processing of the request.
|
||||
* respond with an HTTP redirect status that sends clients to the same path without a trailing slash.
|
||||
* mutate the request to remove the trailing slash.
|
||||
|
||||
Here is how you can instantiate and configure a `UrlHandlerFilter` for a blog application:
|
||||
|
||||
include-code::./UrlHandlerFilterConfiguration[tag=config,indent=0]
|
||||
|
||||
Keep in mind the following:
|
||||
|
||||
- the root path `"/"` is excluded from trailing slash handling.
|
||||
- `@RequestMapping("/")` adds a trailing slash to a type-level mapping, and therefore will
|
||||
not map when trailing slash handling applies; use `@RequestMapping` (no path attribute) instead.
|
||||
|
||||
|
||||
[[webflux-exception-handler]]
|
||||
== Exceptions
|
||||
|
||||
@@ -269,7 +269,7 @@ The parameters to any of the above macros have consistent meanings:
|
||||
For strictly sorted maps, you can use a `SortedMap` (such as a `TreeMap`) with a
|
||||
suitable `Comparator` and, for arbitrary Maps that should return values in insertion
|
||||
order, use a `LinkedHashMap` or a `LinkedMap` from `commons-collections`.
|
||||
* `separator`: Where multiple options are available as discreet elements (radio buttons
|
||||
* `separator`: Where multiple options are available as discrete elements (radio buttons
|
||||
or checkboxes), the sequence of characters used to separate each one in the list
|
||||
(such as `<br>`).
|
||||
* `attributes`: An additional string of arbitrary tags or text to be included within
|
||||
|
||||
@@ -120,17 +120,26 @@ See the sections on xref:web/webmvc-cors.adoc[CORS] and the xref:web/webmvc-cors
|
||||
== URL Handler
|
||||
[.small]#xref:web/webflux/reactive-spring.adoc#filters.url-handler[See equivalent in the Reactive stack]#
|
||||
|
||||
In previous Spring Framework versions, Spring MVC could be configured to ignore trailing slashes in URL paths
|
||||
when mapping incoming requests on controller methods. This could be done by enabling the `setUseTrailingSlashMatch`
|
||||
option on the `PathMatchConfigurer`. This means that sending a "GET /home/" request would be handled by a controller
|
||||
method annotated with `@GetMapping("/home")`.
|
||||
You may want your controller endpoints to match routes with or without a trailing slash in the URL path.
|
||||
For example, both "GET /home" and "GET /home/" should be handled by a controller method annotated with `@GetMapping("/home")`.
|
||||
|
||||
This option has been retired, but applications are still expected to handle such requests in a safe way.
|
||||
The `UrlHandlerFilter` Servlet filter has been designed for this purpose. It can be configured to:
|
||||
Spring provides `UrlHandlerFilter` that removes the trailing slash from URL paths to ensure a consistent view of paths with or without a trailing slash.
|
||||
This is important to avoid a mismatch between URL-based authorization decisions and web framework request mappings.
|
||||
The filter can remove the trailing slash in one of a couple of ways:
|
||||
|
||||
* respond with an HTTP redirect status when receiving URLs with trailing slashes, sending browsers to the non-trailing slash URL variant.
|
||||
* wrap the request to act as if the request was sent without a trailing slash and continue the processing of the request.
|
||||
* respond with an HTTP redirect status that sends clients to the same path without a trailing slash.
|
||||
* wrap the request to remove the trailing slash.
|
||||
|
||||
NOTE: Historically Spring MVC supported trailing slash matching of URL paths.
|
||||
This capability was deprecated in 6.0 for security reasons and removed in 7.0 with
|
||||
`UrlHandlerFilter` providing a safer alternative.
|
||||
|
||||
Here is how you can instantiate and configure a `UrlHandlerFilter` for a blog application:
|
||||
|
||||
include-code::./UrlHandlerFilterConfiguration[tag=config,indent=0]
|
||||
|
||||
Keep in mind the following:
|
||||
|
||||
- the root path `"/"` is excluded from trailing slash handling.
|
||||
- `@RequestMapping("/")` adds a trailing slash to a type-level mapping, and therefore will
|
||||
not map when trailing slash handling applies; use `@RequestMapping` (no path attribute) instead.
|
||||
|
||||
@@ -32,9 +32,9 @@ any `@RequestMapping` method to render an RFC 9457 response. This is processed a
|
||||
- The `status` property of `ProblemDetail` determines the HTTP status.
|
||||
- The `instance` property of `ProblemDetail` is set from the current URL path, if not
|
||||
already set.
|
||||
- For content negotiation, the Jackson `HttpMessageConverter` prefers
|
||||
"application/problem+json" over "application/json" when rendering a `ProblemDetail`,
|
||||
and also falls back on it if no compatible media type is found.
|
||||
- The Jackson JSON and XML codecs use "application/problem+json" or
|
||||
"application/problem+xml" respectively as the producible media types for `ProblemDetail`
|
||||
to ensure they are favored for content negotiation.
|
||||
|
||||
To enable RFC 9457 responses for Spring MVC exceptions and for any
|
||||
`ErrorResponseException`, extend `ResponseEntityExceptionHandler` and declare it as an
|
||||
|
||||
@@ -19,4 +19,5 @@ example shows:
|
||||
include-code::./MyController[tag=snippet,indent=0]
|
||||
|
||||
TIP: If you need to have a `LocalValidatorFactoryBean` injected somewhere, create a bean and
|
||||
mark it with `@Primary` in order to avoid conflict with the one declared in the MVC configuration.
|
||||
mark it with `@Primary`, or mark the one declared in the MVC configuration with
|
||||
`@Fallback`, in order to avoid conflict.
|
||||
|
||||
+1
-1
@@ -188,7 +188,7 @@ the content negotiation during the error handling phase will decide which conten
|
||||
| `View`
|
||||
| A `View` instance to use for rendering together with the implicit model -- determined
|
||||
through command objects and `@ModelAttribute` methods. The handler method may also
|
||||
programmatically enrich the model by declaring a `Model` argument (descried earlier).
|
||||
programmatically enrich the model by declaring a `Model` argument (described earlier).
|
||||
|
||||
| `java.util.Map`, `org.springframework.ui.Model`
|
||||
| Attributes to be added to the implicit model with the view name implicitly determined
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
[.small]#xref:web/webflux/uri-building.adoc[See equivalent in the Reactive stack]#
|
||||
|
||||
This section describes various options available in the Spring Framework to work with URI's.
|
||||
This section describes various options available in the Spring Framework to work with URIs.
|
||||
|
||||
include::partial$web/web-uris.adoc[leveloffset=+1]
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
= UriComponents
|
||||
[.small]#Spring MVC and Spring WebFlux#
|
||||
|
||||
`UriComponentsBuilder` helps to build URI's from URI templates with variables, as the following example shows:
|
||||
`UriComponentsBuilder` helps to build URIs from URI templates with variables, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
@@ -128,7 +128,7 @@ Kotlin::
|
||||
= UriBuilder
|
||||
[.small]#Spring MVC and Spring WebFlux#
|
||||
|
||||
<<web-uricomponents, `UriComponentsBuilder`>> implements `UriBuilder`. You can create a
|
||||
<<uricomponents, `UriComponentsBuilder`>> implements `UriBuilder`. You can create a
|
||||
`UriBuilder`, in turn, with a `UriBuilderFactory`. Together, `UriBuilderFactory` and
|
||||
`UriBuilder` provide a pluggable mechanism to build URIs from URI templates, based on
|
||||
shared configuration, such as a base URL, encoding preferences, and other details.
|
||||
@@ -247,7 +247,7 @@ and treats deviations from the syntax as illegal.
|
||||
https://github.com/web-platform-tests/wpt/tree/master/url[URL parsing algorithm] in the
|
||||
https://url.spec.whatwg.org[WhatWG URL Living standard]. It provides lenient handling of
|
||||
a wide range of cases of unexpected input. Browsers implement this in order to handle
|
||||
leniently user typed URL's. For more details, see the URL Living Standard and URL parsing
|
||||
leniently user typed URLs. For more details, see the URL Living Standard and URL parsing
|
||||
https://github.com/web-platform-tests/wpt/tree/master/url[test cases].
|
||||
|
||||
By default, `RestClient`, `WebClient`, and `RestTemplate` use the RFC parser type, and
|
||||
@@ -255,10 +255,10 @@ expect applications to provide with URL templates that conform to RFC syntax. To
|
||||
that you can customize the `UriBuilderFactory` on any of the clients.
|
||||
|
||||
Applications and frameworks may further rely on `UriComponentsBuilder` for their own needs
|
||||
to parse user provided URL's in order to inspect and possibly validated URI components
|
||||
to parse user provided URLs in order to inspect and possibly validated URI components
|
||||
such as the scheme, host, port, path, and query. Such components can decide to use the
|
||||
WhatWG parser type in order to handle URL's more leniently, and to align with the way
|
||||
browsers parse URI's, in case of a redirect to the input URL or if it is included in a
|
||||
WhatWG parser type in order to handle URLs more leniently, and to align with the way
|
||||
browsers parse URIs, in case of a redirect to the input URL or if it is included in a
|
||||
response to a browser.
|
||||
|
||||
|
||||
@@ -373,14 +373,14 @@ Java::
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
String baseUrl = "https://example.com";
|
||||
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl)
|
||||
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
|
||||
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
|
||||
|
||||
// Customize the RestTemplate..
|
||||
// Customize the RestTemplate.
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
restTemplate.setUriTemplateHandler(factory);
|
||||
|
||||
// Customize the WebClient..
|
||||
// Customize the WebClient.
|
||||
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
|
||||
----
|
||||
|
||||
@@ -393,12 +393,12 @@ Kotlin::
|
||||
encodingMode = EncodingMode.TEMPLATE_AND_VALUES
|
||||
}
|
||||
|
||||
// Customize the RestTemplate..
|
||||
// Customize the RestTemplate.
|
||||
val restTemplate = RestTemplate().apply {
|
||||
uriTemplateHandler = factory
|
||||
}
|
||||
|
||||
// Customize the WebClient..
|
||||
// Customize the WebClient.
|
||||
val client = WebClient.builder().uriBuilderFactory(factory).build()
|
||||
----
|
||||
======
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"antora": "3.2.0-alpha.4",
|
||||
"@antora/atlas-extension": "1.0.0-alpha.2",
|
||||
"@antora/collector-extension": "1.0.0-alpha.3",
|
||||
"antora": "3.2.0-alpha.12",
|
||||
"@antora/atlas-extension": "1.0.0-alpha.5",
|
||||
"@antora/collector-extension": "1.0.3",
|
||||
"@asciidoctor/tabs": "1.0.0-beta.6",
|
||||
"@springio/antora-extensions": "1.14.7",
|
||||
"fast-xml-parser": "4.5.2",
|
||||
"@springio/asciidoctor-extensions": "1.0.0-alpha.10"
|
||||
"@springio/antora-extensions": "1.14.12",
|
||||
"fast-xml-parser": "5.7.0",
|
||||
"@springio/asciidoctor-extensions": "1.0.0-alpha.18"
|
||||
}
|
||||
}
|
||||
|
||||
+9
-10
@@ -200,6 +200,7 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
=======================================================================
|
||||
|
||||
SPRING FRAMEWORK ${version} SUBCOMPONENTS:
|
||||
@@ -212,7 +213,7 @@ code for these subcomponents is subject to the terms and
|
||||
conditions of the following licenses.
|
||||
|
||||
|
||||
>>> ASM 9.1 (org.ow2.asm:asm:9.1, org.ow2.asm:asm-commons:9.1):
|
||||
>>> ASM 9.9.1 (org.ow2.asm:asm:9.9.1):
|
||||
|
||||
Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
All rights reserved.
|
||||
@@ -249,10 +250,8 @@ Copyright (c) 1999-2009, OW2 Consortium <https://www.ow2.org/>
|
||||
|
||||
>>> CGLIB 3.3 (cglib:cglib:3.3):
|
||||
|
||||
Per the LICENSE file in the CGLIB JAR distribution downloaded from
|
||||
https://github.com/cglib/cglib/releases/download/RELEASE_3_3_0/cglib-3.3.0.jar,
|
||||
CGLIB 3.3 is licensed under the Apache License, version 2.0, the text of which
|
||||
is included above.
|
||||
Per the LICENSE file in the CGLIB distribution, CGLIB 3.3 is licensed
|
||||
under the Apache License, version 2.0, the text of which is included above.
|
||||
|
||||
|
||||
>>> JavaPoet 1.13.0 (com.squareup:javapoet:1.13.0):
|
||||
@@ -263,18 +262,18 @@ JavaPoet 1.13.0 is licensed under the Apache License, version 2.0, the text of
|
||||
which is included above.
|
||||
|
||||
|
||||
>>> Objenesis 3.4 (org.objenesis:objenesis:3.4):
|
||||
>>> Objenesis 3.5 (org.objenesis:objenesis:3.5):
|
||||
|
||||
Per the LICENSE file in the Objenesis ZIP distribution downloaded from
|
||||
http://objenesis.org/download.html, Objenesis 3.4 is licensed under the
|
||||
Per the LICENSE file in the Objenesis distribution downloaded from
|
||||
http://objenesis.org/download.html, Objenesis 3.5 is licensed under the
|
||||
Apache License, version 2.0, the text of which is included above.
|
||||
|
||||
Per the NOTICE file in the Objenesis ZIP distribution downloaded from
|
||||
Per the NOTICE file in the Objenesis distribution downloaded from
|
||||
http://objenesis.org/download.html and corresponding to section 4d of the
|
||||
Apache License, Version 2.0, in this case for Objenesis:
|
||||
|
||||
Objenesis
|
||||
Copyright 2006-2019 Joe Walnes, Henri Tremblay, Leonardo Mesquita
|
||||
Copyright 2006-2026 Joe Walnes, Henri Tremblay, Leonardo Mesquita
|
||||
|
||||
|
||||
===============================================================================
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2002-present 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.docs.core.expressions.languageref.expressionsoperatorsoverloaded;
|
||||
|
||||
import org.springframework.expression.Operation;
|
||||
import org.springframework.expression.OperatorOverloader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ListConcatenation implements OperatorOverloader {
|
||||
|
||||
@Override
|
||||
public boolean overridesOperation(Operation operation, Object left, Object right) {
|
||||
return (operation == Operation.ADD && left instanceof List && right instanceof List);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public Object operate(Operation operation, Object left, Object right) {
|
||||
if (operation == Operation.ADD &&
|
||||
left instanceof List list1 && right instanceof List list2) {
|
||||
|
||||
List result = new ArrayList(list1);
|
||||
result.addAll(list2);
|
||||
return result;
|
||||
}
|
||||
throw new UnsupportedOperationException(
|
||||
"No overload for operation %s and operands [%s] and [%s]"
|
||||
.formatted(operation, left, right));
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -29,7 +29,7 @@ public class ExceptionController {
|
||||
|
||||
// tag::narrow[]
|
||||
@ExceptionHandler({FileSystemException.class, RemoteException.class})
|
||||
public ResponseEntity<String> handleIoException(IOException ex) {
|
||||
public ResponseEntity<String> handleIOException(IOException ex) {
|
||||
return ResponseEntity.internalServerError().body(ex.getMessage());
|
||||
}
|
||||
// end::narrow[]
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2002-present 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.docs.core.expressions.languageref.expressionsoperatorsoverloaded
|
||||
|
||||
import org.springframework.expression.Operation
|
||||
import org.springframework.expression.OperatorOverloader
|
||||
|
||||
class ListConcatenation: OperatorOverloader {
|
||||
|
||||
override fun overridesOperation(operation: Operation, left: Any?, right: Any?): Boolean {
|
||||
return operation == Operation.ADD && left is List<*> && right is List<*>
|
||||
}
|
||||
|
||||
override fun operate(operation: Operation, left: Any?, right: Any?): Any {
|
||||
if (operation == Operation.ADD && left is List<*> && right is List<*>) {
|
||||
return left + right
|
||||
}
|
||||
|
||||
throw UnsupportedOperationException(
|
||||
"No overload for operation $operation and operands [$left] and [$right]")
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -27,7 +27,7 @@ class ExceptionController {
|
||||
|
||||
// tag::narrow[]
|
||||
@ExceptionHandler(FileSystemException::class, RemoteException::class)
|
||||
fun handleIoException(ex: IOException): ResponseEntity<String> {
|
||||
fun handleIOException(ex: IOException): ResponseEntity<String> {
|
||||
return ResponseEntity.internalServerError().body(ex.message)
|
||||
}
|
||||
// end::narrow[]
|
||||
|
||||
@@ -8,20 +8,20 @@ javaPlatform {
|
||||
|
||||
dependencies {
|
||||
api(platform("com.fasterxml.jackson:jackson-bom:2.18.5"))
|
||||
api(platform("io.micrometer:micrometer-bom:1.14.14"))
|
||||
api(platform("io.netty:netty-bom:4.1.128.Final"))
|
||||
api(platform("io.micrometer:micrometer-bom:1.15.12"))
|
||||
api(platform("io.netty:netty-bom:4.1.134.Final"))
|
||||
api(platform("io.netty:netty5-bom:5.0.0.Alpha5"))
|
||||
api(platform("io.projectreactor:reactor-bom:2024.0.13"))
|
||||
api(platform("io.projectreactor:reactor-bom:2024.0.18"))
|
||||
api(platform("io.rsocket:rsocket-bom:1.1.5"))
|
||||
api(platform("org.apache.groovy:groovy-bom:4.0.29"))
|
||||
api(platform("org.apache.groovy:groovy-bom:4.0.31"))
|
||||
api(platform("org.apache.logging.log4j:log4j-bom:2.21.1"))
|
||||
api(platform("org.assertj:assertj-bom:3.27.6"))
|
||||
api(platform("org.eclipse.jetty:jetty-bom:12.0.30"))
|
||||
api(platform("org.eclipse.jetty.ee10:jetty-ee10-bom:12.0.30"))
|
||||
api(platform("org.assertj:assertj-bom:3.27.7"))
|
||||
api(platform("org.eclipse.jetty:jetty-bom:12.0.33"))
|
||||
api(platform("org.eclipse.jetty.ee10:jetty-ee10-bom:12.0.33"))
|
||||
api(platform("org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.8.1"))
|
||||
api(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:1.6.3"))
|
||||
api(platform("org.junit:junit-bom:5.14.1"))
|
||||
api(platform("org.mockito:mockito-bom:5.20.0"))
|
||||
api(platform("org.junit:junit-bom:5.14.4"))
|
||||
api(platform("org.mockito:mockito-bom:5.23.0"))
|
||||
|
||||
constraints {
|
||||
api("com.fasterxml:aalto-xml:1.3.4")
|
||||
@@ -31,8 +31,8 @@ dependencies {
|
||||
api("com.google.code.findbugs:findbugs:3.0.1")
|
||||
api("com.google.code.findbugs:jsr305:3.0.2")
|
||||
api("com.google.code.gson:gson:2.13.2")
|
||||
api("com.google.protobuf:protobuf-java-util:4.32.1")
|
||||
api("com.h2database:h2:2.3.232")
|
||||
api("com.google.protobuf:protobuf-java-util:4.34.1")
|
||||
api("com.h2database:h2:2.4.240")
|
||||
api("com.jayway.jsonpath:json-path:2.10.0")
|
||||
api("com.oracle.database.jdbc:ojdbc11:21.9.0.0")
|
||||
api("com.rometools:rome:1.19.0")
|
||||
@@ -50,7 +50,7 @@ dependencies {
|
||||
api("io.mockk:mockk:1.13.17")
|
||||
api("io.projectreactor.netty:reactor-netty5-http:2.0.0-M3")
|
||||
api("io.projectreactor.tools:blockhound:1.0.8.RELEASE")
|
||||
api("io.r2dbc:r2dbc-h2:1.0.0.RELEASE")
|
||||
api("io.r2dbc:r2dbc-h2:1.1.0.RELEASE")
|
||||
api("io.r2dbc:r2dbc-spi-test:1.0.0.RELEASE")
|
||||
api("io.r2dbc:r2dbc-spi:1.0.0.RELEASE")
|
||||
api("io.reactivex.rxjava3:rxjava:3.1.12")
|
||||
@@ -90,11 +90,11 @@ dependencies {
|
||||
api("junit:junit:4.13.2")
|
||||
api("net.sf.jopt-simple:jopt-simple:5.0.4")
|
||||
api("org.apache-extras.beanshell:bsh:2.0b6")
|
||||
api("org.apache.activemq:activemq-broker:5.17.7")
|
||||
api("org.apache.activemq:activemq-kahadb-store:5.17.7")
|
||||
api("org.apache.activemq:activemq-stomp:5.17.7")
|
||||
api("org.apache.activemq:artemis-jakarta-client:2.42.0")
|
||||
api("org.apache.activemq:artemis-junit-5:2.42.0")
|
||||
api("org.apache.activemq:activemq-broker:5.17.7")
|
||||
api("org.apache.activemq:activemq-kahadb-store:5.17.7")
|
||||
api("org.apache.activemq:activemq-stomp:5.17.7")
|
||||
api("org.apache.activemq:artemis-jakarta-client:2.42.0")
|
||||
api("org.apache.activemq:artemis-junit-5:2.42.0")
|
||||
api("org.apache.commons:commons-pool2:2.9.0")
|
||||
api("org.apache.derby:derby:10.16.1.1")
|
||||
api("org.apache.derby:derbyclient:10.16.1.1")
|
||||
@@ -129,7 +129,7 @@ dependencies {
|
||||
api("org.hibernate:hibernate-core-jakarta:5.6.15.Final")
|
||||
api("org.hibernate:hibernate-validator:7.0.5.Final")
|
||||
api("org.hsqldb:hsqldb:2.7.4")
|
||||
api("org.htmlunit:htmlunit:4.18.0")
|
||||
api("org.htmlunit:htmlunit:4.21.0")
|
||||
api("org.javamoney:moneta:1.4.4")
|
||||
api("org.jruby:jruby:9.4.13.0")
|
||||
api("org.junit.support:testng-engine:1.0.5")
|
||||
@@ -137,8 +137,8 @@ dependencies {
|
||||
api("org.ogce:xpp3:1.1.6")
|
||||
api("org.python:jython-standalone:2.7.4")
|
||||
api("org.quartz-scheduler:quartz:2.3.2")
|
||||
api("org.seleniumhq.selenium:htmlunit3-driver:4.38.0")
|
||||
api("org.seleniumhq.selenium:selenium-java:4.38.0")
|
||||
api("org.seleniumhq.selenium:htmlunit3-driver:4.41.0")
|
||||
api("org.seleniumhq.selenium:selenium-java:4.41.0")
|
||||
api("org.skyscreamer:jsonassert:1.5.3")
|
||||
api("org.slf4j:slf4j-api:2.0.17")
|
||||
api("org.testng:testng:7.11.0")
|
||||
@@ -147,6 +147,6 @@ dependencies {
|
||||
api("org.webjars:webjars-locator-lite:1.1.0")
|
||||
api("org.xmlunit:xmlunit-assertj:2.10.4")
|
||||
api("org.xmlunit:xmlunit-matchers:2.10.4")
|
||||
api("org.yaml:snakeyaml:2.5")
|
||||
api("org.yaml:snakeyaml:2.6")
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
version=6.2.15-SNAPSHOT
|
||||
version=6.2.20-SNAPSHOT
|
||||
|
||||
org.gradle.caching=true
|
||||
org.gradle.jvmargs=-Xmx2048m
|
||||
|
||||
@@ -84,19 +84,6 @@ eclipse.classpath.file.whenMerged {
|
||||
}
|
||||
}
|
||||
|
||||
// Due to an apparent bug in Gradle, even though we exclude the "main" classpath
|
||||
// entries for sources generated by XJC in spring-oxm.gradle, the Gradle eclipse
|
||||
// plugin still includes them in the generated .classpath file. So, we have to
|
||||
// manually remove those lingering "main" entries.
|
||||
if (project.name == "spring-oxm") {
|
||||
eclipse.classpath.file.whenMerged { classpath ->
|
||||
classpath.entries.removeAll {
|
||||
it.path =~ /build\/generated\/sources\/xjc\/.+/ &&
|
||||
it.entryAttributes.get("gradle_scope") == "main"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Include project specific settings
|
||||
tasks.register('eclipseSettings', Copy) {
|
||||
from rootProject.files(
|
||||
|
||||
+8
-13
@@ -61,10 +61,9 @@ class AopNamespaceHandlerScopeIntegrationTests {
|
||||
|
||||
|
||||
@Test
|
||||
void testSingletonScoping() throws Exception {
|
||||
void singletonScoping() throws Exception {
|
||||
assertThat(AopUtils.isAopProxy(singletonScoped)).as("Should be AOP proxy").isTrue();
|
||||
boolean condition = singletonScoped instanceof TestBean;
|
||||
assertThat(condition).as("Should be target class proxy").isTrue();
|
||||
assertThat(singletonScoped).as("Should be target class proxy").isInstanceOf(TestBean.class);
|
||||
String rob = "Rob Harrop";
|
||||
String bram = "Bram Smeets";
|
||||
assertThat(singletonScoped.getName()).isEqualTo(rob);
|
||||
@@ -75,19 +74,17 @@ class AopNamespaceHandlerScopeIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRequestScoping() {
|
||||
void requestScoping() {
|
||||
MockHttpServletRequest oldRequest = new MockHttpServletRequest();
|
||||
MockHttpServletRequest newRequest = new MockHttpServletRequest();
|
||||
|
||||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(oldRequest));
|
||||
|
||||
assertThat(AopUtils.isAopProxy(requestScoped)).as("Should be AOP proxy").isTrue();
|
||||
boolean condition = requestScoped instanceof TestBean;
|
||||
assertThat(condition).as("Should be target class proxy").isTrue();
|
||||
assertThat(requestScoped).as("Should be target class proxy").isInstanceOf(TestBean.class);
|
||||
|
||||
assertThat(AopUtils.isAopProxy(testBean)).as("Should be AOP proxy").isTrue();
|
||||
boolean condition1 = testBean instanceof TestBean;
|
||||
assertThat(condition1).as("Regular bean should be JDK proxy").isFalse();
|
||||
assertThat(testBean).as("Regular bean should be JDK proxy").isNotInstanceOf(TestBean.class);
|
||||
|
||||
String rob = "Rob Harrop";
|
||||
String bram = "Bram Smeets";
|
||||
@@ -103,7 +100,7 @@ class AopNamespaceHandlerScopeIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSessionScoping() {
|
||||
void sessionScoping() {
|
||||
MockHttpSession oldSession = new MockHttpSession();
|
||||
MockHttpSession newSession = new MockHttpSession();
|
||||
|
||||
@@ -112,14 +109,12 @@ class AopNamespaceHandlerScopeIntegrationTests {
|
||||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
|
||||
|
||||
assertThat(AopUtils.isAopProxy(sessionScoped)).as("Should be AOP proxy").isTrue();
|
||||
boolean condition1 = sessionScoped instanceof TestBean;
|
||||
assertThat(condition1).as("Should not be target class proxy").isFalse();
|
||||
assertThat(sessionScoped).as("Should not be target class proxy").isNotInstanceOf(TestBean.class);
|
||||
|
||||
assertThat(sessionScopedAlias).isSameAs(sessionScoped);
|
||||
|
||||
assertThat(AopUtils.isAopProxy(testBean)).as("Should be AOP proxy").isTrue();
|
||||
boolean condition = testBean instanceof TestBean;
|
||||
assertThat(condition).as("Regular bean should be JDK proxy").isFalse();
|
||||
assertThat(testBean).as("Regular bean should be JDK proxy").isNotInstanceOf(TestBean.class);
|
||||
|
||||
String rob = "Rob Harrop";
|
||||
String bram = "Bram Smeets";
|
||||
|
||||
+9
-10
@@ -65,7 +65,7 @@ class AdvisorAutoProxyCreatorIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultExclusionPrefix() {
|
||||
void defaultExclusionPrefix() {
|
||||
DefaultAdvisorAutoProxyCreator aapc = (DefaultAdvisorAutoProxyCreator) getBeanFactory().getBean(ADVISOR_APC_BEAN_NAME);
|
||||
assertThat(aapc.getAdvisorBeanNamePrefix()).isEqualTo((ADVISOR_APC_BEAN_NAME + DefaultAdvisorAutoProxyCreator.SEPARATOR));
|
||||
assertThat(aapc.isUsePrefix()).isFalse();
|
||||
@@ -75,21 +75,21 @@ class AdvisorAutoProxyCreatorIntegrationTests {
|
||||
* If no pointcuts match (no attrs) there should be proxying.
|
||||
*/
|
||||
@Test
|
||||
void testNoProxy() {
|
||||
void noProxy() {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
Object o = bf.getBean("noSetters");
|
||||
assertThat(AopUtils.isAopProxy(o)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTxIsProxied() {
|
||||
void txIsProxied() {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
ITestBean test = (ITestBean) bf.getBean("test");
|
||||
assertThat(AopUtils.isAopProxy(test)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRegexpApplied() {
|
||||
void regexpApplied() {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
ITestBean test = (ITestBean) bf.getBean("test");
|
||||
MethodCounter counter = (MethodCounter) bf.getBean("countingAdvice");
|
||||
@@ -99,7 +99,7 @@ class AdvisorAutoProxyCreatorIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransactionAttributeOnMethod() {
|
||||
void transactionAttributeOnMethod() {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
ITestBean test = (ITestBean) bf.getBean("test");
|
||||
|
||||
@@ -121,7 +121,7 @@ class AdvisorAutoProxyCreatorIntegrationTests {
|
||||
* Should not roll back on servlet exception.
|
||||
*/
|
||||
@Test
|
||||
void testRollbackRulesOnMethodCauseRollback() throws Exception {
|
||||
void rollbackRulesOnMethodCauseRollback() throws Exception {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
Rollback rb = (Rollback) bf.getBean("rollback");
|
||||
|
||||
@@ -147,7 +147,7 @@ class AdvisorAutoProxyCreatorIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRollbackRulesOnMethodPreventRollback() throws Exception {
|
||||
void rollbackRulesOnMethodPreventRollback() throws Exception {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
Rollback rb = (Rollback) bf.getBean("rollback");
|
||||
|
||||
@@ -165,12 +165,11 @@ class AdvisorAutoProxyCreatorIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testProgrammaticRollback() {
|
||||
void programmaticRollback() {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
|
||||
Object bean = bf.getBean(TXMANAGER_BEAN_NAME);
|
||||
boolean condition = bean instanceof CallCountingTransactionManager;
|
||||
assertThat(condition).isTrue();
|
||||
assertThat(bean).isInstanceOf(CallCountingTransactionManager.class);
|
||||
CallCountingTransactionManager txMan = (CallCountingTransactionManager) bf.getBean(TXMANAGER_BEAN_NAME);
|
||||
|
||||
Rollback rb = (Rollback) bf.getBean("rollback");
|
||||
|
||||
+3
-3
@@ -50,13 +50,13 @@ class ComponentBeanDefinitionParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBionicBasic() {
|
||||
void bionicBasic() {
|
||||
Component cp = getBionicFamily();
|
||||
assertThat(cp.getName()).isEqualTo("Bionic-1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBionicFirstLevelChildren() {
|
||||
void bionicFirstLevelChildren() {
|
||||
Component cp = getBionicFamily();
|
||||
List<Component> components = cp.getComponents();
|
||||
assertThat(components).hasSize(2);
|
||||
@@ -65,7 +65,7 @@ class ComponentBeanDefinitionParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBionicSecondLevelChildren() {
|
||||
void bionicSecondLevelChildren() {
|
||||
Component cp = getBionicFamily();
|
||||
List<Component> components = cp.getComponents().get(0).getComponents();
|
||||
assertThat(components).hasSize(2);
|
||||
|
||||
+15
-20
@@ -83,7 +83,7 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
|
||||
|
||||
@Test
|
||||
void testPrototype() {
|
||||
void prototype() {
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("prototype");
|
||||
assertThat(bean).isNotNull();
|
||||
@@ -92,7 +92,7 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSingletonScopeWithNoProxy() {
|
||||
void singletonScopeWithNoProxy() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("singleton");
|
||||
@@ -115,7 +115,7 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSingletonScopeIgnoresProxyInterfaces() {
|
||||
void singletonScopeIgnoresProxyInterfaces() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.INTERFACES);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("singleton");
|
||||
@@ -136,7 +136,7 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSingletonScopeIgnoresProxyTargetClass() {
|
||||
void singletonScopeIgnoresProxyTargetClass() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.TARGET_CLASS);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("singleton");
|
||||
@@ -157,7 +157,7 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRequestScopeWithNoProxy() {
|
||||
void requestScopeWithNoProxy() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("request");
|
||||
@@ -178,15 +178,14 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRequestScopeWithProxiedInterfaces() {
|
||||
void requestScopeWithProxiedInterfaces() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.INTERFACES);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("request");
|
||||
|
||||
// should be dynamic proxy, implementing both interfaces
|
||||
assertThat(AopUtils.isJdkDynamicProxy(bean)).isTrue();
|
||||
boolean condition = bean instanceof AnotherScopeTestInterface;
|
||||
assertThat(condition).isTrue();
|
||||
assertThat(bean).isInstanceOf(AnotherScopeTestInterface.class);
|
||||
|
||||
assertThat(bean.getName()).isEqualTo(DEFAULT_NAME);
|
||||
bean.setName(MODIFIED_NAME);
|
||||
@@ -200,15 +199,14 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRequestScopeWithProxiedTargetClass() {
|
||||
void requestScopeWithProxiedTargetClass() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.TARGET_CLASS);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("request");
|
||||
|
||||
// should be a class-based proxy
|
||||
assertThat(AopUtils.isCglibProxy(bean)).isTrue();
|
||||
boolean condition = bean instanceof RequestScopedTestBean;
|
||||
assertThat(condition).isTrue();
|
||||
assertThat(bean).isInstanceOf(RequestScopedTestBean.class);
|
||||
|
||||
assertThat(bean.getName()).isEqualTo(DEFAULT_NAME);
|
||||
bean.setName(MODIFIED_NAME);
|
||||
@@ -222,7 +220,7 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSessionScopeWithNoProxy() {
|
||||
void sessionScopeWithNoProxy() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("session");
|
||||
@@ -243,15 +241,14 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSessionScopeWithProxiedInterfaces() {
|
||||
void sessionScopeWithProxiedInterfaces() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.INTERFACES);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("session");
|
||||
|
||||
// should be dynamic proxy, implementing both interfaces
|
||||
assertThat(AopUtils.isJdkDynamicProxy(bean)).isTrue();
|
||||
boolean condition = bean instanceof AnotherScopeTestInterface;
|
||||
assertThat(condition).isTrue();
|
||||
assertThat(bean).isInstanceOf(AnotherScopeTestInterface.class);
|
||||
|
||||
assertThat(bean.getName()).isEqualTo(DEFAULT_NAME);
|
||||
bean.setName(MODIFIED_NAME);
|
||||
@@ -271,17 +268,15 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSessionScopeWithProxiedTargetClass() {
|
||||
void sessionScopeWithProxiedTargetClass() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.TARGET_CLASS);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("session");
|
||||
|
||||
// should be a class-based proxy
|
||||
assertThat(AopUtils.isCglibProxy(bean)).isTrue();
|
||||
boolean condition1 = bean instanceof ScopedTestBean;
|
||||
assertThat(condition1).isTrue();
|
||||
boolean condition = bean instanceof SessionScopedTestBean;
|
||||
assertThat(condition).isTrue();
|
||||
assertThat(bean).isInstanceOf(ScopedTestBean.class);
|
||||
assertThat(bean).isInstanceOf(SessionScopedTestBean.class);
|
||||
|
||||
assertThat(bean.getName()).isEqualTo(DEFAULT_NAME);
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
+5
-10
@@ -166,8 +166,7 @@ class ClassPathBeanDefinitionScannerScopeIntegrationTests {
|
||||
|
||||
// should be dynamic proxy, implementing both interfaces
|
||||
assertThat(AopUtils.isJdkDynamicProxy(bean)).isTrue();
|
||||
boolean condition = bean instanceof AnotherScopeTestInterface;
|
||||
assertThat(condition).isTrue();
|
||||
assertThat(bean).isInstanceOf(AnotherScopeTestInterface.class);
|
||||
|
||||
assertThat(bean.getName()).isEqualTo(DEFAULT_NAME);
|
||||
bean.setName(MODIFIED_NAME);
|
||||
@@ -188,8 +187,7 @@ class ClassPathBeanDefinitionScannerScopeIntegrationTests {
|
||||
|
||||
// should be a class-based proxy
|
||||
assertThat(AopUtils.isCglibProxy(bean)).isTrue();
|
||||
boolean condition = bean instanceof RequestScopedTestBean;
|
||||
assertThat(condition).isTrue();
|
||||
assertThat(bean).isInstanceOf(RequestScopedTestBean.class);
|
||||
|
||||
assertThat(bean.getName()).isEqualTo(DEFAULT_NAME);
|
||||
bean.setName(MODIFIED_NAME);
|
||||
@@ -231,8 +229,7 @@ class ClassPathBeanDefinitionScannerScopeIntegrationTests {
|
||||
|
||||
// should be dynamic proxy, implementing both interfaces
|
||||
assertThat(AopUtils.isJdkDynamicProxy(bean)).isTrue();
|
||||
boolean condition = bean instanceof AnotherScopeTestInterface;
|
||||
assertThat(condition).isTrue();
|
||||
assertThat(bean).isInstanceOf(AnotherScopeTestInterface.class);
|
||||
|
||||
assertThat(bean.getName()).isEqualTo(DEFAULT_NAME);
|
||||
bean.setName(MODIFIED_NAME);
|
||||
@@ -259,10 +256,8 @@ class ClassPathBeanDefinitionScannerScopeIntegrationTests {
|
||||
|
||||
// should be a class-based proxy
|
||||
assertThat(AopUtils.isCglibProxy(bean)).isTrue();
|
||||
boolean condition1 = bean instanceof ScopedTestBean;
|
||||
assertThat(condition1).isTrue();
|
||||
boolean condition = bean instanceof SessionScopedTestBean;
|
||||
assertThat(condition).isTrue();
|
||||
assertThat(bean).isInstanceOf(ScopedTestBean.class);
|
||||
assertThat(bean).isInstanceOf(SessionScopedTestBean.class);
|
||||
|
||||
assertThat(bean.getName()).isEqualTo(DEFAULT_NAME);
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2002-present 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.core.env;
|
||||
|
||||
/**
|
||||
* Constants used both locally and in scan* sub-packages
|
||||
*/
|
||||
public class Constants {
|
||||
|
||||
public static final String XML_PATH = "org/springframework/core/env/EnvironmentSystemIntegrationTests-context.xml";
|
||||
|
||||
public static final String ENVIRONMENT_AWARE_BEAN_NAME = "envAwareBean";
|
||||
|
||||
public static final String PROD_BEAN_NAME = "prodBean";
|
||||
public static final String DEV_BEAN_NAME = "devBean";
|
||||
public static final String DERIVED_DEV_BEAN_NAME = "derivedDevBean";
|
||||
public static final String TRANSITIVE_BEAN_NAME = "transitiveBean";
|
||||
|
||||
public static final String PROD_ENV_NAME = "prod";
|
||||
public static final String DEV_ENV_NAME = "dev";
|
||||
public static final String DERIVED_DEV_ENV_NAME = "derivedDev";
|
||||
}
|
||||
Vendored
+11
-31
@@ -58,15 +58,15 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
|
||||
import static org.springframework.context.ConfigurableApplicationContext.ENVIRONMENT_BEAN_NAME;
|
||||
import static org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.DERIVED_DEV_BEAN_NAME;
|
||||
import static org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.DERIVED_DEV_ENV_NAME;
|
||||
import static org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.DEV_BEAN_NAME;
|
||||
import static org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.DEV_ENV_NAME;
|
||||
import static org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.ENVIRONMENT_AWARE_BEAN_NAME;
|
||||
import static org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.PROD_BEAN_NAME;
|
||||
import static org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.PROD_ENV_NAME;
|
||||
import static org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.TRANSITIVE_BEAN_NAME;
|
||||
import static org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.XML_PATH;
|
||||
import static org.springframework.core.env.Constants.DERIVED_DEV_BEAN_NAME;
|
||||
import static org.springframework.core.env.Constants.DERIVED_DEV_ENV_NAME;
|
||||
import static org.springframework.core.env.Constants.DEV_BEAN_NAME;
|
||||
import static org.springframework.core.env.Constants.DEV_ENV_NAME;
|
||||
import static org.springframework.core.env.Constants.ENVIRONMENT_AWARE_BEAN_NAME;
|
||||
import static org.springframework.core.env.Constants.PROD_BEAN_NAME;
|
||||
import static org.springframework.core.env.Constants.PROD_ENV_NAME;
|
||||
import static org.springframework.core.env.Constants.TRANSITIVE_BEAN_NAME;
|
||||
import static org.springframework.core.env.Constants.XML_PATH;
|
||||
|
||||
/**
|
||||
* System integration tests for container support of the {@link Environment} API.
|
||||
@@ -87,7 +87,7 @@ import static org.springframework.core.env.EnvironmentSystemIntegrationTests.Con
|
||||
* @author Sam Brannen
|
||||
* @see org.springframework.context.support.EnvironmentIntegrationTests
|
||||
*/
|
||||
public class EnvironmentSystemIntegrationTests {
|
||||
class EnvironmentSystemIntegrationTests {
|
||||
|
||||
private final ConfigurableEnvironment prodEnv = new StandardEnvironment();
|
||||
|
||||
@@ -648,7 +648,7 @@ public class EnvironmentSystemIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Profile(DERIVED_DEV_ENV_NAME)
|
||||
@Profile(Constants.DERIVED_DEV_ENV_NAME)
|
||||
@Configuration
|
||||
static class DerivedDevConfig extends DevConfig {
|
||||
@Bean
|
||||
@@ -666,24 +666,4 @@ public class EnvironmentSystemIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constants used both locally and in scan* sub-packages
|
||||
*/
|
||||
public static class Constants {
|
||||
|
||||
public static final String XML_PATH = "org/springframework/core/env/EnvironmentSystemIntegrationTests-context.xml";
|
||||
|
||||
public static final String ENVIRONMENT_AWARE_BEAN_NAME = "envAwareBean";
|
||||
|
||||
public static final String PROD_BEAN_NAME = "prodBean";
|
||||
public static final String DEV_BEAN_NAME = "devBean";
|
||||
public static final String DERIVED_DEV_BEAN_NAME = "derivedDevBean";
|
||||
public static final String TRANSITIVE_BEAN_NAME = "transitiveBean";
|
||||
|
||||
public static final String PROD_ENV_NAME = "prod";
|
||||
public static final String DEV_ENV_NAME = "dev";
|
||||
public static final String DERIVED_DEV_ENV_NAME = "derivedDev";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
|
||||
@Profile(org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.DEV_ENV_NAME)
|
||||
@Profile(org.springframework.core.env.Constants.DEV_ENV_NAME)
|
||||
@Configuration
|
||||
class DevConfig {
|
||||
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
|
||||
@Profile(org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.PROD_ENV_NAME)
|
||||
@Profile(org.springframework.core.env.Constants.PROD_ENV_NAME)
|
||||
@Configuration
|
||||
class ProdConfig {
|
||||
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ package org.springframework.core.env.scan2;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Profile(org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.DEV_ENV_NAME)
|
||||
@Component(org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.DEV_BEAN_NAME)
|
||||
@Profile(org.springframework.core.env.Constants.DEV_ENV_NAME)
|
||||
@Component(org.springframework.core.env.Constants.DEV_BEAN_NAME)
|
||||
class DevBean {
|
||||
}
|
||||
|
||||
+2
-2
@@ -19,8 +19,8 @@ package org.springframework.core.env.scan2;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Profile(org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.PROD_ENV_NAME)
|
||||
@Component(org.springframework.core.env.EnvironmentSystemIntegrationTests.Constants.PROD_BEAN_NAME)
|
||||
@Profile(org.springframework.core.env.Constants.PROD_ENV_NAME)
|
||||
@Component(org.springframework.core.env.Constants.PROD_BEAN_NAME)
|
||||
class ProdBean {
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -171,7 +171,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "execution(" + getSignature().toString() + ")";
|
||||
return "execution(" + getSignature() + ")";
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
|
||||
/**
|
||||
* Add the supplied aspect instance to the chain. The type of the aspect instance
|
||||
* supplied must be a singleton aspect. True singleton lifecycle is not honoured when
|
||||
* supplied must be a singleton aspect. True singleton lifecycle is not honored when
|
||||
* using this method - the caller is responsible for managing the lifecycle of any
|
||||
* aspects added in this way.
|
||||
* @param aspectInstance the AspectJ aspect instance
|
||||
|
||||
+2
-2
@@ -120,7 +120,7 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
|
||||
/**
|
||||
* The pointcut for Spring AOP to use.
|
||||
* Actual behaviour of the pointcut will change depending on the state of the advice.
|
||||
* Actual behavior of the pointcut will change depending on the state of the advice.
|
||||
*/
|
||||
@Override
|
||||
public Pointcut getPointcut() {
|
||||
@@ -261,7 +261,7 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
|
||||
|
||||
/**
|
||||
* Pointcut implementation that changes its behaviour when the advice is instantiated.
|
||||
* Pointcut implementation that changes its behavior when the advice is instantiated.
|
||||
* Note that this is a <i>dynamic</i> pointcut; otherwise it might be optimized out
|
||||
* if it does not at first match statically.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ public class DelegatePerTargetObjectIntroductionInterceptor extends Introduction
|
||||
|
||||
/**
|
||||
* Subclasses may need to override this if they want to perform custom
|
||||
* behaviour in around advice. However, subclasses should invoke this
|
||||
* behavior in around advice. However, subclasses should invoke this
|
||||
* method, which handles introduced interfaces and forwarding to the target.
|
||||
*/
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -98,7 +98,7 @@ public class DelegatingIntroductionInterceptor extends IntroductionInfoSupport
|
||||
|
||||
/**
|
||||
* Subclasses may need to override this if they want to perform custom
|
||||
* behaviour in around advice. However, subclasses should invoke this
|
||||
* behavior in around advice. However, subclasses should invoke this
|
||||
* method, which handles introduced interfaces and forwarding to the target.
|
||||
*/
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ import org.springframework.aop.Pointcut;
|
||||
* Convenient superclass when we want to force subclasses to
|
||||
* implement MethodMatcher interface, but subclasses
|
||||
* will want to be pointcuts. The getClassFilter() method can
|
||||
* be overridden to customize ClassFilter behaviour as well.
|
||||
* be overridden to customize ClassFilter behavior as well.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
|
||||
+36
-44
@@ -23,7 +23,6 @@ import java.util.Map;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import test.annotation.EmptySpringAnnotation;
|
||||
import test.annotation.transaction.Tx;
|
||||
@@ -37,6 +36,7 @@ import org.springframework.beans.testfixture.beans.IOther;
|
||||
import org.springframework.beans.testfixture.beans.ITestBean;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.beans.testfixture.beans.subpkg.DeepBean;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
@@ -50,30 +50,22 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
*/
|
||||
class AspectJExpressionPointcutTests {
|
||||
|
||||
private Method getAge;
|
||||
|
||||
private Method setAge;
|
||||
|
||||
private Method setSomeNumber;
|
||||
|
||||
private final Method getAge = ClassUtils.getMethod(TestBean.class, "getAge");
|
||||
private final Method setAge = ClassUtils.getMethod(TestBean.class, "setAge", int.class);
|
||||
private final Method setSomeNumber = ClassUtils.getMethod(TestBean.class, "setSomeNumber", Number.class);
|
||||
private final Map<String, Method> methodsOnHasGeneric = new HashMap<>();
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void setup() throws NoSuchMethodException {
|
||||
getAge = TestBean.class.getMethod("getAge");
|
||||
setAge = TestBean.class.getMethod("setAge", int.class);
|
||||
setSomeNumber = TestBean.class.getMethod("setSomeNumber", Number.class);
|
||||
|
||||
AspectJExpressionPointcutTests() throws NoSuchMethodException {
|
||||
// Assumes no overloading
|
||||
for (Method method : HasGeneric.class.getMethods()) {
|
||||
methodsOnHasGeneric.put(method.getName(), method);
|
||||
this.methodsOnHasGeneric.put(method.getName(), method);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testMatchExplicit() {
|
||||
void matchExplicit() {
|
||||
String expression = "execution(int org.springframework.beans.testfixture.beans.TestBean.getAge())";
|
||||
|
||||
Pointcut pointcut = getPointcut(expression);
|
||||
@@ -91,7 +83,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMatchWithTypePattern() {
|
||||
void matchWithTypePattern() {
|
||||
String expression = "execution(* *..TestBean.*Age(..))";
|
||||
|
||||
Pointcut pointcut = getPointcut(expression);
|
||||
@@ -110,12 +102,12 @@ class AspectJExpressionPointcutTests {
|
||||
|
||||
|
||||
@Test
|
||||
void testThis() throws SecurityException, NoSuchMethodException{
|
||||
void thisCase() throws SecurityException, NoSuchMethodException{
|
||||
testThisOrTarget("this");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTarget() throws SecurityException, NoSuchMethodException {
|
||||
void target() throws SecurityException, NoSuchMethodException {
|
||||
testThisOrTarget("target");
|
||||
}
|
||||
|
||||
@@ -139,12 +131,12 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithinRootPackage() throws SecurityException, NoSuchMethodException {
|
||||
void withinRootPackage() throws SecurityException, NoSuchMethodException {
|
||||
testWithinPackage(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithinRootAndSubpackages() throws SecurityException, NoSuchMethodException {
|
||||
void withinRootAndSubpackages() throws SecurityException, NoSuchMethodException {
|
||||
testWithinPackage(true);
|
||||
}
|
||||
|
||||
@@ -168,7 +160,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFriendlyErrorOnNoLocationClassMatching() {
|
||||
void friendlyErrorOnNoLocationClassMatching() {
|
||||
AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> pc.getClassFilter().matches(ITestBean.class))
|
||||
@@ -176,7 +168,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFriendlyErrorOnNoLocation2ArgMatching() {
|
||||
void friendlyErrorOnNoLocation2ArgMatching() {
|
||||
AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> pc.getMethodMatcher().matches(getAge, ITestBean.class))
|
||||
@@ -184,7 +176,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFriendlyErrorOnNoLocation3ArgMatching() {
|
||||
void friendlyErrorOnNoLocation3ArgMatching() {
|
||||
AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> pc.getMethodMatcher().matches(getAge, ITestBean.class, (Object[]) null))
|
||||
@@ -193,7 +185,7 @@ class AspectJExpressionPointcutTests {
|
||||
|
||||
|
||||
@Test
|
||||
void testMatchWithArgs() {
|
||||
void matchWithArgs() {
|
||||
String expression = "execution(void org.springframework.beans.testfixture.beans.TestBean.setSomeNumber(Number)) && args(Double)";
|
||||
|
||||
Pointcut pointcut = getPointcut(expression);
|
||||
@@ -214,7 +206,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSimpleAdvice() {
|
||||
void simpleAdvice() {
|
||||
String expression = "execution(int org.springframework.beans.testfixture.beans.TestBean.getAge())";
|
||||
CallCountingInterceptor interceptor = new CallCountingInterceptor();
|
||||
TestBean testBean = getAdvisedProxy(expression, interceptor);
|
||||
@@ -227,7 +219,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDynamicMatchingProxy() {
|
||||
void dynamicMatchingProxy() {
|
||||
String expression = "execution(void org.springframework.beans.testfixture.beans.TestBean.setSomeNumber(Number)) && args(Double)";
|
||||
CallCountingInterceptor interceptor = new CallCountingInterceptor();
|
||||
TestBean testBean = getAdvisedProxy(expression, interceptor);
|
||||
@@ -241,7 +233,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidExpression() {
|
||||
void invalidExpression() {
|
||||
String expression = "execution(void org.springframework.beans.testfixture.beans.TestBean.setSomeNumber(Number) && args(Double)";
|
||||
assertThat(getPointcut(expression).getClassFilter().matches(Object.class)).isFalse();
|
||||
}
|
||||
@@ -271,20 +263,20 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithUnsupportedPointcutPrimitive() {
|
||||
void withUnsupportedPointcutPrimitive() {
|
||||
String expression = "call(int org.springframework.beans.testfixture.beans.TestBean.getAge())";
|
||||
assertThat(getPointcut(expression).getClassFilter().matches(Object.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAndSubstitution() {
|
||||
void andSubstitution() {
|
||||
AspectJExpressionPointcut pc = getPointcut("execution(* *(..)) and args(String)");
|
||||
String expr = pc.getPointcutExpression().getPointcutExpression();
|
||||
assertThat(expr).isEqualTo("execution(* *(..)) && args(String)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultipleAndSubstitutions() {
|
||||
void multipleAndSubstitutions() {
|
||||
AspectJExpressionPointcut pc = getPointcut("execution(* *(..)) and args(String) and this(Object)");
|
||||
String expr = pc.getPointcutExpression().getPointcutExpression();
|
||||
assertThat(expr).isEqualTo("execution(* *(..)) && args(String) && this(Object)");
|
||||
@@ -297,7 +289,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMatchGenericArgument() {
|
||||
void matchGenericArgument() {
|
||||
String expression = "execution(* set*(java.util.List<org.springframework.beans.testfixture.beans.TestBean>) )";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
@@ -316,7 +308,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMatchVarargs() throws Exception {
|
||||
void matchVarargs() throws Exception {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
class MyTemplate {
|
||||
@@ -342,19 +334,19 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMatchAnnotationOnClassWithAtWithin() throws Exception {
|
||||
void matchAnnotationOnClassWithAtWithin() throws Exception {
|
||||
String expression = "@within(test.annotation.transaction.Tx)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMatchAnnotationOnClassWithoutBinding() throws Exception {
|
||||
void matchAnnotationOnClassWithoutBinding() throws Exception {
|
||||
String expression = "within(@test.annotation.transaction.Tx *)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMatchAnnotationOnClassWithSubpackageWildcard() throws Exception {
|
||||
void matchAnnotationOnClassWithSubpackageWildcard() throws Exception {
|
||||
String expression = "within(@(test.annotation..*) *)";
|
||||
AspectJExpressionPointcut springAnnotatedPc = testMatchAnnotationOnClass(expression);
|
||||
assertThat(springAnnotatedPc.matches(TestBean.class.getMethod("setName", String.class), TestBean.class)).isFalse();
|
||||
@@ -366,7 +358,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMatchAnnotationOnClassWithExactPackageWildcard() throws Exception {
|
||||
void matchAnnotationOnClassWithExactPackageWildcard() throws Exception {
|
||||
String expression = "within(@(test.annotation.transaction.*) *)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
@@ -384,7 +376,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAnnotationOnMethodWithFQN() throws Exception {
|
||||
void annotationOnMethodWithFQN() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
@@ -398,7 +390,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAnnotationOnCglibProxyMethod() throws Exception {
|
||||
void annotationOnCglibProxyMethod() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
@@ -410,7 +402,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNotAnnotationOnCglibProxyMethod() throws Exception {
|
||||
void notAnnotationOnCglibProxyMethod() throws Exception {
|
||||
String expression = "!@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
@@ -422,7 +414,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAnnotationOnDynamicProxyMethod() throws Exception {
|
||||
void annotationOnDynamicProxyMethod() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
@@ -434,7 +426,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNotAnnotationOnDynamicProxyMethod() throws Exception {
|
||||
void notAnnotationOnDynamicProxyMethod() throws Exception {
|
||||
String expression = "!@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
@@ -446,7 +438,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAnnotationOnMethodWithWildcard() throws Exception {
|
||||
void annotationOnMethodWithWildcard() throws Exception {
|
||||
String expression = "execution(@(test.annotation..*) * *(..))";
|
||||
AspectJExpressionPointcut anySpringMethodAnnotation = new AspectJExpressionPointcut();
|
||||
anySpringMethodAnnotation.setExpression(expression);
|
||||
@@ -462,7 +454,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAnnotationOnMethodArgumentsWithFQN() throws Exception {
|
||||
void annotationOnMethodArgumentsWithFQN() throws Exception {
|
||||
String expression = "@args(*, test.annotation.EmptySpringAnnotation))";
|
||||
AspectJExpressionPointcut takesSpringAnnotatedArgument2 = new AspectJExpressionPointcut();
|
||||
takesSpringAnnotatedArgument2.setExpression(expression);
|
||||
@@ -491,7 +483,7 @@ class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAnnotationOnMethodArgumentsWithWildcards() throws Exception {
|
||||
void annotationOnMethodArgumentsWithWildcards() throws Exception {
|
||||
String expression = "execution(* *(*, @(test..*) *))";
|
||||
AspectJExpressionPointcut takesSpringAnnotatedArgument2 = new AspectJExpressionPointcut();
|
||||
takesSpringAnnotatedArgument2.setExpression(expression);
|
||||
|
||||
+2
-2
@@ -31,7 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class BeanNamePointcutMatchingTests {
|
||||
|
||||
@Test
|
||||
void testMatchingPointcuts() {
|
||||
void matchingPointcuts() {
|
||||
assertMatch("someName", "bean(someName)");
|
||||
|
||||
// Spring bean names are less restrictive compared to AspectJ names (methods, types etc.)
|
||||
@@ -66,7 +66,7 @@ class BeanNamePointcutMatchingTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNonMatchingPointcuts() {
|
||||
void nonMatchingPointcuts() {
|
||||
assertMisMatch("someName", "bean(someNamex)");
|
||||
assertMisMatch("someName", "bean(someX*Name)");
|
||||
|
||||
|
||||
+7
-8
@@ -17,7 +17,6 @@
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
@@ -49,17 +48,17 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
class MethodInvocationProceedingJoinPointTests {
|
||||
|
||||
@Test
|
||||
void testingBindingWithJoinPoint() {
|
||||
void bindingWithJoinPoint() {
|
||||
assertThatIllegalStateException().isThrownBy(AbstractAspectJAdvice::currentJoinPoint);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testingBindingWithProceedingJoinPoint() {
|
||||
void bindingWithProceedingJoinPoint() {
|
||||
assertThatIllegalStateException().isThrownBy(AbstractAspectJAdvice::currentJoinPoint);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCanGetMethodSignatureFromJoinPoint() {
|
||||
void canGetMethodSignatureFromJoinPoint() {
|
||||
final Object raw = new TestBean();
|
||||
// Will be set by advice during a method call
|
||||
final int newAge = 23;
|
||||
@@ -106,9 +105,9 @@ class MethodInvocationProceedingJoinPointTests {
|
||||
assertThat(AbstractAspectJAdvice.currentJoinPoint().getSignature()).as("Return same MethodSignature repeatedly").isSameAs(msig);
|
||||
assertThat(AbstractAspectJAdvice.currentJoinPoint()).as("Return same JoinPoint repeatedly").isSameAs(AbstractAspectJAdvice.currentJoinPoint());
|
||||
assertThat(msig.getDeclaringType()).isEqualTo(method.getDeclaringClass());
|
||||
assertThat(Arrays.equals(method.getParameterTypes(), msig.getParameterTypes())).isTrue();
|
||||
assertThat(method.getParameterTypes()).isEqualTo(msig.getParameterTypes());
|
||||
assertThat(msig.getReturnType()).isEqualTo(method.getReturnType());
|
||||
assertThat(Arrays.equals(method.getExceptionTypes(), msig.getExceptionTypes())).isTrue();
|
||||
assertThat(method.getExceptionTypes()).isEqualTo(msig.getExceptionTypes());
|
||||
msig.toLongString();
|
||||
msig.toShortString();
|
||||
});
|
||||
@@ -118,7 +117,7 @@ class MethodInvocationProceedingJoinPointTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCanGetSourceLocationFromJoinPoint() {
|
||||
void canGetSourceLocationFromJoinPoint() {
|
||||
final Object raw = new TestBean();
|
||||
ProxyFactory pf = new ProxyFactory(raw);
|
||||
pf.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
|
||||
@@ -135,7 +134,7 @@ class MethodInvocationProceedingJoinPointTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCanGetStaticPartFromJoinPoint() {
|
||||
void canGetStaticPartFromJoinPoint() {
|
||||
final Object raw = new TestBean();
|
||||
ProxyFactory pf = new ProxyFactory(raw);
|
||||
pf.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
|
||||
|
||||
+5
-5
@@ -43,14 +43,14 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
class TrickyAspectJPointcutExpressionTests {
|
||||
|
||||
@Test
|
||||
void testManualProxyJavaWithUnconditionalPointcut() {
|
||||
void manualProxyJavaWithUnconditionalPointcut() {
|
||||
TestService target = new TestServiceImpl();
|
||||
LogUserAdvice logAdvice = new LogUserAdvice();
|
||||
testAdvice(new DefaultPointcutAdvisor(logAdvice), logAdvice, target, "TestServiceImpl");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testManualProxyJavaWithStaticPointcut() {
|
||||
void manualProxyJavaWithStaticPointcut() {
|
||||
TestService target = new TestServiceImpl();
|
||||
LogUserAdvice logAdvice = new LogUserAdvice();
|
||||
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
@@ -59,7 +59,7 @@ class TrickyAspectJPointcutExpressionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testManualProxyJavaWithDynamicPointcut() {
|
||||
void manualProxyJavaWithDynamicPointcut() {
|
||||
TestService target = new TestServiceImpl();
|
||||
LogUserAdvice logAdvice = new LogUserAdvice();
|
||||
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
@@ -68,7 +68,7 @@ class TrickyAspectJPointcutExpressionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testManualProxyJavaWithDynamicPointcutAndProxyTargetClass() {
|
||||
void manualProxyJavaWithDynamicPointcutAndProxyTargetClass() {
|
||||
TestService target = new TestServiceImpl();
|
||||
LogUserAdvice logAdvice = new LogUserAdvice();
|
||||
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
@@ -77,7 +77,7 @@ class TrickyAspectJPointcutExpressionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testManualProxyJavaWithStaticPointcutAndTwoClassLoaders() throws Exception {
|
||||
void manualProxyJavaWithStaticPointcutAndTwoClassLoaders() throws Exception {
|
||||
|
||||
LogUserAdvice logAdvice = new LogUserAdvice();
|
||||
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
|
||||
+3
-3
@@ -97,7 +97,7 @@ class TypePatternClassFilterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEquals() {
|
||||
void equals() {
|
||||
TypePatternClassFilter filter1 = new TypePatternClassFilter("org.springframework.beans.testfixture.beans.*");
|
||||
TypePatternClassFilter filter2 = new TypePatternClassFilter("org.springframework.beans.testfixture.beans.*");
|
||||
TypePatternClassFilter filter3 = new TypePatternClassFilter("org.springframework.tests.*");
|
||||
@@ -107,7 +107,7 @@ class TypePatternClassFilterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHashCode() {
|
||||
void hashCodeBehavior() {
|
||||
TypePatternClassFilter filter1 = new TypePatternClassFilter("org.springframework.beans.testfixture.beans.*");
|
||||
TypePatternClassFilter filter2 = new TypePatternClassFilter("org.springframework.beans.testfixture.beans.*");
|
||||
TypePatternClassFilter filter3 = new TypePatternClassFilter("org.springframework.tests.*");
|
||||
@@ -117,7 +117,7 @@ class TypePatternClassFilterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToString() {
|
||||
void toStringOutput() {
|
||||
TypePatternClassFilter filter1 = new TypePatternClassFilter("org.springframework.beans.testfixture.beans.*");
|
||||
TypePatternClassFilter filter2 = new TypePatternClassFilter("org.springframework.beans.testfixture.beans.*");
|
||||
|
||||
|
||||
+2
-2
@@ -430,8 +430,8 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(itb::getAge);
|
||||
}
|
||||
|
||||
// TODO document this behaviour.
|
||||
// Is it different AspectJ behaviour, at least for checked exceptions?
|
||||
// TODO document this behavior.
|
||||
// Is it different AspectJ behavior, at least for checked exceptions?
|
||||
@Test
|
||||
void aspectMethodThrowsExceptionIllegalOnSignature() {
|
||||
TestBean target = new TestBean();
|
||||
|
||||
+5
-6
@@ -39,7 +39,7 @@ class AspectJPointcutAdvisorTests {
|
||||
|
||||
|
||||
@Test
|
||||
void testSingleton() throws SecurityException, NoSuchMethodException {
|
||||
void singleton() throws SecurityException, NoSuchMethodException {
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(CommonExpressions.MATCH_ALL_METHODS);
|
||||
|
||||
@@ -53,7 +53,7 @@ class AspectJPointcutAdvisorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPerTarget() throws SecurityException, NoSuchMethodException {
|
||||
void perTarget() throws SecurityException, NoSuchMethodException {
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(CommonExpressions.MATCH_ALL_METHODS);
|
||||
|
||||
@@ -63,8 +63,7 @@ class AspectJPointcutAdvisorTests {
|
||||
1, "someBean");
|
||||
|
||||
assertThat(ajpa.getAspectMetadata().getPerClausePointcut()).isNotSameAs(Pointcut.TRUE);
|
||||
boolean condition = ajpa.getAspectMetadata().getPerClausePointcut() instanceof AspectJExpressionPointcut;
|
||||
assertThat(condition).isTrue();
|
||||
assertThat(ajpa.getAspectMetadata().getPerClausePointcut()).isInstanceOf(AspectJExpressionPointcut.class);
|
||||
assertThat(ajpa.isPerInstance()).isTrue();
|
||||
|
||||
assertThat(ajpa.getAspectMetadata().getPerClausePointcut().getClassFilter().matches(TestBean.class)).isTrue();
|
||||
@@ -76,13 +75,13 @@ class AspectJPointcutAdvisorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPerCflowTarget() {
|
||||
void perCflowTarget() {
|
||||
assertThatExceptionOfType(AopConfigException.class).isThrownBy(() ->
|
||||
testIllegalInstantiationModel(AbstractAspectJAdvisorFactoryTests.PerCflowAspect.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPerCflowBelowTarget() {
|
||||
void perCflowBelowTarget() {
|
||||
assertThatExceptionOfType(AopConfigException.class).isThrownBy(() ->
|
||||
testIllegalInstantiationModel(AbstractAspectJAdvisorFactoryTests.PerCflowBelowAspect.class));
|
||||
}
|
||||
|
||||
+9
-9
@@ -39,13 +39,13 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
class AspectProxyFactoryTests {
|
||||
|
||||
@Test
|
||||
void testWithNonAspect() {
|
||||
void withNonAspect() {
|
||||
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean());
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> proxyFactory.addAspect(TestBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithSimpleAspect() {
|
||||
void withSimpleAspect() {
|
||||
TestBean bean = new TestBean();
|
||||
bean.setAge(2);
|
||||
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(bean);
|
||||
@@ -55,7 +55,7 @@ class AspectProxyFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithPerThisAspect() {
|
||||
void withPerThisAspect() {
|
||||
TestBean bean1 = new TestBean();
|
||||
TestBean bean2 = new TestBean();
|
||||
|
||||
@@ -75,14 +75,14 @@ class AspectProxyFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithInstanceWithNonAspect() {
|
||||
void withInstanceWithNonAspect() {
|
||||
AspectJProxyFactory pf = new AspectJProxyFactory();
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> pf.addAspect(new TestBean()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void testSerializable() throws Exception {
|
||||
void serializable() throws Exception {
|
||||
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean());
|
||||
proxyFactory.addAspect(LoggingAspectOnVarargs.class);
|
||||
ITestBean proxy = proxyFactory.getProxy();
|
||||
@@ -92,7 +92,7 @@ class AspectProxyFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithInstance() throws Exception {
|
||||
void withInstance() throws Exception {
|
||||
MultiplyReturnValue aspect = new MultiplyReturnValue();
|
||||
int multiple = 3;
|
||||
aspect.setMultiple(multiple);
|
||||
@@ -111,14 +111,14 @@ class AspectProxyFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithNonSingletonAspectInstance() {
|
||||
void withNonSingletonAspectInstance() {
|
||||
AspectJProxyFactory pf = new AspectJProxyFactory();
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> pf.addAspect(new PerThisAspect()));
|
||||
}
|
||||
|
||||
@Test // SPR-13328
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testProxiedVarargsWithEnumArray() {
|
||||
void proxiedVarargsWithEnumArray() {
|
||||
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean());
|
||||
proxyFactory.addAspect(LoggingAspectOnVarargs.class);
|
||||
ITestBean proxy = proxyFactory.getProxy();
|
||||
@@ -127,7 +127,7 @@ class AspectProxyFactoryTests {
|
||||
|
||||
@Test // SPR-13328
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testUnproxiedVarargsWithEnumArray() {
|
||||
void unproxiedVarargsWithEnumArray() {
|
||||
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean());
|
||||
proxyFactory.addAspect(LoggingAspectOnSetter.class);
|
||||
ITestBean proxy = proxyFactory.getProxy();
|
||||
|
||||
+5
-5
@@ -47,7 +47,7 @@ class AspectJNamespaceHandlerTests {
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
void setUp() {
|
||||
SourceExtractor sourceExtractor = new PassThroughSourceExtractor();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.registry);
|
||||
XmlReaderContext readerContext =
|
||||
@@ -56,7 +56,7 @@ class AspectJNamespaceHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRegisterAutoProxyCreator() {
|
||||
void registerAutoProxyCreator() {
|
||||
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(this.parserContext, null);
|
||||
assertThat(registry.getBeanDefinitionCount()).as("Incorrect number of definitions registered").isEqualTo(1);
|
||||
|
||||
@@ -65,7 +65,7 @@ class AspectJNamespaceHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRegisterAspectJAutoProxyCreator() {
|
||||
void registerAspectJAutoProxyCreator() {
|
||||
AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(this.parserContext, null);
|
||||
assertThat(registry.getBeanDefinitionCount()).as("Incorrect number of definitions registered").isEqualTo(1);
|
||||
|
||||
@@ -77,7 +77,7 @@ class AspectJNamespaceHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRegisterAspectJAutoProxyCreatorWithExistingAutoProxyCreator() {
|
||||
void registerAspectJAutoProxyCreatorWithExistingAutoProxyCreator() {
|
||||
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(this.parserContext, null);
|
||||
assertThat(registry.getBeanDefinitionCount()).isEqualTo(1);
|
||||
|
||||
@@ -89,7 +89,7 @@ class AspectJNamespaceHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRegisterAutoProxyCreatorWhenAspectJAutoProxyCreatorAlreadyExists() {
|
||||
void registerAutoProxyCreatorWhenAspectJAutoProxyCreatorAlreadyExists() {
|
||||
AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(this.parserContext, null);
|
||||
assertThat(registry.getBeanDefinitionCount()).isEqualTo(1);
|
||||
|
||||
|
||||
+21
-16
@@ -33,6 +33,7 @@ import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.aspectj.AspectJMethodBeforeAdvice;
|
||||
import org.springframework.aop.aspectj.AspectJPointcutAdvisor;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -48,24 +49,21 @@ class AspectJPrecedenceComparatorTests {
|
||||
private static final int LATE_ADVICE_DECLARATION_ORDER = 10;
|
||||
|
||||
|
||||
private AspectJPrecedenceComparator comparator;
|
||||
private final AspectJPrecedenceComparator comparator = new AspectJPrecedenceComparator();
|
||||
|
||||
private Method anyOldMethod;
|
||||
private final Method anyOldMethod = ClassUtils.getMethod(MessageService.class, "getMessage");
|
||||
|
||||
private AspectJExpressionPointcut anyOldPointcut;
|
||||
private final AspectJExpressionPointcut anyOldPointcut = new AspectJExpressionPointcut();
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
this.comparator = new AspectJPrecedenceComparator();
|
||||
this.anyOldMethod = getClass().getMethods()[0];
|
||||
this.anyOldPointcut = new AspectJExpressionPointcut();
|
||||
void setUp() {
|
||||
this.anyOldPointcut.setExpression("execution(* *(..))");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testSameAspectNoAfterAdvice() {
|
||||
void sameAspectNoAfterAdvice() {
|
||||
Advisor advisor1 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
assertThat(this.comparator.compare(advisor1, advisor2)).as("advisor1 sorted before advisor2").isEqualTo(-1);
|
||||
@@ -76,7 +74,7 @@ class AspectJPrecedenceComparatorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSameAspectAfterAdvice() {
|
||||
void sameAspectAfterAdvice() {
|
||||
Advisor advisor1 = createAspectJAfterAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
assertThat(this.comparator.compare(advisor1, advisor2)).as("advisor2 sorted before advisor1").isEqualTo(1);
|
||||
@@ -87,14 +85,14 @@ class AspectJPrecedenceComparatorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSameAspectOneOfEach() {
|
||||
void sameAspectOneOfEach() {
|
||||
Advisor advisor1 = createAspectJAfterAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
assertThat(this.comparator.compare(advisor1, advisor2)).as("advisor1 and advisor2 not comparable").isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSameAdvisorPrecedenceDifferentAspectNoAfterAdvice() {
|
||||
void sameAdvisorPrecedenceDifferentAspectNoAfterAdvice() {
|
||||
Advisor advisor1 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertThat(this.comparator.compare(advisor1, advisor2)).as("nothing to say about order here").isEqualTo(0);
|
||||
@@ -105,7 +103,7 @@ class AspectJPrecedenceComparatorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSameAdvisorPrecedenceDifferentAspectAfterAdvice() {
|
||||
void sameAdvisorPrecedenceDifferentAspectAfterAdvice() {
|
||||
Advisor advisor1 = createAspectJAfterAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertThat(this.comparator.compare(advisor1, advisor2)).as("nothing to say about order here").isEqualTo(0);
|
||||
@@ -116,7 +114,7 @@ class AspectJPrecedenceComparatorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHigherAdvisorPrecedenceNoAfterAdvice() {
|
||||
void higherAdvisorPrecedenceNoAfterAdvice() {
|
||||
Advisor advisor1 = createSpringAOPBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER);
|
||||
Advisor advisor2 = createAspectJBeforeAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertThat(this.comparator.compare(advisor1, advisor2)).as("advisor1 sorted before advisor2").isEqualTo(-1);
|
||||
@@ -127,7 +125,7 @@ class AspectJPrecedenceComparatorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHigherAdvisorPrecedenceAfterAdvice() {
|
||||
void higherAdvisorPrecedenceAfterAdvice() {
|
||||
Advisor advisor1 = createAspectJAfterAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJAroundAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertThat(this.comparator.compare(advisor1, advisor2)).as("advisor1 sorted before advisor2").isEqualTo(-1);
|
||||
@@ -138,7 +136,7 @@ class AspectJPrecedenceComparatorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLowerAdvisorPrecedenceNoAfterAdvice() {
|
||||
void lowerAdvisorPrecedenceNoAfterAdvice() {
|
||||
Advisor advisor1 = createAspectJBeforeAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertThat(this.comparator.compare(advisor1, advisor2)).as("advisor1 sorted after advisor2").isEqualTo(1);
|
||||
@@ -149,7 +147,7 @@ class AspectJPrecedenceComparatorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLowerAdvisorPrecedenceAfterAdvice() {
|
||||
void lowerAdvisorPrecedenceAfterAdvice() {
|
||||
Advisor advisor1 = createAspectJAfterAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertThat(this.comparator.compare(advisor1, advisor2)).as("advisor1 sorted after advisor2").isEqualTo(1);
|
||||
@@ -209,4 +207,11 @@ class AspectJPrecedenceComparatorTests {
|
||||
return advisor;
|
||||
}
|
||||
|
||||
static class MessageService {
|
||||
|
||||
public String getMessage() {
|
||||
return "test";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class MethodInvocationTests {
|
||||
|
||||
@Test
|
||||
void testValidInvocation() throws Throwable {
|
||||
void validInvocation() throws Throwable {
|
||||
Method method = Object.class.getMethod("hashCode");
|
||||
Object proxy = new Object();
|
||||
Object returnValue = new Object();
|
||||
@@ -49,7 +49,7 @@ class MethodInvocationTests {
|
||||
* toString on target can cause failure.
|
||||
*/
|
||||
@Test
|
||||
void testToStringDoesntHitTarget() throws Throwable {
|
||||
void toStringDoesntHitTarget() throws Throwable {
|
||||
Object target = new TestBean() {
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
@@ -36,7 +36,7 @@ class NullPrimitiveTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNullPrimitiveWithJdkProxy() {
|
||||
void nullPrimitiveWithJdkProxy() {
|
||||
|
||||
class SimpleFoo implements Foo {
|
||||
@Override
|
||||
@@ -62,7 +62,7 @@ class NullPrimitiveTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNullPrimitiveWithCglibProxy() {
|
||||
void nullPrimitiveWithCglibProxy() {
|
||||
|
||||
Bar target = new Bar();
|
||||
ProxyFactory factory = new ProxyFactory(target);
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ class PrototypeTargetTests {
|
||||
|
||||
|
||||
@Test
|
||||
void testPrototypeProxyWithPrototypeTarget() {
|
||||
void prototypeProxyWithPrototypeTarget() {
|
||||
TestBeanImpl.constructionCount = 0;
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(CONTEXT);
|
||||
@@ -52,7 +52,7 @@ class PrototypeTargetTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSingletonProxyWithPrototypeTarget() {
|
||||
void singletonProxyWithPrototypeTarget() {
|
||||
TestBeanImpl.constructionCount = 0;
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(CONTEXT);
|
||||
|
||||
+6
-6
@@ -40,14 +40,14 @@ import static org.mockito.Mockito.mock;
|
||||
class ThrowsAdviceInterceptorTests {
|
||||
|
||||
@Test
|
||||
void testNoHandlerMethods() {
|
||||
void noHandlerMethods() {
|
||||
// should require one handler method at least
|
||||
assertThatExceptionOfType(AopConfigException.class).isThrownBy(() ->
|
||||
new ThrowsAdviceInterceptor(new Object()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNotInvoked() throws Throwable {
|
||||
void notInvoked() throws Throwable {
|
||||
MyThrowsHandler th = new MyThrowsHandler();
|
||||
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
|
||||
Object ret = new Object();
|
||||
@@ -58,7 +58,7 @@ class ThrowsAdviceInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoHandlerMethodForThrowable() throws Throwable {
|
||||
void noHandlerMethodForThrowable() throws Throwable {
|
||||
MyThrowsHandler th = new MyThrowsHandler();
|
||||
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
|
||||
assertThat(ti.getHandlerMethodCount()).isEqualTo(2);
|
||||
@@ -70,7 +70,7 @@ class ThrowsAdviceInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCorrectHandlerUsed() throws Throwable {
|
||||
void correctHandlerUsed() throws Throwable {
|
||||
MyThrowsHandler th = new MyThrowsHandler();
|
||||
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
|
||||
FileNotFoundException ex = new FileNotFoundException();
|
||||
@@ -84,7 +84,7 @@ class ThrowsAdviceInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCorrectHandlerUsedForSubclass() throws Throwable {
|
||||
void correctHandlerUsedForSubclass() throws Throwable {
|
||||
MyThrowsHandler th = new MyThrowsHandler();
|
||||
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
|
||||
// Extends RemoteException
|
||||
@@ -97,7 +97,7 @@ class ThrowsAdviceInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHandlerMethodThrowsException() throws Throwable {
|
||||
void handlerMethodThrowsException() throws Throwable {
|
||||
final Throwable t = new Throwable();
|
||||
|
||||
MyThrowsHandler th = new MyThrowsHandler() {
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ import static org.mockito.Mockito.verify;
|
||||
class DebugInterceptorTests {
|
||||
|
||||
@Test
|
||||
void testSunnyDayPathLogsCorrectly() throws Throwable {
|
||||
void sunnyDayPathLogsCorrectly() throws Throwable {
|
||||
MethodInvocation methodInvocation = mock();
|
||||
|
||||
Log log = mock();
|
||||
@@ -52,7 +52,7 @@ class DebugInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExceptionPathStillLogsCorrectly() throws Throwable {
|
||||
void exceptionPathStillLogsCorrectly() throws Throwable {
|
||||
MethodInvocation methodInvocation = mock();
|
||||
|
||||
IllegalArgumentException exception = new IllegalArgumentException();
|
||||
|
||||
+4
-6
@@ -46,7 +46,7 @@ class ExposeBeanNameAdvisorsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoIntroduction() {
|
||||
void noIntroduction() {
|
||||
String beanName = "foo";
|
||||
TestBean target = new RequiresBeanNameBoundTestBean(beanName);
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
@@ -54,14 +54,13 @@ class ExposeBeanNameAdvisorsTests {
|
||||
pf.addAdvisor(ExposeBeanNameAdvisors.createAdvisorWithoutIntroduction(beanName));
|
||||
ITestBean proxy = (ITestBean) pf.getProxy();
|
||||
|
||||
boolean condition = proxy instanceof NamedBean;
|
||||
assertThat(condition).as("No introduction").isFalse();
|
||||
assertThat(proxy).as("No introduction").isNotInstanceOf(NamedBean.class);
|
||||
// Requires binding
|
||||
proxy.getAge();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithIntroduction() {
|
||||
void withIntroduction() {
|
||||
String beanName = "foo";
|
||||
TestBean target = new RequiresBeanNameBoundTestBean(beanName);
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
@@ -69,8 +68,7 @@ class ExposeBeanNameAdvisorsTests {
|
||||
pf.addAdvisor(ExposeBeanNameAdvisors.createAdvisorIntroducingNamedBean(beanName));
|
||||
ITestBean proxy = (ITestBean) pf.getProxy();
|
||||
|
||||
boolean condition = proxy instanceof NamedBean;
|
||||
assertThat(condition).as("Introduction was made").isTrue();
|
||||
assertThat(proxy).as("Introduction was made").isInstanceOf(NamedBean.class);
|
||||
// Requires binding
|
||||
proxy.getAge();
|
||||
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ import static org.springframework.core.testfixture.io.ResourceTestUtils.qualifie
|
||||
class ExposeInvocationInterceptorTests {
|
||||
|
||||
@Test
|
||||
void testXmlConfig() {
|
||||
void xmlConfig() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
|
||||
qualifiedResource(ExposeInvocationInterceptorTests.class, "context.xml"));
|
||||
|
||||
+3
-3
@@ -35,7 +35,7 @@ import static org.mockito.Mockito.verify;
|
||||
class PerformanceMonitorInterceptorTests {
|
||||
|
||||
@Test
|
||||
void testSuffixAndPrefixAssignment() {
|
||||
void suffixAndPrefixAssignment() {
|
||||
PerformanceMonitorInterceptor interceptor = new PerformanceMonitorInterceptor();
|
||||
|
||||
assertThat(interceptor.getPrefix()).isNotNull();
|
||||
@@ -49,7 +49,7 @@ class PerformanceMonitorInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSunnyDayPathLogsPerformanceMetricsCorrectly() throws Throwable {
|
||||
void sunnyDayPathLogsPerformanceMetricsCorrectly() throws Throwable {
|
||||
MethodInvocation mi = mock();
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
|
||||
@@ -62,7 +62,7 @@ class PerformanceMonitorInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExceptionPathStillLogsPerformanceMetricsCorrectly() throws Throwable {
|
||||
void exceptionPathStillLogsPerformanceMetricsCorrectly() throws Throwable {
|
||||
MethodInvocation mi = mock();
|
||||
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
|
||||
+2
-2
@@ -37,7 +37,7 @@ import static org.mockito.Mockito.verify;
|
||||
class SimpleTraceInterceptorTests {
|
||||
|
||||
@Test
|
||||
void testSunnyDayPathLogsCorrectly() throws Throwable {
|
||||
void sunnyDayPathLogsCorrectly() throws Throwable {
|
||||
MethodInvocation mi = mock();
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(mi.getThis()).willReturn(this);
|
||||
@@ -51,7 +51,7 @@ class SimpleTraceInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExceptionPathStillLogsCorrectly() throws Throwable {
|
||||
void exceptionPathStillLogsCorrectly() throws Throwable {
|
||||
MethodInvocation mi = mock();
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(mi.getThis()).willReturn(this);
|
||||
|
||||
+4
-4
@@ -35,25 +35,25 @@ class DefaultScopedObjectTests {
|
||||
|
||||
|
||||
@Test
|
||||
void testCtorWithNullBeanFactory() {
|
||||
void ctorWithNullBeanFactory() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
new DefaultScopedObject(null, GOOD_BEAN_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCtorWithNullTargetBeanName() {
|
||||
void ctorWithNullTargetBeanName() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
testBadTargetBeanName(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCtorWithEmptyTargetBeanName() {
|
||||
void ctorWithEmptyTargetBeanName() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
testBadTargetBeanName(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCtorWithJustWhitespacedTargetBeanName() {
|
||||
void ctorWithJustWhitespacedTargetBeanName() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
testBadTargetBeanName(" "));
|
||||
}
|
||||
|
||||
+2
-2
@@ -34,7 +34,7 @@ import static org.springframework.core.testfixture.io.ResourceTestUtils.qualifie
|
||||
class ScopedProxyAutowireTests {
|
||||
|
||||
@Test
|
||||
void testScopedProxyInheritsAutowireCandidateFalse() {
|
||||
void scopedProxyInheritsAutowireCandidateFalse() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
|
||||
qualifiedResource(ScopedProxyAutowireTests.class, "scopedAutowireFalse.xml"));
|
||||
@@ -48,7 +48,7 @@ class ScopedProxyAutowireTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testScopedProxyReplacesAutowireCandidateTrue() {
|
||||
void scopedProxyReplacesAutowireCandidateTrue() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
|
||||
qualifiedResource(ScopedProxyAutowireTests.class, "scopedAutowireTrue.xml"));
|
||||
|
||||
@@ -45,7 +45,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class AopUtilsTests {
|
||||
|
||||
@Test
|
||||
void testPointcutCanNeverApply() {
|
||||
void pointcutCanNeverApply() {
|
||||
class TestPointcut extends StaticMethodMatcherPointcut {
|
||||
@Override
|
||||
public boolean matches(Method method, @Nullable Class<?> clazzy) {
|
||||
@@ -58,13 +58,13 @@ class AopUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPointcutAlwaysApplies() {
|
||||
void pointcutAlwaysApplies() {
|
||||
assertThat(AopUtils.canApply(new DefaultPointcutAdvisor(new NopInterceptor()), Object.class)).isTrue();
|
||||
assertThat(AopUtils.canApply(new DefaultPointcutAdvisor(new NopInterceptor()), TestBean.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPointcutAppliesToOneMethodOnObject() {
|
||||
void pointcutAppliesToOneMethodOnObject() {
|
||||
class TestPointcut extends StaticMethodMatcherPointcut {
|
||||
@Override
|
||||
public boolean matches(Method method, @Nullable Class<?> clazz) {
|
||||
@@ -84,7 +84,7 @@ class AopUtilsTests {
|
||||
* that's subverted the singleton construction limitation.
|
||||
*/
|
||||
@Test
|
||||
void testCanonicalFrameworkClassesStillCanonicalOnDeserialization() throws Exception {
|
||||
void canonicalFrameworkClassesStillCanonicalOnDeserialization() throws Exception {
|
||||
assertThat(SerializationTestUtils.serializeAndDeserialize(MethodMatcher.TRUE)).isSameAs(MethodMatcher.TRUE);
|
||||
assertThat(SerializationTestUtils.serializeAndDeserialize(ClassFilter.TRUE)).isSameAs(ClassFilter.TRUE);
|
||||
assertThat(SerializationTestUtils.serializeAndDeserialize(Pointcut.TRUE)).isSameAs(Pointcut.TRUE);
|
||||
@@ -95,7 +95,7 @@ class AopUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvokeJoinpointUsingReflection() throws Throwable {
|
||||
void invokeJoinpointUsingReflection() throws Throwable {
|
||||
String name = "foo";
|
||||
TestBean testBean = new TestBean(name);
|
||||
Method method = ReflectionUtils.findMethod(TestBean.class, "getName");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user