mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-19 10:59:13 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d045d40702 | ||
|
|
afd67a0deb | ||
|
|
dcaddddbc5 | ||
|
|
ce3be72e7f | ||
|
|
3e3f046dc9 | ||
|
|
5847454aa4 | ||
|
|
569df6eecc | ||
|
|
979118c1eb | ||
|
|
f87a87e29d | ||
|
|
0619e19140 | ||
|
|
ac521a366a | ||
|
|
9a4df5a97d | ||
|
|
f54e1ef880 | ||
|
|
a3efcabe0c | ||
|
|
dd3dc2d0d0 | ||
|
|
2578e3894e | ||
|
|
5335778d8d | ||
|
|
616e7779e0 | ||
|
|
84c7f07364 | ||
|
|
ac429a4ef7 | ||
|
|
12d4dc1bae | ||
|
|
4da2499613 | ||
|
|
18896aceca | ||
|
|
d7824c7831 | ||
|
|
f91b2249b3 | ||
|
|
33b329e13a | ||
|
|
b23316302d | ||
|
|
dc843adb45 | ||
|
|
9fcafd2650 | ||
|
|
ccbb4bdd27 | ||
|
|
5b79a57f14 | ||
|
|
189d4e3e4c | ||
|
|
79a1fcb099 | ||
|
|
026be04b75 | ||
|
|
45ae00fda3 | ||
|
|
3e2f58cdd2 | ||
|
|
72926c29f9 | ||
|
|
f5c1e2ffa1 | ||
|
|
67df0756cd | ||
|
|
17bc3facaa | ||
|
|
1de9426df0 | ||
|
|
27fdf56ed5 | ||
|
|
55392dfbd7 | ||
|
|
ca9439657e | ||
|
|
5819d76d98 | ||
|
|
431ae03447 | ||
|
|
a7ec6b4a2a | ||
|
|
e5ff54955f | ||
|
|
9c0b28ffdc | ||
|
|
08e7f5a292 | ||
|
|
5f458e2578 | ||
|
|
7584dfc79a | ||
|
|
dc2c33e0ab | ||
|
|
dbf360997a | ||
|
|
b719a87061 | ||
|
|
97e557c886 | ||
|
|
89c170b095 | ||
|
|
482482f62b | ||
|
|
a2a676241c | ||
|
|
28602ad012 | ||
|
|
8e9dc3590d | ||
|
|
b8a7aa9395 | ||
|
|
cb63164593 | ||
|
|
9f061f1eec | ||
|
|
1d4bf58e8d | ||
|
|
ce85fdc5c7 | ||
|
|
7851994a17 | ||
|
|
84bc1dfa89 | ||
|
|
159a3e71f2 | ||
|
|
adbba712d6 | ||
|
|
e050c37158 | ||
|
|
eff1a1a664 | ||
|
|
8838e0d825 | ||
|
|
0d21f0b1d4 | ||
|
|
41aeb07585 | ||
|
|
70aaec2a8d | ||
|
|
3029b7b9be | ||
|
|
708f600afe | ||
|
|
f7418704de | ||
|
|
7440afe571 | ||
|
|
bc583ea74f | ||
|
|
dcda127b60 | ||
|
|
ac6385025b | ||
|
|
e170c16b02 | ||
|
|
4beb05ddb3 | ||
|
|
06fd6ecf1f | ||
|
|
b8827d8e11 | ||
|
|
23a60aeb27 | ||
|
|
58fbf60d2d | ||
|
|
ebca9f726f | ||
|
|
5fd73f0bae | ||
|
|
16937c7ce5 | ||
|
|
c0c9ba5c2c | ||
|
|
4d6249811e | ||
|
|
3a08d643ed | ||
|
|
a74b86e812 | ||
|
|
7c9dca3d2e | ||
|
|
64219783f6 | ||
|
|
846a54aef4 | ||
|
|
9e735d4f0f | ||
|
|
0ddb394fd0 | ||
|
|
f5a39308a0 | ||
|
|
e4ceb80678 | ||
|
|
64b89429cb | ||
|
|
8e843c242a | ||
|
|
635f010de3 | ||
|
|
aac1ed6ee5 | ||
|
|
d5b0782700 | ||
|
|
ebe717ff6c | ||
|
|
89c7c6e9dd | ||
|
|
9c6fd3ed06 | ||
|
|
e564a0de46 | ||
|
|
17f1eadb6f | ||
|
|
09991f2492 | ||
|
|
15931532cd | ||
|
|
aa9f445422 | ||
|
|
b578ff1296 | ||
|
|
cf9fc69d6b | ||
|
|
04321d0577 | ||
|
|
67c141f15b | ||
|
|
ad4e0d9ad7 | ||
|
|
c13dfc5144 | ||
|
|
b7d53ac9a4 | ||
|
|
f9884e08af | ||
|
|
9819cb3eb5 | ||
|
|
9b0929c392 | ||
|
|
af21ebe6c6 | ||
|
|
0b446a94c5 | ||
|
|
5dfa61eb0b | ||
|
|
b267547fb4 | ||
|
|
e0f60dc09d | ||
|
|
8783075e40 | ||
|
|
f2cdced501 | ||
|
|
33a0e65135 | ||
|
|
e3fb0a39a2 | ||
|
|
57fb072215 | ||
|
|
75046bbea0 | ||
|
|
8e2eeb5364 | ||
|
|
556863d401 | ||
|
|
6a6a35a0b9 | ||
|
|
7da6e93597 | ||
|
|
963274a915 | ||
|
|
d72df5ace4 | ||
|
|
767f59a3ae | ||
|
|
da088e58c3 | ||
|
|
5502e61519 | ||
|
|
ab9bea1d93 | ||
|
|
e6397c8a38 | ||
|
|
1e47f31210 | ||
|
|
57b6f7e494 | ||
|
|
d37ef61b30 | ||
|
|
3f148c2aaa | ||
|
|
fa1ef1dc85 | ||
|
|
58872c79ee | ||
|
|
24f18275dd | ||
|
|
8f94c4e933 | ||
|
|
20c79e1481 | ||
|
|
fb0aa5abb3 | ||
|
|
86a40716bd | ||
|
|
7f48d1b55a | ||
|
|
fd84b0997a | ||
|
|
0e8838db90 | ||
|
|
94fc24b6fb | ||
|
|
ab0d1c395d | ||
|
|
047f660572 | ||
|
|
22323072fd | ||
|
|
a34b1af49e | ||
|
|
1ace42f245 | ||
|
|
0502d18e3d | ||
|
|
c4c786596f | ||
|
|
c3d123fef7 | ||
|
|
e4b25ab480 | ||
|
|
1680502313 | ||
|
|
e725e3a51b | ||
|
|
2fe75c1a24 | ||
|
|
9ebd1e8d64 | ||
|
|
64de6de725 | ||
|
|
c3e8ff9ce7 | ||
|
|
5448e81021 | ||
|
|
f7e07322ab | ||
|
|
37217a63e1 | ||
|
|
ad5c636aff | ||
|
|
ebdc82b86b | ||
|
|
a12c9a0430 | ||
|
|
0d14c3bc1a | ||
|
|
8be542016b | ||
|
|
3a585f8c29 | ||
|
|
c0e38a2f1e | ||
|
|
5de1460f88 | ||
|
|
312db36849 | ||
|
|
46875c91ce | ||
|
|
86305c45a9 | ||
|
|
1342837686 | ||
|
|
012b8f18c6 | ||
|
|
5ea310452c | ||
|
|
a4956dfe26 | ||
|
|
0415975dd1 | ||
|
|
afb8a0d1b1 | ||
|
|
48abd493fe |
@@ -30,5 +30,7 @@ Andy Clement <aclement@vmware.com> <andrew.clement@gmail.com>
|
||||
Sam Brannen <sbrannen@vmware.com>
|
||||
Sam Brannen <sbrannen@vmware.com> <sbrannen@pivotal.io>
|
||||
Sam Brannen <sbrannen@vmware.com> <sam@sambrannen.com>
|
||||
Simon Basle <sbasle@vmware.com>
|
||||
Simon Baslé <sbasle@vmware.com>
|
||||
<dmitry.katsubo@gmail.com> <dmitry.katsubo@gmai.com>
|
||||
Nick Williams <nicholas@nicholaswilliams.net>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Enable auto-env through the sdkman_auto_env config
|
||||
# Add key=value pairs of SDKs to use below
|
||||
java=17.0.5-librca
|
||||
java=17.0.6-librca
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id 'io.spring.nohttp' version '0.0.10'
|
||||
id 'io.spring.nohttp' version '0.0.11'
|
||||
id 'io.freefair.aspectj' version '6.5.0.3' apply false
|
||||
// kotlinVersion is managed in gradle.properties
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version "${kotlinVersion}" apply false
|
||||
@@ -78,7 +78,7 @@ configure([rootProject] + javaProjects) { project ->
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
toolVersion = "10.6.0"
|
||||
toolVersion = "10.7.0"
|
||||
configDirectory.set(rootProject.file("src/checkstyle"))
|
||||
}
|
||||
|
||||
@@ -121,9 +121,9 @@ configure([rootProject] + javaProjects) { project ->
|
||||
"https://docs.jboss.org/jbossas/javadoc/7.1.2.Final/",
|
||||
"https://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
|
||||
"https://www.quartz-scheduler.org/api/2.3.0/",
|
||||
"https://fasterxml.github.io/jackson-core/javadoc/2.10/",
|
||||
"https://fasterxml.github.io/jackson-databind/javadoc/2.10/",
|
||||
"https://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.10/",
|
||||
"https://www.javadoc.io/doc/com.fasterxml.jackson.core/jackson-core/2.14.1/",
|
||||
"https://www.javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind/2.14.1/",
|
||||
"https://www.javadoc.io/doc/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.14.1/",
|
||||
"https://hc.apache.org/httpcomponents-client-5.2.x/current/httpclient5/apidocs/",
|
||||
"https://projectreactor.io/docs/test/release/api/",
|
||||
"https://junit.org/junit4/javadoc/4.13.2/",
|
||||
|
||||
@@ -17,4 +17,4 @@ changelog:
|
||||
- "type: dependency-upgrade"
|
||||
contributors:
|
||||
exclude:
|
||||
names: ["bclozel", "jhoeller", "poutsma", "rstoyanchev", "sbrannen", "sdeleuze", "snicoll"]
|
||||
names: ["bclozel", "jhoeller", "poutsma", "rstoyanchev", "sbrannen", "sdeleuze", "snicoll", "simonbasle"]
|
||||
|
||||
@@ -6,7 +6,6 @@ RUN ./setup.sh
|
||||
|
||||
ENV JAVA_HOME /opt/openjdk/java17
|
||||
ENV JDK17 /opt/openjdk/java17
|
||||
ENV JDK18 /opt/openjdk/java18
|
||||
ENV JDK19 /opt/openjdk/java19
|
||||
|
||||
ENV PATH $JAVA_HOME/bin:$PATH
|
||||
|
||||
@@ -3,13 +3,10 @@ set -e
|
||||
|
||||
case "$1" in
|
||||
java17)
|
||||
echo "https://github.com/bell-sw/Liberica/releases/download/17.0.5+8/bellsoft-jdk17.0.5+8-linux-amd64.tar.gz"
|
||||
;;
|
||||
java18)
|
||||
echo "https://github.com/bell-sw/Liberica/releases/download/18.0.2.1%2B1/bellsoft-jdk18.0.2.1+1-linux-amd64.tar.gz"
|
||||
echo "https://github.com/bell-sw/Liberica/releases/download/17.0.6+10/bellsoft-jdk17.0.6+10-linux-amd64.tar.gz"
|
||||
;;
|
||||
java19)
|
||||
echo "https://github.com/bell-sw/Liberica/releases/download/19.0.1%2B11/bellsoft-jdk19.0.1+11-linux-amd64.tar.gz"
|
||||
echo "https://github.com/bell-sw/Liberica/releases/download/19.0.2+9/bellsoft-jdk19.0.2+9-linux-amd64.tar.gz"
|
||||
;;
|
||||
*)
|
||||
echo $"Unknown java version"
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ curl https://raw.githubusercontent.com/spring-io/concourse-java-scripts/v0.0.4/c
|
||||
|
||||
mkdir -p /opt/openjdk
|
||||
pushd /opt/openjdk > /dev/null
|
||||
for jdk in java17 java18 java19
|
||||
for jdk in java17 java19
|
||||
do
|
||||
JDK_URL=$( /get-jdk-url.sh $jdk )
|
||||
mkdir $jdk
|
||||
|
||||
@@ -8,7 +8,4 @@ milestone: "6.0.x"
|
||||
build-name: "spring-framework"
|
||||
pipeline-name: "spring-framework"
|
||||
concourse-url: "https://ci.spring.io"
|
||||
registry-mirror-host: docker.repo.spring.io
|
||||
registry-mirror-username: ((artifactory-username))
|
||||
registry-mirror-password: ((artifactory-password))
|
||||
task-timeout: 1h00m
|
||||
|
||||
+14
-44
@@ -23,11 +23,6 @@ anchors:
|
||||
docker-resource-source: &docker-resource-source
|
||||
username: ((docker-hub-username))
|
||||
password: ((docker-hub-password))
|
||||
tag: ((milestone))
|
||||
registry-mirror-vars: ®istry-mirror-vars
|
||||
registry-mirror-host: ((registry-mirror-host))
|
||||
registry-mirror-username: ((registry-mirror-username))
|
||||
registry-mirror-password: ((registry-mirror-password))
|
||||
slack-fail-params: &slack-fail-params
|
||||
text: >
|
||||
:concourse-failed: <https://ci.spring.io/teams/${BUILD_TEAM_NAME}/pipelines/${BUILD_PIPELINE_NAME}/jobs/${BUILD_JOB_NAME}/builds/${BUILD_NAME}|${BUILD_PIPELINE_NAME} ${BUILD_JOB_NAME} failed!>
|
||||
@@ -48,31 +43,37 @@ resource_types:
|
||||
- name: registry-image
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: concourse/registry-image-resource
|
||||
tag: 1.5.0
|
||||
- name: artifactory-resource
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: springio/artifactory-resource
|
||||
tag: 0.0.17
|
||||
tag: 0.0.18
|
||||
- name: github-release
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: concourse/github-release-resource
|
||||
tag: 1.5.5
|
||||
- name: github-status-resource
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: dpb587/github-status-resource
|
||||
tag: master
|
||||
- name: pull-request
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: teliaoss/github-pr-resource
|
||||
tag: v0.23.0
|
||||
- name: slack-notification
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: cfcommunity/slack-notification-resource
|
||||
tag: latest
|
||||
resources:
|
||||
@@ -94,6 +95,7 @@ resources:
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: ((docker-hub-organization))/spring-framework-ci
|
||||
tag: ((milestone))
|
||||
- name: every-morning
|
||||
type: time
|
||||
icon: alarm
|
||||
@@ -125,14 +127,6 @@ resources:
|
||||
access_token: ((github-ci-status-token))
|
||||
branch: ((branch))
|
||||
context: build
|
||||
- name: repo-status-jdk18-build
|
||||
type: github-status-resource
|
||||
icon: eye-check-outline
|
||||
source:
|
||||
repository: ((github-repo-name))
|
||||
access_token: ((github-ci-status-token))
|
||||
branch: ((branch))
|
||||
context: jdk18-build
|
||||
- name: repo-status-jdk19-build
|
||||
type: github-status-resource
|
||||
icon: eye-check-outline
|
||||
@@ -176,7 +170,7 @@ jobs:
|
||||
image: ci-image
|
||||
vars:
|
||||
ci-image-name: ci-image
|
||||
<<: *registry-mirror-vars
|
||||
<<: *docker-resource-source
|
||||
- put: ci-image
|
||||
params:
|
||||
image: ci-image/image.tar
|
||||
@@ -237,34 +231,6 @@ jobs:
|
||||
"zip.type": "schema"
|
||||
get_params:
|
||||
threads: 8
|
||||
- name: jdk18-build
|
||||
serial: true
|
||||
public: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
- get: every-morning
|
||||
trigger: true
|
||||
- put: repo-status-jdk18-build
|
||||
params: { state: "pending", commit: "git-repo" }
|
||||
- do:
|
||||
- task: check-project
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/check-project.yml
|
||||
privileged: true
|
||||
timeout: ((task-timeout))
|
||||
params:
|
||||
TEST_TOOLCHAIN: 18
|
||||
<<: *build-project-task-params
|
||||
on_failure:
|
||||
do:
|
||||
- put: repo-status-jdk18-build
|
||||
params: { state: "failure", commit: "git-repo" }
|
||||
- put: slack-alert
|
||||
params:
|
||||
<<: *slack-fail-params
|
||||
- put: repo-status-jdk18-build
|
||||
params: { state: "success", commit: "git-repo" }
|
||||
- name: jdk19-build
|
||||
serial: true
|
||||
public: true
|
||||
@@ -365,6 +331,7 @@ jobs:
|
||||
params:
|
||||
RELEASE_TYPE: M
|
||||
<<: *github-task-params
|
||||
<<: *docker-resource-source
|
||||
- put: github-pre-release
|
||||
params:
|
||||
<<: *changelog-task-params
|
||||
@@ -403,6 +370,7 @@ jobs:
|
||||
file: git-repo/ci/tasks/promote-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: RC
|
||||
<<: *docker-resource-source
|
||||
<<: *artifactory-task-params
|
||||
- task: generate-changelog
|
||||
file: git-repo/ci/tasks/generate-changelog.yml
|
||||
@@ -447,6 +415,7 @@ jobs:
|
||||
file: git-repo/ci/tasks/promote-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: RELEASE
|
||||
<<: *docker-resource-source
|
||||
<<: *artifactory-task-params
|
||||
<<: *sonatype-task-params
|
||||
- name: create-github-release
|
||||
@@ -464,6 +433,7 @@ jobs:
|
||||
file: git-repo/ci/tasks/generate-changelog.yml
|
||||
params:
|
||||
RELEASE_TYPE: RELEASE
|
||||
<<: *docker-resource-source
|
||||
<<: *github-task-params
|
||||
- put: github-release
|
||||
params:
|
||||
@@ -471,7 +441,7 @@ jobs:
|
||||
|
||||
groups:
|
||||
- name: "builds"
|
||||
jobs: ["build", "jdk18-build", "jdk19-build"]
|
||||
jobs: ["build", "jdk19-build"]
|
||||
- name: "releases"
|
||||
jobs: ["stage-milestone", "stage-rc", "stage-release", "promote-milestone", "promote-rc", "promote-release", "create-github-release"]
|
||||
- name: "ci-images"
|
||||
|
||||
@@ -4,6 +4,6 @@ set -e
|
||||
source $(dirname $0)/common.sh
|
||||
|
||||
pushd git-repo > /dev/null
|
||||
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK18 \
|
||||
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK19 \
|
||||
-PmainToolchain=${MAIN_TOOLCHAIN} -PtestToolchain=${TEST_TOOLCHAIN} --no-daemon --max-workers=4 check
|
||||
popd > /dev/null
|
||||
|
||||
@@ -5,10 +5,8 @@ image_resource:
|
||||
source:
|
||||
repository: concourse/oci-build-task
|
||||
tag: 0.10.0
|
||||
registry_mirror:
|
||||
host: ((registry-mirror-host))
|
||||
username: ((registry-mirror-username))
|
||||
password: ((registry-mirror-password))
|
||||
username: ((docker-hub-username))
|
||||
password: ((docker-hub-password))
|
||||
inputs:
|
||||
- name: ci-images-git-repo
|
||||
outputs:
|
||||
|
||||
@@ -5,6 +5,8 @@ image_resource:
|
||||
source:
|
||||
repository: springio/github-changelog-generator
|
||||
tag: '0.0.8'
|
||||
username: ((docker-hub-username))
|
||||
password: ((docker-hub-password))
|
||||
inputs:
|
||||
- name: git-repo
|
||||
- name: artifactory-repo
|
||||
|
||||
@@ -5,6 +5,8 @@ image_resource:
|
||||
source:
|
||||
repository: springio/concourse-release-scripts
|
||||
tag: '0.3.4'
|
||||
username: ((docker-hub-username))
|
||||
password: ((docker-hub-password))
|
||||
inputs:
|
||||
- name: git-repo
|
||||
- name: artifactory-repo
|
||||
|
||||
@@ -28,13 +28,7 @@ javadoc {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
asciidoctorExtensions "io.spring.asciidoctor.backends:spring-asciidoctor-backends:0.0.3"
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url "https://repo.spring.io/release"
|
||||
}
|
||||
asciidoctorExtensions "io.spring.asciidoctor.backends:spring-asciidoctor-backends:0.0.4"
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
:chomp: default headers packages
|
||||
:fold: all
|
||||
:docs-site: https://docs.spring.io
|
||||
// Spring Framework
|
||||
:docs-spring-framework: {docs-site}/spring-framework/docs/{spring-version}
|
||||
|
||||
@@ -1100,12 +1100,15 @@ subclass is used to implement the Decorator pattern, weaving in the advice.
|
||||
CGLIB proxying should generally be transparent to users. However, there are some issues
|
||||
to consider:
|
||||
|
||||
* `Final` methods cannot be advised, as they cannot be overridden.
|
||||
* There is no need to add CGLIB to your classpath. As of Spring 3.2, CGLIB is repackaged
|
||||
and included in the spring-core JAR. In other words, CGLIB-based AOP works "`out of
|
||||
the box`", as do JDK dynamic proxies.
|
||||
* `final` classes cannot be proxied, because they cannot be extended.
|
||||
* `final` methods cannot be advised, because they cannot be overridden.
|
||||
* `private` methods cannot be advised, because they cannot be overridden.
|
||||
|
||||
There is little performance difference between CGLIB proxying and dynamic proxies.
|
||||
NOTE: There is no need to add CGLIB to your classpath. CGLIB is repackaged and included
|
||||
in the `spring-core` JAR. In other words, CGLIB-based AOP works "out of the box", as do
|
||||
JDK dynamic proxies.
|
||||
|
||||
There is little performance difference between CGLIB proxies and dynamic proxies.
|
||||
Performance should not be a decisive consideration in this case.
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ Applying such optimizations early implies the following restrictions:
|
||||
* The beans defined in your application cannot change at runtime, meaning:
|
||||
** `@Profile`, in particular profile-specific configuration needs to be chosen at build time.
|
||||
** Environment properties that impact the presence of a bean (`@Conditional`) are only considered at build time.
|
||||
* Bean definitions with instance suppliers (lambdas or method references) can't be transformed Ahead of Time (see https://github.com/spring-projects/spring-framework/issues/29555[spring-framework#29555] related issue)
|
||||
* The return type of methods annotated with `@Bean` should be the most specific one in order to allow proper hint inference (typically the concrete class, not an interface).
|
||||
|
||||
When these restrictions are in place, it becomes possible to perform ahead-of-time processing at build time and generate additional assets.
|
||||
A Spring AOT processed application typically generates:
|
||||
|
||||
@@ -524,15 +524,13 @@ container that hosts the bean. A bean usually has only one identifier. However,
|
||||
requires more than one, the extra ones can be considered aliases.
|
||||
|
||||
In XML-based configuration metadata, you use the `id` attribute, the `name` attribute, or
|
||||
both to specify the bean identifiers. The `id` attribute lets you specify
|
||||
exactly one id. Conventionally, these names are alphanumeric ('myBean',
|
||||
'someService', etc.), but they can contain special characters as well. If you want to
|
||||
introduce other aliases for the bean, you can also specify them in the `name`
|
||||
attribute, separated by a comma (`,`), semicolon (`;`), or white space. As a
|
||||
historical note, in versions prior to Spring 3.1, the `id` attribute was
|
||||
defined as an `xsd:ID` type, which constrained possible characters. As of 3.1,
|
||||
it is defined as an `xsd:string` type. Note that bean `id` uniqueness is still
|
||||
enforced by the container, though no longer by XML parsers.
|
||||
both to specify bean identifiers. The `id` attribute lets you specify exactly one `id`.
|
||||
Conventionally, these names are alphanumeric ('myBean', 'someService', etc.), but they
|
||||
can contain special characters as well. If you want to introduce other aliases for the
|
||||
bean, you can also specify them in the `name` attribute, separated by a comma (`,`),
|
||||
semicolon (`;`), or white space. Although the `id` attribute is defined as an
|
||||
`xsd:string` type, bean `id` uniqueness is enforced by the container, though not by XML
|
||||
parsers.
|
||||
|
||||
You are not required to supply a `name` or an `id` for a bean. If you do not supply a
|
||||
`name` or `id` explicitly, the container generates a unique name for that bean. However,
|
||||
@@ -2704,8 +2702,8 @@ The following table describes the supported scopes:
|
||||
the context of a web-aware Spring `ApplicationContext`.
|
||||
|===
|
||||
|
||||
NOTE: As of Spring 3.0, a thread scope is available but is not registered by default. For
|
||||
more information, see the documentation for
|
||||
NOTE: A thread scope is available but is not registered by default. For more information,
|
||||
see the documentation for
|
||||
{api-spring-framework}/context/support/SimpleThreadScope.html[`SimpleThreadScope`].
|
||||
For instructions on how to register this or any other custom scope, see
|
||||
<<beans-factory-scopes-custom-using>>.
|
||||
@@ -4590,26 +4588,24 @@ configuration becomes decentralized and harder to control.
|
||||
|
||||
No matter the choice, Spring can accommodate both styles and even mix them together.
|
||||
It is worth pointing out that through its <<beans-java, JavaConfig>> option, Spring lets
|
||||
annotations be used in a non-invasive way, without touching the target components
|
||||
source code and that, in terms of tooling, all configuration styles are supported by the
|
||||
https://spring.io/tools[Spring Tools for Eclipse].
|
||||
annotations be used in a non-invasive way, without touching the target components'
|
||||
source code and that, in terms of tooling, all configuration styles are supported by
|
||||
https://spring.io/tools[Spring Tools] for Eclipse, Visual Studio Code, and Theia.
|
||||
****
|
||||
|
||||
An alternative to XML setup is provided by annotation-based configuration, which relies
|
||||
on the bytecode metadata for wiring up components instead of angle-bracket declarations.
|
||||
Instead of using XML to describe a bean wiring, the developer moves the configuration
|
||||
into the component class itself by using annotations on the relevant class, method, or
|
||||
field declaration. As mentioned in <<beans-factory-extension-bpp-examples-aabpp>>, using
|
||||
a `BeanPostProcessor` in conjunction with annotations is a common means of extending the
|
||||
Spring IoC container. For example, Spring 2.5 introduced an annotation-based approach to
|
||||
drive Spring's dependency injection. Essentially, the <<beans-autowired-annotation,
|
||||
`@Autowired`>> annotation provides the same capabilities as described in
|
||||
<<beans-factory-autowire>> but with more fine-grained control and wider applicability.
|
||||
Spring 2.5 also added support for JSR-250 annotations, such as `@PostConstruct` and
|
||||
`@PreDestroy`. Spring 3.0 added support for JSR-330 (Dependency Injection for Java)
|
||||
annotations contained in the `jakarta.inject` package such as `@Inject` and `@Named`.
|
||||
Details about those annotations can be found in the <<beans-standard-annotations,
|
||||
relevant section>>.
|
||||
on bytecode metadata for wiring up components instead of XML declarations. Instead of
|
||||
using XML to describe a bean wiring, the developer moves the configuration into the
|
||||
component class itself by using annotations on the relevant class, method, or field
|
||||
declaration. As mentioned in <<beans-factory-extension-bpp-examples-aabpp>>, using a
|
||||
`BeanPostProcessor` in conjunction with annotations is a common means of extending the
|
||||
Spring IoC container. For example, the <<beans-autowired-annotation, `@Autowired`>>
|
||||
annotation provides the same capabilities as described in <<beans-factory-autowire>> but
|
||||
with more fine-grained control and wider applicability. In addition, Spring provides
|
||||
support for JSR-250 annotations, such as `@PostConstruct` and `@PreDestroy`, as well as
|
||||
support for JSR-330 (Dependency Injection for Java) annotations contained in the
|
||||
`jakarta.inject` package such as `@Inject` and `@Named`. Details about those annotations
|
||||
can be found in the <<beans-standard-annotations, relevant section>>.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
@@ -6237,7 +6233,7 @@ simply to be added to the application's classpath like any other library.
|
||||
Most examples in this chapter use XML to specify the configuration metadata that produces
|
||||
each `BeanDefinition` within the Spring container. The previous section
|
||||
(<<beans-annotation-config>>) demonstrates how to provide a lot of the configuration
|
||||
metadata through source-level annotations. Even in those examples, however, the "`base`"
|
||||
metadata through source-level annotations. Even in those examples, however, the "base"
|
||||
bean definitions are explicitly defined in the XML file, while the annotations drive only
|
||||
the dependency injection. This section describes an option for implicitly detecting the
|
||||
candidate components by scanning the classpath. Candidate components are classes that
|
||||
@@ -6249,10 +6245,9 @@ the container.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Starting with Spring 3.0, many features provided by the Spring JavaConfig project are
|
||||
part of the core Spring Framework. This allows you to define beans using Java rather
|
||||
than using the traditional XML files. Take a look at the `@Configuration`, `@Bean`,
|
||||
`@Import`, and `@DependsOn` annotations for examples of how to use these new features.
|
||||
You can define beans using Java rather than using XML files. Take a look at the
|
||||
`@Configuration`, `@Bean`, `@Import`, and `@DependsOn` annotations for examples of how to
|
||||
use these features.
|
||||
====
|
||||
|
||||
|
||||
@@ -7172,15 +7167,15 @@ arrangement (as though no index were present at all) by setting `spring.index.ig
|
||||
[[beans-standard-annotations]]
|
||||
== Using JSR 330 Standard Annotations
|
||||
|
||||
Starting with Spring 3.0, Spring offers support for JSR-330 standard annotations
|
||||
(Dependency Injection). Those annotations are scanned in the same way as the Spring
|
||||
annotations. To use them, you need to have the relevant jars in your classpath.
|
||||
Spring offers support for JSR-330 standard annotations (Dependency Injection). Those
|
||||
annotations are scanned in the same way as the Spring annotations. To use them, you need
|
||||
to have the relevant jars in your classpath.
|
||||
|
||||
[NOTE]
|
||||
=====
|
||||
If you use Maven, the `jakarta.inject` artifact is available in the standard Maven
|
||||
repository (
|
||||
https://repo1.maven.org/maven2/jakarta/inject/jakarta.inject-api/2.0.0/[https://repo1.maven.org/maven2/jakarta/inject/jakarta.inject-api/2.0.0/]).
|
||||
https://repo.maven.apache.org/maven2/jakarta/inject/jakarta.inject-api/2.0.0/[https://repo.maven.apache.org/maven2/jakarta/inject/jakarta.inject-api/2.0.0/]).
|
||||
You can add the following dependency to your file pom.xml:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
@@ -7562,7 +7557,7 @@ The simplest possible `@Configuration` class reads as follows:
|
||||
public class AppConfig {
|
||||
|
||||
@Bean
|
||||
public MyService myService() {
|
||||
public MyServiceImpl myService() {
|
||||
return new MyServiceImpl();
|
||||
}
|
||||
}
|
||||
@@ -7574,7 +7569,7 @@ The simplest possible `@Configuration` class reads as follows:
|
||||
class AppConfig {
|
||||
|
||||
@Bean
|
||||
fun myService(): MyService {
|
||||
fun myService(): MyServiceImpl {
|
||||
return MyServiceImpl()
|
||||
}
|
||||
}
|
||||
@@ -8611,22 +8606,24 @@ about singletons here.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
As of Spring 3.2, it is no longer necessary to add CGLIB to your classpath because CGLIB
|
||||
classes have been repackaged under `org.springframework.cglib` and included directly
|
||||
within the spring-core JAR.
|
||||
It is not necessary to add CGLIB to your classpath because CGLIB classes are repackaged
|
||||
under the `org.springframework.cglib` package and included directly within the
|
||||
`spring-core` JAR.
|
||||
====
|
||||
|
||||
[TIP]
|
||||
====
|
||||
There are a few restrictions due to the fact that CGLIB dynamically adds features at
|
||||
startup-time. In particular, configuration classes must not be final. However, as
|
||||
of 4.3, any constructors are allowed on configuration classes, including the use of
|
||||
`@Autowired` or a single non-default constructor declaration for default injection.
|
||||
startup-time. In particular, configuration classes must not be final. However, any
|
||||
constructors are allowed on configuration classes, including the use of `@Autowired` or a
|
||||
single non-default constructor declaration for default injection.
|
||||
|
||||
If you prefer to avoid any CGLIB-imposed limitations, consider declaring your `@Bean`
|
||||
methods on non-`@Configuration` classes (for example, on plain `@Component` classes instead).
|
||||
Cross-method calls between `@Bean` methods are not then intercepted, so you have
|
||||
to exclusively rely on dependency injection at the constructor or method level there.
|
||||
methods on non-`@Configuration` classes (for example, on plain `@Component` classes
|
||||
instead) or by annotating your configuration class with
|
||||
`@Configuration(proxyBeanMethods = false)`. Cross-method calls between `@Bean` methods
|
||||
are then not intercepted, so you have to exclusively rely on dependency injection at the
|
||||
constructor or method level there.
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
= Validation, Data Binding, and Type Conversion
|
||||
|
||||
There are pros and cons for considering validation as business logic, and Spring offers
|
||||
a design for validation (and data binding) that does not exclude either one of them.
|
||||
a design for validation and data binding that does not exclude either one of them.
|
||||
Specifically, validation should not be tied to the web tier and should be easy to localize,
|
||||
and it should be possible to plug in any available validator. Considering these concerns,
|
||||
Spring provides a `Validator` contract that is both basic and eminently usable
|
||||
@@ -15,18 +15,18 @@ provides the aptly named `DataBinder` to do exactly that. The `Validator` and th
|
||||
limited to the web layer.
|
||||
|
||||
The `BeanWrapper` is a fundamental concept in the Spring Framework and is used in a lot
|
||||
of places. However, you probably do not need to use the `BeanWrapper`
|
||||
directly. Because this is reference documentation, however, we felt that some explanation
|
||||
might be in order. We explain the `BeanWrapper` in this chapter, since, if you are
|
||||
going to use it at all, you are most likely do so when trying to bind data to objects.
|
||||
of places. However, you probably do not need to use the `BeanWrapper` directly. Because
|
||||
this is reference documentation, however, we feel that some explanation might be in
|
||||
order. We explain the `BeanWrapper` in this chapter, since, if you are going to use it at
|
||||
all, you are most likely do so when trying to bind data to objects.
|
||||
|
||||
Spring's `DataBinder` and the lower-level `BeanWrapper` both use `PropertyEditorSupport`
|
||||
implementations to parse and format property values. The `PropertyEditor` and
|
||||
`PropertyEditorSupport` types are part of the JavaBeans specification and are also
|
||||
explained in this chapter. Spring 3 introduced a `core.convert` package that provides a
|
||||
general type conversion facility, as well as a higher-level "`format`" package for
|
||||
formatting UI field values. You can use these packages as simpler alternatives to
|
||||
`PropertyEditorSupport` implementations. They are also discussed in this chapter.
|
||||
explained in this chapter. Spring's `core.convert` package provides a general type
|
||||
conversion facility, as well as a higher-level `format` package for formatting UI field
|
||||
values. You can use these packages as simpler alternatives to `PropertyEditorSupport`
|
||||
implementations. They are also discussed in this chapter.
|
||||
|
||||
Spring supports Java Bean Validation through setup infrastructure and an adaptor to
|
||||
Spring's own `Validator` contract. Applications can enable Bean Validation once globally,
|
||||
@@ -861,12 +861,12 @@ as needed.
|
||||
[[core-convert]]
|
||||
== Spring Type Conversion
|
||||
|
||||
Spring 3 introduced a `core.convert` package that provides a general type conversion
|
||||
system. The system defines an SPI to implement type conversion logic and an API
|
||||
to perform type conversions at runtime. Within a Spring container, you can use this system
|
||||
as an alternative to `PropertyEditor` implementations to convert externalized bean property value
|
||||
strings to the required property types. You can also use the public API anywhere in your
|
||||
application where type conversion is needed.
|
||||
The `core.convert` package provides a general type conversion system. The system defines
|
||||
an SPI to implement type conversion logic and an API to perform type conversions at
|
||||
runtime. Within a Spring container, you can use this system as an alternative to
|
||||
`PropertyEditor` implementations to convert externalized bean property value strings to
|
||||
the required property types. You can also use the public API anywhere in your application
|
||||
where type conversion is needed.
|
||||
|
||||
|
||||
|
||||
@@ -1205,8 +1205,9 @@ web or desktop application. In such environments, you typically convert from `St
|
||||
to support the client postback process, as well as back to `String` to support the
|
||||
view rendering process. In addition, you often need to localize `String` values. The more
|
||||
general `core.convert` `Converter` SPI does not address such formatting requirements
|
||||
directly. To directly address them, Spring 3 introduced a convenient `Formatter` SPI that
|
||||
provides a simple and robust alternative to `PropertyEditor` implementations for client environments.
|
||||
directly. To directly address them, Spring provides a convenient `Formatter` SPI that
|
||||
provides a simple and robust alternative to `PropertyEditor` implementations for client
|
||||
environments.
|
||||
|
||||
In general, you can use the `Converter` SPI when you need to implement general-purpose type
|
||||
conversion logic -- for example, for converting between a `java.util.Date` and a `Long`.
|
||||
@@ -1956,9 +1957,9 @@ javadoc for more information on these options.
|
||||
[[validation-binder]]
|
||||
=== Configuring a `DataBinder`
|
||||
|
||||
Since Spring 3, you can configure a `DataBinder` instance with a `Validator`. Once
|
||||
configured, you can invoke the `Validator` by calling `binder.validate()`. Any validation
|
||||
`Errors` are automatically added to the binder's `BindingResult`.
|
||||
You can configure a `DataBinder` instance with a `Validator`. Once configured, you can
|
||||
invoke the `Validator` by calling `binder.validate()`. Any validation `Errors` are
|
||||
automatically added to the binder's `BindingResult`.
|
||||
|
||||
The following example shows how to use a `DataBinder` programmatically to invoke validation
|
||||
logic after binding to a target object:
|
||||
|
||||
@@ -31,7 +31,7 @@ Brannen, Ramnivas Laddad, Arjen Poutsma, Chris Beams, Tareq Abedrabbo, Andy Clem
|
||||
Syer, Oliver Gierke, Rossen Stoyanchev, Phillip Webb, Rob Winch, Brian Clozel, Stephane
|
||||
Nicoll, Sebastien Deleuze, Jay Bryant, Mark Paluch
|
||||
|
||||
Copyright © 2002 - 2022 VMware, Inc. All Rights Reserved.
|
||||
Copyright © 2002 - 2023 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Copies of this document may be made for your own use and for distribution to others,
|
||||
provided that you do not charge any fee for such copies and further provided that each
|
||||
|
||||
@@ -67,6 +67,12 @@ HTTP server exchanges observations are created with the name `"http.server.reque
|
||||
Applications need to configure the `org.springframework.web.filter.ServerHttpObservationFilter` Servlet filter in their application.
|
||||
It is using the `org.springframework.http.server.observation.DefaultServerRequestObservationConvention` by default, backed by the `ServerRequestObservationContext`.
|
||||
|
||||
This will only record an observation as an error if the `Exception` has not been handled by the web Framework and has bubbled up to the Servlet filter.
|
||||
Typically, all exceptions handled by Spring MVC's `@ExceptionHandler` and <<web.adoc#mvc-ann-rest-exceptions,`ProblemDetail` support>> will not be recorded with the observation.
|
||||
You can, at any point during request processing, set the error field on the `ObservationContext` yourself:
|
||||
|
||||
include::code:UserController[]
|
||||
|
||||
By default, the following `KeyValues` are created:
|
||||
|
||||
.Low cardinality Keys
|
||||
@@ -94,6 +100,12 @@ By default, the following `KeyValues` are created:
|
||||
Applications need to configure the `org.springframework.web.filter.reactive.ServerHttpObservationFilter` reactive `WebFilter` in their application.
|
||||
It is using the `org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention` by default, backed by the `ServerRequestObservationContext`.
|
||||
|
||||
This will only record an observation as an error if the `Exception` has not been handled by the web Framework and has bubbled up to the `WebFilter`.
|
||||
Typically, all exceptions handled by Spring WebFlux's `@ExceptionHandler` and <<web.adoc#webflux-ann-rest-exceptions,`ProblemDetail` support>> will not be recorded with the observation.
|
||||
You can, at any point during request processing, set the error field on the `ObservationContext` yourself:
|
||||
|
||||
include::code:UserController[]
|
||||
|
||||
By default, the following `KeyValues` are created:
|
||||
|
||||
.Low cardinality Keys
|
||||
@@ -125,24 +137,27 @@ Unlike their server counterparts, the instrumentation is implemented directly in
|
||||
[[integration.observability.http-client.resttemplate]]
|
||||
=== RestTemplate
|
||||
|
||||
Applications must configure an `ObservationRegistry` on `RestTemplate` instances to enable the instrumentation; without that, observations are "no-ops".
|
||||
Spring Boot will auto-configure `RestTemplateBuilder` beans with the observation registry already set.
|
||||
|
||||
Instrumentation is using the `org.springframework.http.client.observation.ClientRequestObservationConvention` by default, backed by the `ClientRequestObservationContext`.
|
||||
|
||||
.Low cardinality Keys
|
||||
[cols="a,a"]
|
||||
|===
|
||||
|Name | Description
|
||||
|`exception` _(required)_|Name of the exception thrown during the exchange, or `"none"` if no exception happened.
|
||||
|`method` _(required)_|Name of HTTP request method or `"none"` if the request could not be created.
|
||||
|`outcome` _(required)_|Outcome of the HTTP client exchange.
|
||||
|`uri` _(required)_|URI template used for HTTP request, or `"none"` if none was provided. Only the path part of the URI is considered.
|
||||
|`client.name` _(required)_|Client name derived from the request URI host.
|
||||
|`status` _(required)_|HTTP response raw status code, or `"IO_ERROR"` in case of `IOException`, or `"CLIENT_ERROR"` if no response was received.
|
||||
|`uri` _(required)_|URI template used for HTTP request, or `"none"` if none was provided.
|
||||
|`outcome` _(required)_|Outcome of the HTTP client exchange.
|
||||
|`exception` _(required)_|Name of the exception thrown during the exchange, or `"none"` if no exception happened.
|
||||
|===
|
||||
|
||||
.High cardinality Keys
|
||||
[cols="a,a"]
|
||||
|===
|
||||
|Name | Description
|
||||
|`client.name` _(required)_|Client name derived from the request URI host.
|
||||
|`http.url` _(required)_|HTTP request URI.
|
||||
|===
|
||||
|
||||
@@ -151,24 +166,27 @@ Instrumentation is using the `org.springframework.http.client.observation.Client
|
||||
[[integration.observability.http-client.webclient]]
|
||||
=== WebClient
|
||||
|
||||
Applications must configure an `ObservationRegistry` on the `WebClient` builder to enable the instrumentation; without that, observations are "no-ops".
|
||||
Spring Boot will auto-configure `WebClient.Builder` beans with the observation registry already set.
|
||||
|
||||
Instrumentation is using the `org.springframework.web.reactive.function.client.ClientRequestObservationConvention` by default, backed by the `ClientRequestObservationContext`.
|
||||
|
||||
.Low cardinality Keys
|
||||
[cols="a,a"]
|
||||
|===
|
||||
|Name | Description
|
||||
|`exception` _(required)_|Name of the exception thrown during the exchange, or `"none"` if no exception happened.
|
||||
|`method` _(required)_|Name of HTTP request method or `"none"` if the request could not be created.
|
||||
|`outcome` _(required)_|Outcome of the HTTP client exchange.
|
||||
|`uri` _(required)_|URI template used for HTTP request, or `"none"` if none was provided. Only the path part of the URI is considered.
|
||||
|`client.name` _(required)_|Client name derived from the request URI host.
|
||||
|`status` _(required)_|HTTP response raw status code, or `"IO_ERROR"` in case of `IOException`, or `"CLIENT_ERROR"` if no response was received.
|
||||
|`uri` _(required)_|URI template used for HTTP request, or `"none"` if none was provided.
|
||||
|`outcome` _(required)_|Outcome of the HTTP client exchange.
|
||||
|`exception` _(required)_|Name of the exception thrown during the exchange, or `"none"` if no exception happened.
|
||||
|===
|
||||
|
||||
.High cardinality Keys
|
||||
[cols="a,a"]
|
||||
|===
|
||||
|Name | Description
|
||||
|`client.name` _(required)_|Client name derived from the request URI host.
|
||||
|`http.url` _(required)_|HTTP request URI.
|
||||
|===
|
||||
|
||||
|
||||
@@ -117,6 +117,9 @@ TIP: Note that the `java.net` implementation for HTTP requests can raise an exce
|
||||
accessing the status of a response that represents an error (such as 401). If this is an
|
||||
issue, switch to another HTTP client library.
|
||||
|
||||
NOTE: `RestTemplate` can be instrumented for observability, in order to produce metrics and traces.
|
||||
See the <<integration.adoc#integration.observability.http-client.resttemplate,RestTemplate Observability support>> section.
|
||||
|
||||
[[rest-resttemplate-uri]]
|
||||
==== URIs
|
||||
|
||||
|
||||
@@ -136,14 +136,16 @@ To configure the rules that the `TaskExecutor` uses, we expose simple bean prope
|
||||
[[scheduling-task-scheduler]]
|
||||
== The Spring `TaskScheduler` Abstraction
|
||||
|
||||
In addition to the `TaskExecutor` abstraction, Spring 3.0 introduced a `TaskScheduler`
|
||||
with a variety of methods for scheduling tasks to run at some point in the future.
|
||||
The following listing shows the `TaskScheduler` interface definition:
|
||||
In addition to the `TaskExecutor` abstraction, Spring has a `TaskScheduler` SPI with a
|
||||
variety of methods for scheduling tasks to run at some point in the future. The following
|
||||
listing shows the `TaskScheduler` interface definition:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
public interface TaskScheduler {
|
||||
|
||||
Clock getClock();
|
||||
|
||||
ScheduledFuture schedule(Runnable task, Trigger trigger);
|
||||
|
||||
ScheduledFuture schedule(Runnable task, Instant startTime);
|
||||
@@ -168,12 +170,11 @@ much more flexible.
|
||||
[[scheduling-trigger-interface]]
|
||||
=== `Trigger` Interface
|
||||
|
||||
The `Trigger` interface is essentially inspired by JSR-236 which, as of Spring 3.0,
|
||||
was not yet officially implemented. The basic idea of the `Trigger` is that execution
|
||||
times may be determined based on past execution outcomes or even arbitrary conditions.
|
||||
If these determinations take into account the outcome of the preceding execution,
|
||||
that information is available within a `TriggerContext`. The `Trigger` interface itself
|
||||
is quite simple, as the following listing shows:
|
||||
The `Trigger` interface is essentially inspired by JSR-236. The basic idea of the
|
||||
`Trigger` is that execution times may be determined based on past execution outcomes or
|
||||
even arbitrary conditions. If these determinations take into account the outcome of the
|
||||
preceding execution, that information is available within a `TriggerContext`. The
|
||||
`Trigger` interface itself is quite simple, as the following listing shows:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -192,6 +193,8 @@ default). The following listing shows the available methods for `Trigger` implem
|
||||
----
|
||||
public interface TriggerContext {
|
||||
|
||||
Clock getClock();
|
||||
|
||||
Instant lastScheduledExecution();
|
||||
|
||||
Instant lastActualExecution();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
:noheader:
|
||||
:toc:
|
||||
:toclevels: 4
|
||||
:tabsize: 4
|
||||
include::attributes.adoc[]
|
||||
= Spring Framework Documentation
|
||||
Rod Johnson; Juergen Hoeller; Keith Donald; Colin Sampaleanu; Rob Harrop; Thomas Risberg; Alef Arendsen; Darren Davison; Dmitriy Kopylenko; Mark Pollack; Thierry Templier; Erwin Vervaet; Portia Tung; Ben Hale; Adrian Colyer; John Lewis; Costin Leau; Mark Fisher; Sam Brannen; Ramnivas Laddad; Arjen Poutsma; Chris Beams; Tareq Abedrabbo; Andy Clement; Dave Syer; Oliver Gierke; Rossen Stoyanchev; Phillip Webb; Rob Winch; Brian Clozel; Stephane Nicoll; Sebastien Deleuze; Jay Bryant; Mark Paluch
|
||||
@@ -9,7 +11,7 @@ NOTE: This documentation is also available in {docs-spring-framework}/reference/
|
||||
[[legal]]
|
||||
== Legal
|
||||
|
||||
Copyright © 2002 - 2022 VMware, Inc. All Rights Reserved.
|
||||
Copyright © 2002 - 2023 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
|
||||
|
||||
|
||||
@@ -2022,12 +2022,13 @@ properties.
|
||||
class ExampleIntegrationTests {
|
||||
|
||||
@Container
|
||||
static RedisContainer redis = new RedisContainer();
|
||||
static GenericContainer redis =
|
||||
new GenericContainer("redis:5.0.3-alpine").withExposedPorts(6379);
|
||||
|
||||
@DynamicPropertySource
|
||||
static void redisProperties(DynamicPropertyRegistry registry) {
|
||||
registry.add("redis.host", redis::getHost);
|
||||
registry.add("redis.port", redis::getMappedPort);
|
||||
registry.add("redis.port", redis::getFirstMappedPort);
|
||||
}
|
||||
|
||||
// tests ...
|
||||
@@ -2045,13 +2046,14 @@ properties.
|
||||
|
||||
@Container
|
||||
@JvmStatic
|
||||
val redis: RedisContainer = RedisContainer()
|
||||
val redis: GenericContainer =
|
||||
GenericContainer("redis:5.0.3-alpine").withExposedPorts(6379)
|
||||
|
||||
@DynamicPropertySource
|
||||
@JvmStatic
|
||||
fun redisProperties(registry: DynamicPropertyRegistry) {
|
||||
registry.add("redis.host", redis::getHost)
|
||||
registry.add("redis.port", redis::getMappedPort)
|
||||
registry.add("redis.port", redis::getFirstMappedPort)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ You can also use `WebClient.builder()` with further options:
|
||||
* `filter`: Client filter for every request.
|
||||
* `exchangeStrategies`: HTTP message reader/writer customizations.
|
||||
* `clientConnector`: HTTP client library settings.
|
||||
* `observationRegistry`: the registry to use for enabling <<integration.adoc#integration.observability.http-client.webclient, Observability support>>.
|
||||
* `observationConvention`: <<integration.adoc#integration.observability.config,an optional, custom convention to extract metadata>> for recorded observations.
|
||||
|
||||
For example:
|
||||
|
||||
|
||||
@@ -613,8 +613,8 @@ The `DefaultServerWebExchange` uses the configured `HttpMessageReader` to parse
|
||||
----
|
||||
|
||||
The `DefaultServerWebExchange` uses the configured
|
||||
`HttpMessageReader<MultiValueMap<String, Part>>` to parse `multipart/form-data` content
|
||||
into a `MultiValueMap`.
|
||||
`HttpMessageReader<MultiValueMap<String, Part>>` to parse `multipart/form-data`,
|
||||
`multipart/mixed`, and `multipart/related` content into a `MultiValueMap`.
|
||||
By default, this is the `DefaultPartHttpMessageReader`, which does not have any third-party
|
||||
dependencies.
|
||||
Alternatively, the `SynchronossPartHttpMessageReader` can be used, which is based on the
|
||||
@@ -805,9 +805,9 @@ consistently for access to the cached form data versus reading from the raw requ
|
||||
==== Multipart
|
||||
|
||||
`MultipartHttpMessageReader` and `MultipartHttpMessageWriter` support decoding and
|
||||
encoding "multipart/form-data" content. In turn `MultipartHttpMessageReader` delegates to
|
||||
another `HttpMessageReader` for the actual parsing to a `Flux<Part>` and then simply
|
||||
collects the parts into a `MultiValueMap`.
|
||||
encoding "multipart/form-data", "multipart/mixed", and "multipart/related" content.
|
||||
In turn `MultipartHttpMessageReader` delegates to another `HttpMessageReader`
|
||||
for the actual parsing to a `Flux<Part>` and then simply collects the parts into a `MultiValueMap`.
|
||||
By default, the `DefaultPartHttpMessageReader` is used, but this can be changed through the
|
||||
`ServerCodecConfigurer`.
|
||||
For more information about the `DefaultPartHttpMessageReader`, refer to the
|
||||
|
||||
@@ -1649,138 +1649,6 @@ is the default type.
|
||||
|
||||
|
||||
|
||||
[[mvc-view-tiles]]
|
||||
== Tiles
|
||||
|
||||
You can integrate Tiles - just as any other view technology - in web
|
||||
applications that use Spring. This section describes, in a broad way, how to do so.
|
||||
|
||||
NOTE: This section focuses on Spring's support for Tiles version 3 in the
|
||||
`org.springframework.web.servlet.view.tiles3` package.
|
||||
|
||||
|
||||
|
||||
[[mvc-view-tiles-dependencies]]
|
||||
=== Dependencies
|
||||
|
||||
To be able to use Tiles, you have to add a dependency on Tiles version 3.0.1 or higher
|
||||
and https://tiles.apache.org/framework/dependency-management.html[its transitive dependencies]
|
||||
to your project.
|
||||
|
||||
|
||||
|
||||
[[mvc-view-tiles-integrate]]
|
||||
=== Configuration
|
||||
|
||||
To be able to use Tiles, you have to configure it by using files that contain definitions
|
||||
(for basic information on definitions and other Tiles concepts, see
|
||||
https://tiles.apache.org[]). In Spring, this is done by using the `TilesConfigurer`.
|
||||
The following example `ApplicationContext` configuration shows how to do so:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
|
||||
<property name="definitions">
|
||||
<list>
|
||||
<value>/WEB-INF/defs/general.xml</value>
|
||||
<value>/WEB-INF/defs/widgets.xml</value>
|
||||
<value>/WEB-INF/defs/administrator.xml</value>
|
||||
<value>/WEB-INF/defs/customer.xml</value>
|
||||
<value>/WEB-INF/defs/templates.xml</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
|
||||
The preceding example defines five files that contain definitions. The files are all
|
||||
located in the `WEB-INF/defs` directory. At initialization of the `WebApplicationContext`,
|
||||
the files are loaded, and the definitions factory are initialized. After that has
|
||||
been done, the Tiles included in the definition files can be used as views within your
|
||||
Spring web application. To be able to use the views, you have to have a `ViewResolver`
|
||||
as with any other view technology in Spring: typically a convenient `TilesViewResolver`.
|
||||
|
||||
You can specify locale-specific Tiles definitions by adding an underscore and then
|
||||
the locale, as the following example shows:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
|
||||
<property name="definitions">
|
||||
<list>
|
||||
<value>/WEB-INF/defs/tiles.xml</value>
|
||||
<value>/WEB-INF/defs/tiles_fr_FR.xml</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
|
||||
With the preceding configuration, `tiles_fr_FR.xml` is used for requests with the `fr_FR` locale,
|
||||
and `tiles.xml` is used by default.
|
||||
|
||||
NOTE: Since underscores are used to indicate locales, we recommended not using
|
||||
them otherwise in the file names for Tiles definitions.
|
||||
|
||||
|
||||
|
||||
[[mvc-view-tiles-url]]
|
||||
==== `UrlBasedViewResolver`
|
||||
|
||||
The `UrlBasedViewResolver` instantiates the given `viewClass` for each view it has to
|
||||
resolve. The following bean defines a `UrlBasedViewResolver`:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
|
||||
<property name="viewClass" value="org.springframework.web.servlet.view.tiles3.TilesView"/>
|
||||
</bean>
|
||||
----
|
||||
|
||||
|
||||
[[mvc-view-tiles-preparer]]
|
||||
==== `SimpleSpringPreparerFactory` and `SpringBeanPreparerFactory`
|
||||
|
||||
As an advanced feature, Spring also supports two special Tiles `PreparerFactory`
|
||||
implementations. See the Tiles documentation for details on how to use
|
||||
`ViewPreparer` references in your Tiles definition files.
|
||||
|
||||
You can specify `SimpleSpringPreparerFactory` to autowire `ViewPreparer` instances based on
|
||||
specified preparer classes, applying Spring's container callbacks as well as applying
|
||||
configured Spring BeanPostProcessors. If Spring's context-wide annotation configuration has
|
||||
been activated, annotations in `ViewPreparer` classes are automatically detected and
|
||||
applied. Note that this expects preparer classes in the Tiles definition files, as
|
||||
the default `PreparerFactory` does.
|
||||
|
||||
You can specify `SpringBeanPreparerFactory` to operate on specified preparer names (instead
|
||||
of classes), obtaining the corresponding Spring bean from the DispatcherServlet's
|
||||
application context. The full bean creation process is in the control of the Spring
|
||||
application context in this case, allowing for the use of explicit dependency injection
|
||||
configuration, scoped beans, and so on. Note that you need to define one Spring bean definition
|
||||
for each preparer name (as used in your Tiles definitions). The following example shows
|
||||
how to define a `SpringBeanPreparerFactory` property on a `TilesConfigurer` bean:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
|
||||
<property name="definitions">
|
||||
<list>
|
||||
<value>/WEB-INF/defs/general.xml</value>
|
||||
<value>/WEB-INF/defs/widgets.xml</value>
|
||||
<value>/WEB-INF/defs/administrator.xml</value>
|
||||
<value>/WEB-INF/defs/customer.xml</value>
|
||||
<value>/WEB-INF/defs/templates.xml</value>
|
||||
</list>
|
||||
</property>
|
||||
|
||||
<!-- resolving preparer names as Spring bean definition names -->
|
||||
<property name="preparerFactoryClass"
|
||||
value="org.springframework.web.servlet.view.tiles3.SpringBeanPreparerFactory"/>
|
||||
|
||||
</bean>
|
||||
----
|
||||
|
||||
|
||||
|
||||
|
||||
[[mvc-view-feeds]]
|
||||
== RSS and Atom
|
||||
|
||||
|
||||
@@ -802,8 +802,8 @@ The following table provides more details on the `ViewResolver` hierarchy:
|
||||
|
||||
| `InternalResourceViewResolver`
|
||||
| Convenient subclass of `UrlBasedViewResolver` that supports `InternalResourceView` (in
|
||||
effect, Servlets and JSPs) and subclasses such as `JstlView` and `TilesView`. You can
|
||||
specify the view class for all views generated by this resolver by using `setViewClass(..)`.
|
||||
effect, Servlets and JSPs) and subclasses such as `JstlView`. You can specify the view
|
||||
class for all views generated by this resolver by using `setViewClass(..)`.
|
||||
See the {api-spring-framework}/web/reactive/result/view/UrlBasedViewResolver.html[`UrlBasedViewResolver`]
|
||||
javadoc for details.
|
||||
|
||||
@@ -4777,7 +4777,7 @@ directly. For example:
|
||||
ContextSnapshot snapshot = ContextSnapshot.captureAll();
|
||||
|
||||
// On a different thread: restore ThreadLocal values
|
||||
try (ContextSnapshot.Scope scoped = snapshot.setThreadLocals()) {
|
||||
try (ContextSnapshot.Scope scope = snapshot.setThreadLocals()) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
@@ -5888,7 +5888,7 @@ The following example shows how to achieve the same configuration in XML:
|
||||
</mvc:view-resolvers>
|
||||
----
|
||||
|
||||
Note, however, that FreeMarker, Tiles, Groovy Markup, and script templates also require
|
||||
Note, however, that FreeMarker, Groovy Markup, and script templates also require
|
||||
configuration of the underlying view technology.
|
||||
|
||||
The MVC namespace provides dedicated elements. The following example works with FreeMarker:
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,6 +30,8 @@ public class AotProcessingSample {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.register(MyApplication.class);
|
||||
context.refreshForAotProcessing(hints);
|
||||
// ...
|
||||
context.close();
|
||||
// end::aotcontext[]
|
||||
}
|
||||
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.docs.integration.observability.httpserver.reactive;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.filter.reactive.ServerHttpObservationFilter;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
@Controller
|
||||
public class UserController {
|
||||
|
||||
@ExceptionHandler(MissingUserException.class)
|
||||
ResponseEntity<Void> handleMissingUser(ServerWebExchange exchange, MissingUserException exception) {
|
||||
// We want to record this exception with the observation
|
||||
ServerHttpObservationFilter.findObservationContext(exchange)
|
||||
.ifPresent(context -> context.setError(exception));
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
// @fold:on
|
||||
@SuppressWarnings("serial")
|
||||
static class MissingUserException extends RuntimeException {
|
||||
}
|
||||
// @fold:off
|
||||
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.docs.integration.observability.httpserver.servlet;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.filter.ServerHttpObservationFilter;
|
||||
|
||||
@Controller
|
||||
public class UserController {
|
||||
|
||||
@ExceptionHandler(MissingUserException.class)
|
||||
ResponseEntity<Void> handleMissingUser(HttpServletRequest request, MissingUserException exception) {
|
||||
// We want to record this exception with the observation
|
||||
ServerHttpObservationFilter.findObservationContext(request)
|
||||
.ifPresent(context -> context.setError(exception));
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
// @fold:on
|
||||
@SuppressWarnings("serial")
|
||||
static class MissingUserException extends RuntimeException {
|
||||
}
|
||||
// @fold:off
|
||||
|
||||
}
|
||||
@@ -7,23 +7,23 @@ javaPlatform {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(platform("com.fasterxml.jackson:jackson-bom:2.14.1"))
|
||||
api(platform("io.micrometer:micrometer-bom:1.10.3"))
|
||||
api(platform("io.netty:netty-bom:4.1.86.Final"))
|
||||
api(platform("com.fasterxml.jackson:jackson-bom:2.14.2"))
|
||||
api(platform("io.micrometer:micrometer-bom:1.10.4"))
|
||||
api(platform("io.netty:netty-bom:4.1.89.Final"))
|
||||
api(platform("io.netty:netty5-bom:5.0.0.Alpha5"))
|
||||
api(platform("io.projectreactor:reactor-bom:2022.0.2"))
|
||||
api(platform("io.projectreactor:reactor-bom:2022.0.3"))
|
||||
api(platform("io.rsocket:rsocket-bom:1.1.3"))
|
||||
api(platform("org.apache.groovy:groovy-bom:4.0.6"))
|
||||
api(platform("org.apache.groovy:groovy-bom:4.0.8"))
|
||||
api(platform("org.apache.logging.log4j:log4j-bom:2.19.0"))
|
||||
api(platform("org.eclipse.jetty:jetty-bom:11.0.13"))
|
||||
api(platform("org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.4"))
|
||||
api(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:1.4.0"))
|
||||
api(platform("org.junit:junit-bom:5.9.2"))
|
||||
api(platform("org.mockito:mockito-bom:4.9.0")) // spring-beans tests fail with 4.10+
|
||||
api(platform("org.mockito:mockito-bom:5.1.1"))
|
||||
|
||||
constraints {
|
||||
api("com.fasterxml:aalto-xml:1.3.1")
|
||||
api("com.fasterxml.woodstox:woodstox-core:6.4.0")
|
||||
api("com.fasterxml.woodstox:woodstox-core:6.5.0")
|
||||
api("com.github.ben-manes.caffeine:caffeine:3.1.2")
|
||||
api("com.github.librepdf:openpdf:1.3.30")
|
||||
api("com.google.code.findbugs:findbugs:3.0.1")
|
||||
@@ -55,9 +55,9 @@ dependencies {
|
||||
api("io.r2dbc:r2dbc-spi:1.0.0.RELEASE")
|
||||
api("io.reactivex.rxjava3:rxjava:3.1.5")
|
||||
api("io.smallrye.reactive:mutiny:1.8.0")
|
||||
api("io.undertow:undertow-core:2.3.2.Final")
|
||||
api("io.undertow:undertow-servlet:2.3.2.Final")
|
||||
api("io.undertow:undertow-websockets-jsr:2.3.2.Final")
|
||||
api("io.undertow:undertow-core:2.3.3.Final")
|
||||
api("io.undertow:undertow-servlet:2.3.3.Final")
|
||||
api("io.undertow:undertow-websockets-jsr:2.3.3.Final")
|
||||
api("io.vavr:vavr:0.10.4")
|
||||
api("jakarta.activation:jakarta.activation-api:2.0.1")
|
||||
api("jakarta.annotation:jakarta.annotation-api:2.0.0")
|
||||
@@ -87,7 +87,7 @@ dependencies {
|
||||
api("jaxen:jaxen:1.2.0")
|
||||
api("junit:junit:4.13.2")
|
||||
api("net.sf.jopt-simple:jopt-simple:5.0.4")
|
||||
api("net.sourceforge.htmlunit:htmlunit:2.69.0")
|
||||
api("net.sourceforge.htmlunit:htmlunit:2.70.0")
|
||||
api("org.apache-extras.beanshell:bsh:2.0b6")
|
||||
api("org.apache.activemq:activemq-broker:5.16.2")
|
||||
api("org.apache.activemq:activemq-kahadb-store:5.16.2")
|
||||
@@ -97,16 +97,16 @@ dependencies {
|
||||
api("org.apache.derby:derbyclient:10.16.1.1")
|
||||
api("org.apache.derby:derbytools:10.16.1.1")
|
||||
api("org.apache.httpcomponents.client5:httpclient5:5.2.1")
|
||||
api("org.apache.httpcomponents.core5:httpcore5-reactive:5.2")
|
||||
api("org.apache.httpcomponents.core5:httpcore5-reactive:5.2.1")
|
||||
api("org.apache.poi:poi-ooxml:5.2.3")
|
||||
api("org.apache.tomcat.embed:tomcat-embed-core:10.1.4")
|
||||
api("org.apache.tomcat.embed:tomcat-embed-websocket:10.1.4")
|
||||
api("org.apache.tomcat:tomcat-util:10.1.4")
|
||||
api("org.apache.tomcat:tomcat-websocket:10.1.4")
|
||||
api("org.apache.tomcat.embed:tomcat-embed-core:10.1.5")
|
||||
api("org.apache.tomcat.embed:tomcat-embed-websocket:10.1.5")
|
||||
api("org.apache.tomcat:tomcat-util:10.1.5")
|
||||
api("org.apache.tomcat:tomcat-websocket:10.1.5")
|
||||
api("org.aspectj:aspectjrt:1.9.9.1")
|
||||
api("org.aspectj:aspectjtools:1.9.9.1")
|
||||
api("org.aspectj:aspectjweaver:1.9.9.1")
|
||||
api("org.assertj:assertj-core:3.24.1")
|
||||
api("org.assertj:assertj-core:3.24.2")
|
||||
api("org.awaitility:awaitility:3.1.6")
|
||||
api("org.bouncycastle:bcpkix-jdk18on:1.71")
|
||||
api("org.codehaus.jettison:jettison:1.3.8")
|
||||
@@ -116,7 +116,7 @@ dependencies {
|
||||
api("org.eclipse:yasson:2.0.4")
|
||||
api("org.ehcache:ehcache:3.4.0")
|
||||
api("org.ehcache:jcache:1.0.1")
|
||||
api("org.freemarker:freemarker:2.3.31")
|
||||
api("org.freemarker:freemarker:2.3.32")
|
||||
// Substitute for "javax.management:jmxremote_optional:1.0.1_04" which
|
||||
// is not available on Maven Central
|
||||
api("org.glassfish.external:opendmk_jmxremote_optional_jar:1.0-b01-ea")
|
||||
@@ -124,7 +124,7 @@ dependencies {
|
||||
api("org.glassfish:jakarta.el:4.0.2")
|
||||
api("org.graalvm.sdk:graal-sdk:22.3.0")
|
||||
api("org.hamcrest:hamcrest:2.2")
|
||||
api("org.hibernate:hibernate-core-jakarta:5.6.14.Final")
|
||||
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.1")
|
||||
api("org.javamoney:moneta:1.4.2")
|
||||
@@ -134,15 +134,15 @@ dependencies {
|
||||
api("org.ogce:xpp3:1.1.6")
|
||||
api("org.python:jython-standalone:2.7.1")
|
||||
api("org.quartz-scheduler:quartz:2.3.2")
|
||||
api("org.seleniumhq.selenium:htmlunit-driver:2.67.0")
|
||||
api("org.seleniumhq.selenium:htmlunit-driver:2.70.0")
|
||||
api("org.seleniumhq.selenium:selenium-java:3.141.59")
|
||||
api("org.skyscreamer:jsonassert:1.5.0")
|
||||
api("org.slf4j:slf4j-api:2.0.6")
|
||||
api("org.testng:testng:7.6.1")
|
||||
api("org.testng:testng:7.7.1")
|
||||
api("org.webjars:underscorejs:1.8.3")
|
||||
api("org.webjars:webjars-locator-core:0.52")
|
||||
api("org.xmlunit:xmlunit-assertj:2.9.0")
|
||||
api("org.xmlunit:xmlunit-matchers:2.9.0")
|
||||
api("org.xmlunit:xmlunit-assertj:2.9.1")
|
||||
api("org.xmlunit:xmlunit-matchers:2.9.1")
|
||||
api("org.yaml:snakeyaml:1.33")
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
version=6.0.4-SNAPSHOT
|
||||
version=6.0.5
|
||||
|
||||
org.gradle.caching=true
|
||||
org.gradle.jvmargs=-Xmx2048m
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
* One can choose the toolchain to use for compiling the MAIN sources and/or compiling
|
||||
* and running the TEST sources. These options apply to Java, Kotlin and Groovy sources
|
||||
* when available.
|
||||
* {@code "./gradlew check -PmainToolchain=17 -PtestToolchain=18"} will use:
|
||||
* {@code "./gradlew check -PmainToolchain=17 -PtestToolchain=19"} will use:
|
||||
* <ul>
|
||||
* <li>a JDK17 toolchain for compiling the main SourceSet
|
||||
* <li>a JDK18 toolchain for compiling and running the test SourceSet
|
||||
* <li>a JDK19 toolchain for compiling and running the test SourceSet
|
||||
* </ul>
|
||||
*
|
||||
* By default, the build will fall back to using the current JDK and 17 language level for all sourceSets.
|
||||
@@ -23,9 +23,9 @@
|
||||
* {@code
|
||||
* $ echo JDK17
|
||||
* /opt/openjdk/java17
|
||||
* $ echo JDK18
|
||||
* $ echo JDK19
|
||||
* /opt/openjdk/java18
|
||||
* $ ./gradlew -Porg.gradle.java.installations.fromEnv=JDK17,JDK18 check
|
||||
* $ ./gradlew -Porg.gradle.java.installations.fromEnv=JDK17,JDK19 check
|
||||
* }
|
||||
*
|
||||
* @author Brian Clozel
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -151,7 +151,7 @@ class ScheduledAndTransactionalAnnotationIntegrationTests {
|
||||
|
||||
@Bean
|
||||
PersistenceExceptionTranslator peTranslator() {
|
||||
return mock(PersistenceExceptionTranslator.class);
|
||||
return mock();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "com.gradle.enterprise" version "3.12.1"
|
||||
id "com.gradle.enterprise" version "3.12.3"
|
||||
id "io.spring.ge.conventions" version "0.0.13"
|
||||
}
|
||||
|
||||
|
||||
+11
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -268,18 +268,16 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
this.argumentNames[i] + "' that is not a valid Java identifier");
|
||||
}
|
||||
}
|
||||
if (this.argumentNames != null) {
|
||||
if (this.aspectJAdviceMethod.getParameterCount() == this.argumentNames.length + 1) {
|
||||
// May need to add implicit join point arg name...
|
||||
Class<?> firstArgType = this.aspectJAdviceMethod.getParameterTypes()[0];
|
||||
if (firstArgType == JoinPoint.class ||
|
||||
firstArgType == ProceedingJoinPoint.class ||
|
||||
firstArgType == JoinPoint.StaticPart.class) {
|
||||
String[] oldNames = this.argumentNames;
|
||||
this.argumentNames = new String[oldNames.length + 1];
|
||||
this.argumentNames[0] = "THIS_JOIN_POINT";
|
||||
System.arraycopy(oldNames, 0, this.argumentNames, 1, oldNames.length);
|
||||
}
|
||||
if (this.aspectJAdviceMethod.getParameterCount() == this.argumentNames.length + 1) {
|
||||
// May need to add implicit join point arg name...
|
||||
Class<?> firstArgType = this.aspectJAdviceMethod.getParameterTypes()[0];
|
||||
if (firstArgType == JoinPoint.class ||
|
||||
firstArgType == ProceedingJoinPoint.class ||
|
||||
firstArgType == JoinPoint.StaticPart.class) {
|
||||
String[] oldNames = this.argumentNames;
|
||||
this.argumentNames = new String[oldNames.length + 1];
|
||||
this.argumentNames[0] = "THIS_JOIN_POINT";
|
||||
System.arraycopy(oldNames, 0, this.argumentNames, 1, oldNames.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-23
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -244,31 +244,18 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
int algorithmicStep = STEP_JOIN_POINT_BINDING;
|
||||
while ((this.numberOfRemainingUnboundArguments > 0) && algorithmicStep < STEP_FINISHED) {
|
||||
switch (algorithmicStep++) {
|
||||
case STEP_JOIN_POINT_BINDING:
|
||||
case STEP_JOIN_POINT_BINDING -> {
|
||||
if (!maybeBindThisJoinPoint()) {
|
||||
maybeBindThisJoinPointStaticPart();
|
||||
}
|
||||
break;
|
||||
case STEP_THROWING_BINDING:
|
||||
maybeBindThrowingVariable();
|
||||
break;
|
||||
case STEP_ANNOTATION_BINDING:
|
||||
maybeBindAnnotationsFromPointcutExpression();
|
||||
break;
|
||||
case STEP_RETURNING_BINDING:
|
||||
maybeBindReturningVariable();
|
||||
break;
|
||||
case STEP_PRIMITIVE_ARGS_BINDING:
|
||||
maybeBindPrimitiveArgsFromPointcutExpression();
|
||||
break;
|
||||
case STEP_THIS_TARGET_ARGS_BINDING:
|
||||
maybeBindThisOrTargetOrArgsFromPointcutExpression();
|
||||
break;
|
||||
case STEP_REFERENCE_PCUT_BINDING:
|
||||
maybeBindReferencePointcutParameter();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown algorithmic step: " + (algorithmicStep - 1));
|
||||
}
|
||||
case STEP_THROWING_BINDING -> maybeBindThrowingVariable();
|
||||
case STEP_ANNOTATION_BINDING -> maybeBindAnnotationsFromPointcutExpression();
|
||||
case STEP_RETURNING_BINDING -> maybeBindReturningVariable();
|
||||
case STEP_PRIMITIVE_ARGS_BINDING -> maybeBindPrimitiveArgsFromPointcutExpression();
|
||||
case STEP_THIS_TARGET_ARGS_BINDING -> maybeBindThisOrTargetOrArgsFromPointcutExpression();
|
||||
case STEP_REFERENCE_PCUT_BINDING -> maybeBindReferencePointcutParameter();
|
||||
default -> throw new IllegalStateException("Unknown algorithmic step: " + (algorithmicStep - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,6 @@ import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
@@ -52,6 +51,7 @@ import org.springframework.lang.Nullable;
|
||||
* @author Rod Johnson
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFactory {
|
||||
@@ -101,14 +101,6 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
|
||||
@Override
|
||||
public void validate(Class<?> aspectClass) throws AopConfigException {
|
||||
// If the parent has the annotation and isn't abstract it's an error
|
||||
Class<?> superclass = aspectClass.getSuperclass();
|
||||
if (superclass.getAnnotation(Aspect.class) != null &&
|
||||
!Modifier.isAbstract(superclass.getModifiers())) {
|
||||
throw new AopConfigException("[" + aspectClass.getName() + "] cannot extend concrete aspect [" +
|
||||
superclass.getName() + "]");
|
||||
}
|
||||
|
||||
AjType<?> ajType = AjTypeSystem.getAjType(aspectClass);
|
||||
if (!ajType.isAspect()) {
|
||||
throw new NotAnAtAspectException(aspectClass);
|
||||
|
||||
+5
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -108,14 +108,10 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
List<Element> childElts = DomUtils.getChildElements(element);
|
||||
for (Element elt: childElts) {
|
||||
String localName = parserContext.getDelegate().getLocalName(elt);
|
||||
if (POINTCUT.equals(localName)) {
|
||||
parsePointcut(elt, parserContext);
|
||||
}
|
||||
else if (ADVISOR.equals(localName)) {
|
||||
parseAdvisor(elt, parserContext);
|
||||
}
|
||||
else if (ASPECT.equals(localName)) {
|
||||
parseAspect(elt, parserContext);
|
||||
switch (localName) {
|
||||
case POINTCUT -> parsePointcut(elt, parserContext);
|
||||
case ADVISOR -> parseAdvisor(elt, parserContext);
|
||||
case ASPECT -> parseAspect(elt, parserContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -93,10 +93,16 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
|
||||
if (bean instanceof Advised advised) {
|
||||
if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
|
||||
// Add our local Advisor to the existing proxy's Advisor chain...
|
||||
// Add our local Advisor to the existing proxy's Advisor chain.
|
||||
if (this.beforeExistingAdvisors) {
|
||||
advised.addAdvisor(0, this.advisor);
|
||||
}
|
||||
else if (advised.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE &&
|
||||
advised.getAdvisorCount() > 0) {
|
||||
// No target, leave last Advisor in place and add new Advisor right before.
|
||||
advised.addAdvisor(advised.getAdvisorCount() - 1, this.advisor);
|
||||
return bean;
|
||||
}
|
||||
else {
|
||||
advised.addAdvisor(this.advisor);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -257,23 +257,21 @@ public abstract class AopProxyUtils {
|
||||
if (ObjectUtils.isEmpty(arguments)) {
|
||||
return new Object[0];
|
||||
}
|
||||
if (method.isVarArgs()) {
|
||||
if (method.getParameterCount() == arguments.length) {
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
int varargIndex = paramTypes.length - 1;
|
||||
Class<?> varargType = paramTypes[varargIndex];
|
||||
if (varargType.isArray()) {
|
||||
Object varargArray = arguments[varargIndex];
|
||||
if (varargArray instanceof Object[] && !varargType.isInstance(varargArray)) {
|
||||
Object[] newArguments = new Object[arguments.length];
|
||||
System.arraycopy(arguments, 0, newArguments, 0, varargIndex);
|
||||
Class<?> targetElementType = varargType.getComponentType();
|
||||
int varargLength = Array.getLength(varargArray);
|
||||
Object newVarargArray = Array.newInstance(targetElementType, varargLength);
|
||||
System.arraycopy(varargArray, 0, newVarargArray, 0, varargLength);
|
||||
newArguments[varargIndex] = newVarargArray;
|
||||
return newArguments;
|
||||
}
|
||||
if (method.isVarArgs() && (method.getParameterCount() == arguments.length)) {
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
int varargIndex = paramTypes.length - 1;
|
||||
Class<?> varargType = paramTypes[varargIndex];
|
||||
if (varargType.isArray()) {
|
||||
Object varargArray = arguments[varargIndex];
|
||||
if (varargArray instanceof Object[] && !varargType.isInstance(varargArray)) {
|
||||
Object[] newArguments = new Object[arguments.length];
|
||||
System.arraycopy(arguments, 0, newArguments, 0, varargIndex);
|
||||
Class<?> targetElementType = varargType.getComponentType();
|
||||
int varargLength = Array.getLength(varargArray);
|
||||
Object newVarargArray = Array.newInstance(targetElementType, varargLength);
|
||||
System.arraycopy(varargArray, 0, newVarargArray, 0, varargLength);
|
||||
newArguments[varargIndex] = newVarargArray;
|
||||
return newArguments;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -251,11 +251,10 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
private void validateClassIfNecessary(Class<?> proxySuperClass, @Nullable ClassLoader proxyClassLoader) {
|
||||
if (!this.advised.isOptimize() && logger.isInfoEnabled()) {
|
||||
synchronized (validatedClasses) {
|
||||
if (!validatedClasses.containsKey(proxySuperClass)) {
|
||||
doValidateClass(proxySuperClass, proxyClassLoader,
|
||||
ClassUtils.getAllInterfacesForClassAsSet(proxySuperClass));
|
||||
validatedClasses.put(proxySuperClass, Boolean.TRUE);
|
||||
}
|
||||
validatedClasses.computeIfAbsent(proxySuperClass, clazz -> {
|
||||
doValidateClass(clazz, proxyClassLoader, ClassUtils.getAllInterfacesForClassAsSet(clazz));
|
||||
return Boolean.TRUE;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -702,8 +701,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
// We need to create a method invocation...
|
||||
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
|
||||
}
|
||||
retVal = processReturnType(proxy, target, method, retVal);
|
||||
return retVal;
|
||||
return processReturnType(proxy, target, method, retVal);
|
||||
}
|
||||
finally {
|
||||
if (target != null && !targetSource.isStatic()) {
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -109,10 +109,8 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
|
||||
*/
|
||||
private static boolean hasMatchingIntroductions(Advisor[] advisors, Class<?> actualClass) {
|
||||
for (Advisor advisor : advisors) {
|
||||
if (advisor instanceof IntroductionAdvisor ia) {
|
||||
if (ia.getClassFilter().matches(actualClass)) {
|
||||
return true;
|
||||
}
|
||||
if (advisor instanceof IntroductionAdvisor ia && ia.getClassFilter().matches(actualClass)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
+14
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -54,9 +54,9 @@ import org.springframework.util.ClassUtils;
|
||||
* return type however, such exceptions cannot be transmitted back. In that case an
|
||||
* {@link AsyncUncaughtExceptionHandler} can be registered to process such exceptions.
|
||||
*
|
||||
* <p>As of Spring 3.1.2 the {@code AnnotationAsyncExecutionInterceptor} subclass is
|
||||
* preferred for use due to its support for executor qualification in conjunction with
|
||||
* Spring's {@code @Async} annotation.
|
||||
* <p>Note: the {@code AnnotationAsyncExecutionInterceptor} subclass is preferred
|
||||
* due to its support for executor qualification in conjunction with Spring's
|
||||
* {@code @Async} annotation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
@@ -71,8 +71,8 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport imple
|
||||
/**
|
||||
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
|
||||
* @param defaultExecutor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to;
|
||||
* as of 4.2.6, a local executor for this interceptor will be built otherwise
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to; a local
|
||||
* executor for this interceptor will be built otherwise
|
||||
*/
|
||||
public AsyncExecutionInterceptor(@Nullable Executor defaultExecutor) {
|
||||
super(defaultExecutor);
|
||||
@@ -81,8 +81,8 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport imple
|
||||
/**
|
||||
* Create a new {@code AsyncExecutionInterceptor}.
|
||||
* @param defaultExecutor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to;
|
||||
* as of 4.2.6, a local executor for this interceptor will be built otherwise
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to; a local
|
||||
* executor for this interceptor will be built otherwise
|
||||
* @param exceptionHandler the {@link AsyncUncaughtExceptionHandler} to use
|
||||
*/
|
||||
public AsyncExecutionInterceptor(@Nullable Executor defaultExecutor, AsyncUncaughtExceptionHandler exceptionHandler) {
|
||||
@@ -130,9 +130,12 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport imple
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation is a no-op for compatibility in Spring 3.1.2.
|
||||
* Subclasses may override to provide support for extracting qualifier information,
|
||||
* e.g. via an annotation on the given method.
|
||||
* Get the qualifier for a specific executor to use when executing the given
|
||||
* method.
|
||||
* <p>The default implementation of this method is effectively a no-op.
|
||||
* <p>Subclasses may override this method to provide support for extracting
|
||||
* qualifier information — for example, via an annotation on the given
|
||||
* method.
|
||||
* @return always {@code null}
|
||||
* @since 3.1.2
|
||||
* @see #determineAsyncExecutor(Method)
|
||||
|
||||
+144
-130
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,7 @@ import java.io.FileNotFoundException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.ArrayList;
|
||||
@@ -76,24 +77,21 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
/**
|
||||
* To be overridden by concrete test subclasses.
|
||||
* @return the fixture
|
||||
*/
|
||||
protected abstract AspectJAdvisorFactory getFixture();
|
||||
protected abstract AspectJAdvisorFactory getAdvisorFactory();
|
||||
|
||||
|
||||
@Test
|
||||
void rejectsPerCflowAspect() {
|
||||
assertThatExceptionOfType(AopConfigException.class).isThrownBy(() ->
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new PerCflowAspect(), "someBean")))
|
||||
assertThatExceptionOfType(AopConfigException.class)
|
||||
.isThrownBy(() -> getAdvisorFactory().getAdvisors(aspectInstanceFactory(new PerCflowAspect(), "someBean")))
|
||||
.withMessageContaining("PERCFLOW");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsPerCflowBelowAspect() {
|
||||
assertThatExceptionOfType(AopConfigException.class).isThrownBy(() ->
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new PerCflowBelowAspect(), "someBean")))
|
||||
assertThatExceptionOfType(AopConfigException.class)
|
||||
.isThrownBy(() -> getAdvisorFactory().getAdvisors(aspectInstanceFactory(new PerCflowBelowAspect(), "someBean")))
|
||||
.withMessageContaining("PERCFLOWBELOW");
|
||||
}
|
||||
|
||||
@@ -102,9 +100,8 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
TestBean target = new TestBean();
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
TestBean itb = (TestBean) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new PerTargetAspect(), "someBean")),
|
||||
TestBean.class);
|
||||
TestBean itb = createProxy(target, TestBean.class,
|
||||
getAdvisorFactory().getAdvisors(aspectInstanceFactory(new PerTargetAspect(), "someBean")));
|
||||
assertThat(itb.getAge()).as("Around advice must NOT apply").isEqualTo(realAge);
|
||||
|
||||
Advised advised = (Advised) itb;
|
||||
@@ -139,15 +136,13 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
PerTargetAspect aspect1 = new PerTargetAspect();
|
||||
aspect1.count = 100;
|
||||
aspect1.setOrder(10);
|
||||
advisors.addAll(
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(aspect1, "someBean1")));
|
||||
advisors.addAll(getAdvisorFactory().getAdvisors(aspectInstanceFactory(aspect1, "someBean1")));
|
||||
PerTargetAspect aspect2 = new PerTargetAspect();
|
||||
aspect2.setOrder(5);
|
||||
advisors.addAll(
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(aspect2, "someBean2")));
|
||||
advisors.addAll(getAdvisorFactory().getAdvisors(aspectInstanceFactory(aspect2, "someBean2")));
|
||||
OrderComparator.sort(advisors);
|
||||
|
||||
TestBean itb = (TestBean) createProxy(target, advisors, TestBean.class);
|
||||
TestBean itb = createProxy(target, TestBean.class, advisors);
|
||||
assertThat(itb.getAge()).as("Around advice must NOT apply").isEqualTo(realAge);
|
||||
|
||||
// Hit the method in the per clause to instantiate the aspect
|
||||
@@ -166,14 +161,12 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
List<Advisor> advisors = new ArrayList<>();
|
||||
PerTargetAspectWithOrderAnnotation10 aspect1 = new PerTargetAspectWithOrderAnnotation10();
|
||||
aspect1.count = 100;
|
||||
advisors.addAll(
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(aspect1, "someBean1")));
|
||||
advisors.addAll(getAdvisorFactory().getAdvisors(aspectInstanceFactory(aspect1, "someBean1")));
|
||||
PerTargetAspectWithOrderAnnotation5 aspect2 = new PerTargetAspectWithOrderAnnotation5();
|
||||
advisors.addAll(
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(aspect2, "someBean2")));
|
||||
advisors.addAll(getAdvisorFactory().getAdvisors(aspectInstanceFactory(aspect2, "someBean2")));
|
||||
OrderComparator.sort(advisors);
|
||||
|
||||
TestBean itb = (TestBean) createProxy(target, advisors, TestBean.class);
|
||||
TestBean itb = createProxy(target, TestBean.class, advisors);
|
||||
assertThat(itb.getAge()).as("Around advice must NOT apply").isEqualTo(realAge);
|
||||
|
||||
// Hit the method in the per clause to instantiate the aspect
|
||||
@@ -188,9 +181,8 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
TestBean target = new TestBean();
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
TestBean itb = (TestBean) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new PerThisAspect(), "someBean")),
|
||||
TestBean.class);
|
||||
TestBean itb = createProxy(target, TestBean.class,
|
||||
getAdvisorFactory().getAdvisors(aspectInstanceFactory(new PerThisAspect(), "someBean")));
|
||||
assertThat(itb.getAge()).as("Around advice must NOT apply").isEqualTo(realAge);
|
||||
|
||||
Advised advised = (Advised) itb;
|
||||
@@ -225,7 +217,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
PerTypeWithinAspectInstanceFactory aif = new PerTypeWithinAspectInstanceFactory();
|
||||
TestBean itb = (TestBean) createProxy(target, getFixture().getAdvisors(aif), TestBean.class);
|
||||
TestBean itb = createProxy(target, TestBean.class, getAdvisorFactory().getAdvisors(aif));
|
||||
assertThat(aif.getInstantiationCount()).as("No method calls").isEqualTo(0);
|
||||
assertThat(itb.getAge()).as("Around advice must now apply").isEqualTo(0);
|
||||
|
||||
@@ -254,7 +246,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
assertThat(itb.getAge()).as("Around advice must still apply").isEqualTo(1);
|
||||
assertThat(itb.getAge()).as("Around advice must still apply").isEqualTo(2);
|
||||
|
||||
TestBean itb2 = (TestBean) createProxy(target, getFixture().getAdvisors(aif), TestBean.class);
|
||||
TestBean itb2 = createProxy(target, TestBean.class, getAdvisorFactory().getAdvisors(aif));
|
||||
assertThat(aif.getInstantiationCount()).isEqualTo(1);
|
||||
assertThat(itb2.getAge()).as("Around advice be independent for second instance").isEqualTo(0);
|
||||
assertThat(aif.getInstantiationCount()).isEqualTo(2);
|
||||
@@ -278,10 +270,9 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Test
|
||||
void namedPointcutFromAspectLibraryWithBinding() {
|
||||
TestBean target = new TestBean();
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(
|
||||
new NamedPointcutAspectFromLibraryWithBinding(), "someBean")),
|
||||
ITestBean.class);
|
||||
ITestBean itb = createProxy(target, ITestBean.class,
|
||||
getAdvisorFactory().getAdvisors(aspectInstanceFactory(
|
||||
new NamedPointcutAspectFromLibraryWithBinding(), "someBean")));
|
||||
itb.setAge(10);
|
||||
assertThat(itb.getAge()).as("Around advice must apply").isEqualTo(20);
|
||||
assertThat(target.getAge()).isEqualTo(20);
|
||||
@@ -291,9 +282,8 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
TestBean target = new TestBean();
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(aspectInstance, "someBean")),
|
||||
ITestBean.class);
|
||||
ITestBean itb = createProxy(target, ITestBean.class,
|
||||
getAdvisorFactory().getAdvisors(aspectInstanceFactory(aspectInstance, "someBean")));
|
||||
assertThat(itb.getAge()).as("Around advice must apply").isEqualTo(-1);
|
||||
assertThat(target.getAge()).isEqualTo(realAge);
|
||||
}
|
||||
@@ -301,10 +291,8 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Test
|
||||
void bindingWithSingleArg() {
|
||||
TestBean target = new TestBean();
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new BindingAspectWithSingleArg(), "someBean")),
|
||||
ITestBean.class);
|
||||
ITestBean itb = createProxy(target, ITestBean.class,
|
||||
getAdvisorFactory().getAdvisors(aspectInstanceFactory(new BindingAspectWithSingleArg(), "someBean")));
|
||||
itb.setAge(10);
|
||||
assertThat(itb.getAge()).as("Around advice must apply").isEqualTo(20);
|
||||
assertThat(target.getAge()).isEqualTo(20);
|
||||
@@ -313,10 +301,8 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Test
|
||||
void bindingWithMultipleArgsDifferentlyOrdered() {
|
||||
ManyValuedArgs target = new ManyValuedArgs();
|
||||
ManyValuedArgs mva = (ManyValuedArgs) createProxy(target,
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new ManyValuedArgs(), "someBean")),
|
||||
ManyValuedArgs.class);
|
||||
ManyValuedArgs mva = createProxy(target, ManyValuedArgs.class,
|
||||
getAdvisorFactory().getAdvisors(aspectInstanceFactory(new ManyValuedArgs(), "someBean")));
|
||||
|
||||
String a = "a";
|
||||
int b = 12;
|
||||
@@ -334,10 +320,8 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
void introductionOnTargetNotImplementingInterface() {
|
||||
NotLockable notLockableTarget = new NotLockable();
|
||||
assertThat(notLockableTarget instanceof Lockable).isFalse();
|
||||
NotLockable notLockable1 = (NotLockable) createProxy(notLockableTarget,
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
NotLockable.class);
|
||||
NotLockable notLockable1 = createProxy(notLockableTarget, NotLockable.class,
|
||||
getAdvisorFactory().getAdvisors(aspectInstanceFactory(new MakeLockable(), "someBean")));
|
||||
assertThat(notLockable1 instanceof Lockable).isTrue();
|
||||
Lockable lockable = (Lockable) notLockable1;
|
||||
assertThat(lockable.locked()).isFalse();
|
||||
@@ -345,72 +329,64 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
assertThat(lockable.locked()).isTrue();
|
||||
|
||||
NotLockable notLockable2Target = new NotLockable();
|
||||
NotLockable notLockable2 = (NotLockable) createProxy(notLockable2Target,
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
NotLockable.class);
|
||||
NotLockable notLockable2 = createProxy(notLockable2Target, NotLockable.class,
|
||||
getAdvisorFactory().getAdvisors(aspectInstanceFactory(new MakeLockable(), "someBean")));
|
||||
assertThat(notLockable2 instanceof Lockable).isTrue();
|
||||
Lockable lockable2 = (Lockable) notLockable2;
|
||||
assertThat(lockable2.locked()).isFalse();
|
||||
notLockable2.setIntValue(1);
|
||||
lockable2.lock();
|
||||
assertThatIllegalStateException().isThrownBy(() ->
|
||||
notLockable2.setIntValue(32));
|
||||
assertThatIllegalStateException().isThrownBy(() -> notLockable2.setIntValue(32));
|
||||
assertThat(lockable2.locked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void introductionAdvisorExcludedFromTargetImplementingInterface() {
|
||||
assertThat(AopUtils.findAdvisorsThatCanApply(
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
getAdvisorFactory().getAdvisors(
|
||||
aspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
CannotBeUnlocked.class).isEmpty()).isTrue();
|
||||
assertThat(AopUtils.findAdvisorsThatCanApply(getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")), NotLockable.class)).hasSize(2);
|
||||
assertThat(AopUtils.findAdvisorsThatCanApply(getAdvisorFactory().getAdvisors(
|
||||
aspectInstanceFactory(new MakeLockable(),"someBean")), NotLockable.class)).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void introductionOnTargetImplementingInterface() {
|
||||
CannotBeUnlocked target = new CannotBeUnlocked();
|
||||
Lockable proxy = (Lockable) createProxy(target,
|
||||
Lockable proxy = createProxy(target, CannotBeUnlocked.class,
|
||||
// Ensure that we exclude
|
||||
AopUtils.findAdvisorsThatCanApply(
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
CannotBeUnlocked.class
|
||||
),
|
||||
CannotBeUnlocked.class);
|
||||
getAdvisorFactory().getAdvisors(aspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
CannotBeUnlocked.class));
|
||||
assertThat(proxy).isInstanceOf(Lockable.class);
|
||||
Lockable lockable = proxy;
|
||||
assertThat(lockable.locked()).as("Already locked").isTrue();
|
||||
lockable.lock();
|
||||
assertThat(lockable.locked()).as("Real target ignores locking").isTrue();
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() ->
|
||||
lockable.unlock());
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> lockable.unlock());
|
||||
}
|
||||
|
||||
@Test
|
||||
void introductionOnTargetExcludedByTypePattern() {
|
||||
ArrayList<Object> target = new ArrayList<>();
|
||||
List<?> proxy = (List<?>) createProxy(target,
|
||||
List<?> proxy = createProxy(target, List.class,
|
||||
AopUtils.findAdvisorsThatCanApply(
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
List.class
|
||||
),
|
||||
List.class);
|
||||
getAdvisorFactory().getAdvisors(aspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
List.class));
|
||||
assertThat(proxy instanceof Lockable).as("Type pattern must have excluded mixin").isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void introductionBasedOnAnnotationMatch_SPR5307() {
|
||||
void introductionBasedOnAnnotationMatch() { // gh-9980
|
||||
AnnotatedTarget target = new AnnotatedTargetImpl();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeAnnotatedTypeModifiable(), "someBean"));
|
||||
Object proxy = createProxy(target, advisors, AnnotatedTarget.class);
|
||||
System.out.println(advisors.get(1));
|
||||
assertThat(proxy instanceof Lockable).isTrue();
|
||||
Lockable lockable = (Lockable)proxy;
|
||||
lockable.locked();
|
||||
List<Advisor> advisors = getAdvisorFactory().getAdvisors(
|
||||
aspectInstanceFactory(new MakeAnnotatedTypeModifiable(), "someBean"));
|
||||
Object proxy = createProxy(target, AnnotatedTarget.class, advisors);
|
||||
assertThat(proxy).isInstanceOf(Lockable.class);
|
||||
Lockable lockable = (Lockable) proxy;
|
||||
assertThat(lockable.locked()).isFalse();
|
||||
lockable.lock();
|
||||
assertThat(lockable.locked()).isTrue();
|
||||
}
|
||||
|
||||
// TODO: Why does this test fail? It hasn't been run before, so it maybe never actually passed...
|
||||
@@ -419,12 +395,12 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
void introductionWithArgumentBinding() {
|
||||
TestBean target = new TestBean();
|
||||
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeITestBeanModifiable(), "someBean"));
|
||||
advisors.addAll(getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")));
|
||||
List<Advisor> advisors = getAdvisorFactory().getAdvisors(
|
||||
aspectInstanceFactory(new MakeITestBeanModifiable(), "someBean"));
|
||||
advisors.addAll(getAdvisorFactory().getAdvisors(
|
||||
aspectInstanceFactory(new MakeLockable(), "someBean")));
|
||||
|
||||
Modifiable modifiable = (Modifiable) createProxy(target, advisors, ITestBean.class);
|
||||
Modifiable modifiable = (Modifiable) createProxy(target, ITestBean.class, advisors);
|
||||
assertThat(modifiable).isInstanceOf(Modifiable.class);
|
||||
Lockable lockable = (Lockable) modifiable;
|
||||
assertThat(lockable.locked()).isFalse();
|
||||
@@ -443,8 +419,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
lockable.lock();
|
||||
assertThat(lockable.locked()).isTrue();
|
||||
assertThatIllegalStateException().as("Should be locked").isThrownBy(() ->
|
||||
itb.setName("Else"));
|
||||
assertThatIllegalStateException().as("Should be locked").isThrownBy(() -> itb.setName("Else"));
|
||||
lockable.unlock();
|
||||
itb.setName("Tony");
|
||||
}
|
||||
@@ -453,12 +428,11 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
void aspectMethodThrowsExceptionLegalOnSignature() {
|
||||
TestBean target = new TestBean();
|
||||
UnsupportedOperationException expectedException = new UnsupportedOperationException();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionThrowingAspect(expectedException), "someBean"));
|
||||
List<Advisor> advisors = getAdvisorFactory().getAdvisors(
|
||||
aspectInstanceFactory(new ExceptionThrowingAspect(expectedException), "someBean"));
|
||||
assertThat(advisors.size()).as("One advice method was found").isEqualTo(1);
|
||||
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(
|
||||
itb::getAge);
|
||||
ITestBean itb = createProxy(target, ITestBean.class, advisors);
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(itb::getAge);
|
||||
}
|
||||
|
||||
// TODO document this behaviour.
|
||||
@@ -467,39 +441,23 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
void aspectMethodThrowsExceptionIllegalOnSignature() {
|
||||
TestBean target = new TestBean();
|
||||
RemoteException expectedException = new RemoteException();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionThrowingAspect(expectedException), "someBean"));
|
||||
List<Advisor> advisors = getAdvisorFactory().getAdvisors(
|
||||
aspectInstanceFactory(new ExceptionThrowingAspect(expectedException), "someBean"));
|
||||
assertThat(advisors.size()).as("One advice method was found").isEqualTo(1);
|
||||
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
|
||||
assertThatExceptionOfType(UndeclaredThrowableException.class).isThrownBy(
|
||||
itb::getAge).withCause(expectedException);
|
||||
}
|
||||
|
||||
protected Object createProxy(Object target, List<Advisor> advisors, Class<?>... interfaces) {
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
if (interfaces.length > 1 || interfaces[0].isInterface()) {
|
||||
pf.setInterfaces(interfaces);
|
||||
}
|
||||
else {
|
||||
pf.setProxyTargetClass(true);
|
||||
}
|
||||
|
||||
// Required everywhere we use AspectJ proxies
|
||||
pf.addAdvice(ExposeInvocationInterceptor.INSTANCE);
|
||||
pf.addAdvisors(advisors);
|
||||
|
||||
pf.setExposeProxy(true);
|
||||
return pf.getProxy();
|
||||
ITestBean itb = createProxy(target, ITestBean.class, advisors);
|
||||
assertThatExceptionOfType(UndeclaredThrowableException.class)
|
||||
.isThrownBy(itb::getAge)
|
||||
.withCause(expectedException);
|
||||
}
|
||||
|
||||
@Test
|
||||
void twoAdvicesOnOneAspect() {
|
||||
TestBean target = new TestBean();
|
||||
TwoAdviceAspect twoAdviceAspect = new TwoAdviceAspect();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(twoAdviceAspect, "someBean"));
|
||||
List<Advisor> advisors = getAdvisorFactory().getAdvisors(
|
||||
aspectInstanceFactory(twoAdviceAspect, "someBean"));
|
||||
assertThat(advisors.size()).as("Two advice methods found").isEqualTo(2);
|
||||
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
|
||||
ITestBean itb = createProxy(target, ITestBean.class, advisors);
|
||||
itb.setName("");
|
||||
assertThat(itb.getAge()).isEqualTo(0);
|
||||
int newAge = 32;
|
||||
@@ -510,40 +468,76 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Test
|
||||
void afterAdviceTypes() throws Exception {
|
||||
InvocationTrackingAspect aspect = new InvocationTrackingAspect();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(aspect, "exceptionHandlingAspect"));
|
||||
Echo echo = (Echo) createProxy(new Echo(), advisors, Echo.class);
|
||||
List<Advisor> advisors = getAdvisorFactory().getAdvisors(
|
||||
aspectInstanceFactory(aspect, "exceptionHandlingAspect"));
|
||||
Echo echo = createProxy(new Echo(), Echo.class, advisors);
|
||||
|
||||
assertThat(aspect.invocations).isEmpty();
|
||||
assertThat(echo.echo(42)).isEqualTo(42);
|
||||
assertThat(aspect.invocations).containsExactly("around - start", "before", "after returning", "after", "around - end");
|
||||
|
||||
aspect.invocations.clear();
|
||||
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() -> echo.echo(new FileNotFoundException()));
|
||||
assertThatExceptionOfType(FileNotFoundException.class)
|
||||
.isThrownBy(() -> echo.echo(new FileNotFoundException()));
|
||||
assertThat(aspect.invocations).containsExactly("around - start", "before", "after throwing", "after", "around - end");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonAbstractParentAspect() throws Exception {
|
||||
IncrementingAspect aspect = new IncrementingAspect();
|
||||
|
||||
// Precondition:
|
||||
assertThat(Modifier.isAbstract(aspect.getClass().getSuperclass().getModifiers())).isFalse();
|
||||
|
||||
List<Advisor> advisors = getAdvisorFactory().getAdvisors(aspectInstanceFactory(aspect, "incrementingAspect"));
|
||||
|
||||
ITestBean proxy = createProxy(new TestBean("Jane", 42), ITestBean.class, advisors);
|
||||
assertThat(proxy.getAge()).isEqualTo(86); // (42 + 1) * 2
|
||||
}
|
||||
|
||||
@Test
|
||||
void failureWithoutExplicitDeclarePrecedence() {
|
||||
TestBean target = new TestBean();
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory = new SingletonMetadataAwareAspectInstanceFactory(
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory = aspectInstanceFactory(
|
||||
new NoDeclarePrecedenceShouldFail(), "someBean");
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(aspectInstanceFactory), ITestBean.class);
|
||||
itb.getAge();
|
||||
ITestBean itb = createProxy(target, ITestBean.class, getAdvisorFactory().getAdvisors(aspectInstanceFactory));
|
||||
assertThat(itb.getAge()).isEqualTo(42);
|
||||
}
|
||||
|
||||
@Test
|
||||
void declarePrecedenceNotSupported() {
|
||||
TestBean target = new TestBean();
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> {
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory = new SingletonMetadataAwareAspectInstanceFactory(
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory = aspectInstanceFactory(
|
||||
new DeclarePrecedenceShouldSucceed(), "someBean");
|
||||
createProxy(target, getFixture().getAdvisors(aspectInstanceFactory), ITestBean.class);
|
||||
createProxy(target, ITestBean.class, getAdvisorFactory().getAdvisors(aspectInstanceFactory));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private static MetadataAwareAspectInstanceFactory aspectInstanceFactory(Object aspectInstance, String aspectName) {
|
||||
return new SingletonMetadataAwareAspectInstanceFactory(aspectInstance, aspectName);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T createProxy(Object target, Class<T> type, List<Advisor> advisors) {
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
if (type.isInterface()) {
|
||||
pf.addInterface(type);
|
||||
}
|
||||
else {
|
||||
pf.setProxyTargetClass(true);
|
||||
}
|
||||
|
||||
// Required everywhere we use AspectJ proxies
|
||||
pf.addAdvice(ExposeInvocationInterceptor.INSTANCE);
|
||||
pf.addAdvisors(advisors);
|
||||
|
||||
pf.setExposeProxy(true);
|
||||
return (T) pf.getProxy();
|
||||
}
|
||||
|
||||
|
||||
@Aspect("percflow(execution(* *(..)))")
|
||||
static class PerCflowAspect {
|
||||
}
|
||||
@@ -758,15 +752,35 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
static class Echo {
|
||||
|
||||
Object echo(Object o) throws Exception {
|
||||
if (o instanceof Exception) {
|
||||
throw (Exception) o;
|
||||
Object echo(Object obj) throws Exception {
|
||||
if (obj instanceof Exception ex) {
|
||||
throw ex;
|
||||
}
|
||||
return o;
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
class DoublingAspect {
|
||||
|
||||
@Around("execution(* getAge())")
|
||||
public Object doubleAge(ProceedingJoinPoint pjp) throws Throwable {
|
||||
return ((int) pjp.proceed()) * 2;
|
||||
}
|
||||
}
|
||||
|
||||
@Aspect
|
||||
class IncrementingAspect extends DoublingAspect {
|
||||
|
||||
@Around("execution(* getAge())")
|
||||
public int incrementAge(ProceedingJoinPoint pjp) throws Throwable {
|
||||
return ((int) pjp.proceed()) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Aspect
|
||||
private static class InvocationTrackingAspect {
|
||||
|
||||
@@ -824,7 +838,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Around("getAge()")
|
||||
int preventExecution(ProceedingJoinPoint pjp) {
|
||||
return 666;
|
||||
return 42;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -844,7 +858,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Around("getAge()")
|
||||
int preventExecution(ProceedingJoinPoint pjp) {
|
||||
return 666;
|
||||
return 42;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,7 @@ package org.springframework.aop.aspectj.annotation;
|
||||
class ReflectiveAspectJAdvisorFactoryTests extends AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Override
|
||||
protected AspectJAdvisorFactory getFixture() {
|
||||
protected AspectJAdvisorFactory getAdvisorFactory() {
|
||||
return new ReflectiveAspectJAdvisorFactory();
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,7 +50,7 @@ public class ThrowsAdviceInterceptorTests {
|
||||
MyThrowsHandler th = new MyThrowsHandler();
|
||||
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
|
||||
Object ret = new Object();
|
||||
MethodInvocation mi = mock(MethodInvocation.class);
|
||||
MethodInvocation mi = mock();
|
||||
given(mi.proceed()).willReturn(ret);
|
||||
assertThat(ti.invoke(mi)).isEqualTo(ret);
|
||||
assertThat(th.getCalls()).isEqualTo(0);
|
||||
@@ -62,7 +62,7 @@ public class ThrowsAdviceInterceptorTests {
|
||||
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
|
||||
assertThat(ti.getHandlerMethodCount()).isEqualTo(2);
|
||||
Exception ex = new Exception();
|
||||
MethodInvocation mi = mock(MethodInvocation.class);
|
||||
MethodInvocation mi = mock();
|
||||
given(mi.proceed()).willThrow(ex);
|
||||
assertThatException().isThrownBy(() -> ti.invoke(mi)).isSameAs(ex);
|
||||
assertThat(th.getCalls()).isEqualTo(0);
|
||||
@@ -73,7 +73,7 @@ public class ThrowsAdviceInterceptorTests {
|
||||
MyThrowsHandler th = new MyThrowsHandler();
|
||||
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
|
||||
FileNotFoundException ex = new FileNotFoundException();
|
||||
MethodInvocation mi = mock(MethodInvocation.class);
|
||||
MethodInvocation mi = mock();
|
||||
given(mi.getMethod()).willReturn(Object.class.getMethod("hashCode"));
|
||||
given(mi.getThis()).willReturn(new Object());
|
||||
given(mi.proceed()).willThrow(ex);
|
||||
@@ -90,7 +90,7 @@ public class ThrowsAdviceInterceptorTests {
|
||||
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
|
||||
// Extends RemoteException
|
||||
ConnectException ex = new ConnectException("");
|
||||
MethodInvocation mi = mock(MethodInvocation.class);
|
||||
MethodInvocation mi = mock();
|
||||
given(mi.proceed()).willThrow(ex);
|
||||
assertThatExceptionOfType(ConnectException.class).isThrownBy(() ->
|
||||
ti.invoke(mi))
|
||||
@@ -115,7 +115,7 @@ public class ThrowsAdviceInterceptorTests {
|
||||
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
|
||||
// Extends RemoteException
|
||||
ConnectException ex = new ConnectException("");
|
||||
MethodInvocation mi = mock(MethodInvocation.class);
|
||||
MethodInvocation mi = mock();
|
||||
given(mi.proceed()).willThrow(ex);
|
||||
assertThatExceptionOfType(Throwable.class).isThrownBy(() ->
|
||||
ti.invoke(mi))
|
||||
|
||||
+7
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -94,12 +94,11 @@ public class CustomizableTraceInterceptorTests {
|
||||
|
||||
@Test
|
||||
public void testSunnyDayPathLogsCorrectly() throws Throwable {
|
||||
|
||||
MethodInvocation methodInvocation = mock(MethodInvocation.class);
|
||||
MethodInvocation methodInvocation = mock();
|
||||
given(methodInvocation.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(methodInvocation.getThis()).willReturn(this);
|
||||
|
||||
Log log = mock(Log.class);
|
||||
Log log = mock();
|
||||
given(log.isTraceEnabled()).willReturn(true);
|
||||
|
||||
CustomizableTraceInterceptor interceptor = new StubCustomizableTraceInterceptor(log);
|
||||
@@ -110,15 +109,14 @@ public class CustomizableTraceInterceptorTests {
|
||||
|
||||
@Test
|
||||
public void testExceptionPathLogsCorrectly() throws Throwable {
|
||||
|
||||
MethodInvocation methodInvocation = mock(MethodInvocation.class);
|
||||
MethodInvocation methodInvocation = mock();
|
||||
|
||||
IllegalArgumentException exception = new IllegalArgumentException();
|
||||
given(methodInvocation.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(methodInvocation.getThis()).willReturn(this);
|
||||
given(methodInvocation.proceed()).willThrow(exception);
|
||||
|
||||
Log log = mock(Log.class);
|
||||
Log log = mock();
|
||||
given(log.isTraceEnabled()).willReturn(true);
|
||||
|
||||
CustomizableTraceInterceptor interceptor = new StubCustomizableTraceInterceptor(log);
|
||||
@@ -131,15 +129,14 @@ public class CustomizableTraceInterceptorTests {
|
||||
|
||||
@Test
|
||||
public void testSunnyDayPathLogsCorrectlyWithPrettyMuchAllPlaceholdersMatching() throws Throwable {
|
||||
|
||||
MethodInvocation methodInvocation = mock(MethodInvocation.class);
|
||||
MethodInvocation methodInvocation = mock();
|
||||
|
||||
given(methodInvocation.getMethod()).willReturn(String.class.getMethod("toString", new Class[0]));
|
||||
given(methodInvocation.getThis()).willReturn(this);
|
||||
given(methodInvocation.getArguments()).willReturn(new Object[]{"$ One \\$", 2L});
|
||||
given(methodInvocation.proceed()).willReturn("Hello!");
|
||||
|
||||
Log log = mock(Log.class);
|
||||
Log log = mock();
|
||||
given(log.isTraceEnabled()).willReturn(true);
|
||||
|
||||
CustomizableTraceInterceptor interceptor = new StubCustomizableTraceInterceptor(log);
|
||||
|
||||
+5
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,10 +39,9 @@ public class DebugInterceptorTests {
|
||||
|
||||
@Test
|
||||
public void testSunnyDayPathLogsCorrectly() throws Throwable {
|
||||
MethodInvocation methodInvocation = mock();
|
||||
|
||||
MethodInvocation methodInvocation = mock(MethodInvocation.class);
|
||||
|
||||
Log log = mock(Log.class);
|
||||
Log log = mock();
|
||||
given(log.isTraceEnabled()).willReturn(true);
|
||||
|
||||
DebugInterceptor interceptor = new StubDebugInterceptor(log);
|
||||
@@ -54,13 +53,12 @@ public class DebugInterceptorTests {
|
||||
|
||||
@Test
|
||||
public void testExceptionPathStillLogsCorrectly() throws Throwable {
|
||||
|
||||
MethodInvocation methodInvocation = mock(MethodInvocation.class);
|
||||
MethodInvocation methodInvocation = mock();
|
||||
|
||||
IllegalArgumentException exception = new IllegalArgumentException();
|
||||
given(methodInvocation.proceed()).willThrow(exception);
|
||||
|
||||
Log log = mock(Log.class);
|
||||
Log log = mock();
|
||||
given(log.isTraceEnabled()).willReturn(true);
|
||||
|
||||
DebugInterceptor interceptor = new StubDebugInterceptor(log);
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,10 +50,10 @@ public class PerformanceMonitorInterceptorTests {
|
||||
|
||||
@Test
|
||||
public void testSunnyDayPathLogsPerformanceMetricsCorrectly() throws Throwable {
|
||||
MethodInvocation mi = mock(MethodInvocation.class);
|
||||
MethodInvocation mi = mock();
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString", new Class[0]));
|
||||
|
||||
Log log = mock(Log.class);
|
||||
Log log = mock();
|
||||
|
||||
PerformanceMonitorInterceptor interceptor = new PerformanceMonitorInterceptor(true);
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
@@ -63,11 +63,11 @@ public class PerformanceMonitorInterceptorTests {
|
||||
|
||||
@Test
|
||||
public void testExceptionPathStillLogsPerformanceMetricsCorrectly() throws Throwable {
|
||||
MethodInvocation mi = mock(MethodInvocation.class);
|
||||
MethodInvocation mi = mock();
|
||||
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString", new Class[0]));
|
||||
given(mi.proceed()).willThrow(new IllegalArgumentException());
|
||||
Log log = mock(Log.class);
|
||||
Log log = mock();
|
||||
|
||||
PerformanceMonitorInterceptor interceptor = new PerformanceMonitorInterceptor(true);
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,11 +38,11 @@ public class SimpleTraceInterceptorTests {
|
||||
|
||||
@Test
|
||||
public void testSunnyDayPathLogsCorrectly() throws Throwable {
|
||||
MethodInvocation mi = mock(MethodInvocation.class);
|
||||
MethodInvocation mi = mock();
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(mi.getThis()).willReturn(this);
|
||||
|
||||
Log log = mock(Log.class);
|
||||
Log log = mock();
|
||||
|
||||
SimpleTraceInterceptor interceptor = new SimpleTraceInterceptor(true);
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
@@ -52,13 +52,13 @@ public class SimpleTraceInterceptorTests {
|
||||
|
||||
@Test
|
||||
public void testExceptionPathStillLogsCorrectly() throws Throwable {
|
||||
MethodInvocation mi = mock(MethodInvocation.class);
|
||||
MethodInvocation mi = mock();
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(mi.getThis()).willReturn(this);
|
||||
IllegalArgumentException exception = new IllegalArgumentException();
|
||||
given(mi.proceed()).willThrow(exception);
|
||||
|
||||
Log log = mock(Log.class);
|
||||
Log log = mock();
|
||||
|
||||
final SimpleTraceInterceptor interceptor = new SimpleTraceInterceptor(true);
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -59,7 +59,7 @@ public class DefaultScopedObjectTests {
|
||||
}
|
||||
|
||||
private static void testBadTargetBeanName(final String badTargetBeanName) {
|
||||
ConfigurableBeanFactory factory = mock(ConfigurableBeanFactory.class);
|
||||
ConfigurableBeanFactory factory = mock();
|
||||
new DefaultScopedObject(factory, badTargetBeanName);
|
||||
}
|
||||
|
||||
|
||||
+15
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -44,22 +44,22 @@ import static org.mockito.Mockito.mock;
|
||||
* @author Chris Beams
|
||||
* @since 13.05.2003
|
||||
*/
|
||||
public class DelegatingIntroductionInterceptorTests {
|
||||
class DelegatingIntroductionInterceptorTests {
|
||||
|
||||
@Test
|
||||
public void testNullTarget() throws Exception {
|
||||
void testNullTarget() throws Exception {
|
||||
// Shouldn't accept null target
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
new DelegatingIntroductionInterceptor(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntroductionInterceptorWithDelegation() throws Exception {
|
||||
void testIntroductionInterceptorWithDelegation() throws Exception {
|
||||
TestBean raw = new TestBean();
|
||||
assertThat(! (raw instanceof TimeStamped)).isTrue();
|
||||
ProxyFactory factory = new ProxyFactory(raw);
|
||||
|
||||
TimeStamped ts = mock(TimeStamped.class);
|
||||
TimeStamped ts = mock();
|
||||
long timestamp = 111L;
|
||||
given(ts.getTimeStamp()).willReturn(timestamp);
|
||||
|
||||
@@ -70,12 +70,12 @@ public class DelegatingIntroductionInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntroductionInterceptorWithInterfaceHierarchy() throws Exception {
|
||||
void testIntroductionInterceptorWithInterfaceHierarchy() throws Exception {
|
||||
TestBean raw = new TestBean();
|
||||
assertThat(! (raw instanceof SubTimeStamped)).isTrue();
|
||||
ProxyFactory factory = new ProxyFactory(raw);
|
||||
|
||||
TimeStamped ts = mock(SubTimeStamped.class);
|
||||
SubTimeStamped ts = mock();
|
||||
long timestamp = 111L;
|
||||
given(ts.getTimeStamp()).willReturn(timestamp);
|
||||
|
||||
@@ -86,12 +86,12 @@ public class DelegatingIntroductionInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntroductionInterceptorWithSuperInterface() throws Exception {
|
||||
void testIntroductionInterceptorWithSuperInterface() throws Exception {
|
||||
TestBean raw = new TestBean();
|
||||
assertThat(! (raw instanceof TimeStamped)).isTrue();
|
||||
ProxyFactory factory = new ProxyFactory(raw);
|
||||
|
||||
TimeStamped ts = mock(SubTimeStamped.class);
|
||||
SubTimeStamped ts = mock();
|
||||
long timestamp = 111L;
|
||||
given(ts.getTimeStamp()).willReturn(timestamp);
|
||||
|
||||
@@ -103,7 +103,7 @@ public class DelegatingIntroductionInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutomaticInterfaceRecognitionInDelegate() throws Exception {
|
||||
void testAutomaticInterfaceRecognitionInDelegate() throws Exception {
|
||||
final long t = 1001L;
|
||||
class Tester implements TimeStamped, ITester {
|
||||
@Override
|
||||
@@ -133,7 +133,7 @@ public class DelegatingIntroductionInterceptorTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void testAutomaticInterfaceRecognitionInSubclass() throws Exception {
|
||||
void testAutomaticInterfaceRecognitionInSubclass() throws Exception {
|
||||
final long t = 1001L;
|
||||
@SuppressWarnings("serial")
|
||||
class TestII extends DelegatingIntroductionInterceptor implements TimeStamped, ITester {
|
||||
@@ -179,7 +179,7 @@ public class DelegatingIntroductionInterceptorTests {
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@Test
|
||||
public void testIntroductionInterceptorDoesntReplaceToString() throws Exception {
|
||||
void testIntroductionInterceptorDoesntReplaceToString() throws Exception {
|
||||
TestBean raw = new TestBean();
|
||||
assertThat(! (raw instanceof TimeStamped)).isTrue();
|
||||
ProxyFactory factory = new ProxyFactory(raw);
|
||||
@@ -200,7 +200,7 @@ public class DelegatingIntroductionInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelegateReturnsThisIsMassagedToReturnProxy() {
|
||||
void testDelegateReturnsThisIsMassagedToReturnProxy() {
|
||||
NestedTestBean target = new NestedTestBean();
|
||||
String company = "Interface21";
|
||||
target.setCompany(company);
|
||||
@@ -221,7 +221,7 @@ public class DelegatingIntroductionInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializableDelegatingIntroductionInterceptorSerializable() throws Exception {
|
||||
void testSerializableDelegatingIntroductionInterceptorSerializable() throws Exception {
|
||||
SerializablePerson serializableTarget = new SerializablePerson();
|
||||
String name = "Tony";
|
||||
serializableTarget.setName("Tony");
|
||||
@@ -246,7 +246,7 @@ public class DelegatingIntroductionInterceptorTests {
|
||||
|
||||
// Test when target implements the interface: should get interceptor by preference.
|
||||
@Test
|
||||
public void testIntroductionMasksTargetImplementation() throws Exception {
|
||||
void testIntroductionMasksTargetImplementation() throws Exception {
|
||||
final long t = 1001L;
|
||||
@SuppressWarnings("serial")
|
||||
class TestII extends DelegatingIntroductionInterceptor implements TimeStamped {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,7 +34,7 @@ import org.springframework.lang.Nullable;
|
||||
public interface ConfigurablePropertyAccessor extends PropertyAccessor, PropertyEditorRegistry, TypeConverter {
|
||||
|
||||
/**
|
||||
* Specify a Spring 3.0 ConversionService to use for converting
|
||||
* Specify a {@link ConversionService} to use for converting
|
||||
* property values, as an alternative to JavaBeans PropertyEditors.
|
||||
*/
|
||||
void setConversionService(@Nullable ConversionService conversionService);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -100,8 +100,8 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
this.delegate = delegate;
|
||||
for (PropertyDescriptor pd : delegate.getPropertyDescriptors()) {
|
||||
try {
|
||||
this.propertyDescriptors.add(pd instanceof IndexedPropertyDescriptor ?
|
||||
new SimpleIndexedPropertyDescriptor((IndexedPropertyDescriptor) pd) :
|
||||
this.propertyDescriptors.add(pd instanceof IndexedPropertyDescriptor indexedPd ?
|
||||
new SimpleIndexedPropertyDescriptor(indexedPd) :
|
||||
new SimplePropertyDescriptor(pd));
|
||||
}
|
||||
catch (IntrospectionException ex) {
|
||||
@@ -170,8 +170,8 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
this.propertyDescriptors.add(
|
||||
new SimpleIndexedPropertyDescriptor(propertyName, null, null, null, method));
|
||||
}
|
||||
else if (existingPd instanceof IndexedPropertyDescriptor) {
|
||||
((IndexedPropertyDescriptor) existingPd).setIndexedWriteMethod(method);
|
||||
else if (existingPd instanceof IndexedPropertyDescriptor indexedPd) {
|
||||
indexedPd.setIndexedWriteMethod(method);
|
||||
}
|
||||
else {
|
||||
this.propertyDescriptors.remove(existingPd);
|
||||
@@ -189,8 +189,8 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
for (PropertyDescriptor pd : this.propertyDescriptors) {
|
||||
final Class<?> candidateType;
|
||||
final String candidateName = pd.getName();
|
||||
if (pd instanceof IndexedPropertyDescriptor ipd) {
|
||||
candidateType = ipd.getIndexedPropertyType();
|
||||
if (pd instanceof IndexedPropertyDescriptor indexedPd) {
|
||||
candidateType = indexedPd.getIndexedPropertyType();
|
||||
if (candidateName.equals(propertyName) &&
|
||||
(candidateType.equals(propertyType) || candidateType.equals(propertyType.getComponentType()))) {
|
||||
return pd;
|
||||
@@ -338,9 +338,9 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object other) {
|
||||
return (this == other || (other instanceof PropertyDescriptor &&
|
||||
PropertyDescriptorUtils.equals(this, (PropertyDescriptor) other)));
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return (this == obj || (obj instanceof PropertyDescriptor that &&
|
||||
PropertyDescriptorUtils.equals(this, that)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -184,8 +184,8 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
|
||||
/**
|
||||
* Overloaded version of {@code addPropertyValue} that takes
|
||||
* a property name and a property value.
|
||||
* <p>Note: As of Spring 3.0, we recommend using the more concise
|
||||
* and chaining-capable variant {@link #add}.
|
||||
* <p>Note: we recommend using the more concise and chaining-capable variant
|
||||
* {@link #add(String, Object)}.
|
||||
* @param propertyName name of the property
|
||||
* @param propertyValue value of the property
|
||||
* @see #addPropertyValue(PropertyValue)
|
||||
@@ -366,9 +366,9 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object other) {
|
||||
return (this == other || (other instanceof MutablePropertyValues &&
|
||||
this.propertyValueList.equals(((MutablePropertyValues) other).propertyValueList)));
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return (this == obj || (obj instanceof MutablePropertyValues that &&
|
||||
this.propertyValueList.equals(that.propertyValueList)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -116,7 +116,7 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
|
||||
|
||||
/**
|
||||
* Specify a Spring 3.0 ConversionService to use for converting
|
||||
* Specify a {@link ConversionService} to use for converting
|
||||
* property values, as an alternative to JavaBeans PropertyEditors.
|
||||
*/
|
||||
public void setConversionService(@Nullable ConversionService conversionService) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -135,8 +135,8 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
|
||||
public PropertyValue getOriginalPropertyValue() {
|
||||
PropertyValue original = this;
|
||||
Object source = getSource();
|
||||
while (source instanceof PropertyValue && source != original) {
|
||||
original = (PropertyValue) source;
|
||||
while (source instanceof PropertyValue pv && source != original) {
|
||||
original = pv;
|
||||
source = original.getSource();
|
||||
}
|
||||
return original;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -140,12 +140,12 @@ class TypeConverterDelegate {
|
||||
// Value not of required type?
|
||||
if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
|
||||
if (typeDescriptor != null && requiredType != null && Collection.class.isAssignableFrom(requiredType) &&
|
||||
convertedValue instanceof String) {
|
||||
convertedValue instanceof String text) {
|
||||
TypeDescriptor elementTypeDesc = typeDescriptor.getElementTypeDescriptor();
|
||||
if (elementTypeDesc != null) {
|
||||
Class<?> elementType = elementTypeDesc.getType();
|
||||
if (Class.class == elementType || Enum.class.isAssignableFrom(elementType)) {
|
||||
convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
|
||||
convertedValue = StringUtils.commaDelimitedListToStringArray(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,21 +166,19 @@ class TypeConverterDelegate {
|
||||
}
|
||||
else if (requiredType.isArray()) {
|
||||
// Array required -> apply appropriate conversion of elements.
|
||||
if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {
|
||||
convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
|
||||
if (convertedValue instanceof String text && Enum.class.isAssignableFrom(requiredType.getComponentType())) {
|
||||
convertedValue = StringUtils.commaDelimitedListToStringArray(text);
|
||||
}
|
||||
return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
|
||||
}
|
||||
else if (convertedValue instanceof Collection) {
|
||||
else if (convertedValue instanceof Collection<?> coll) {
|
||||
// Convert elements to target type, if determined.
|
||||
convertedValue = convertToTypedCollection(
|
||||
(Collection<?>) convertedValue, propertyName, requiredType, typeDescriptor);
|
||||
convertedValue = convertToTypedCollection(coll, propertyName, requiredType, typeDescriptor);
|
||||
standardConversion = true;
|
||||
}
|
||||
else if (convertedValue instanceof Map) {
|
||||
else if (convertedValue instanceof Map<?, ?> map) {
|
||||
// Convert keys and values to respective target type, if determined.
|
||||
convertedValue = convertToTypedMap(
|
||||
(Map<?, ?>) convertedValue, propertyName, requiredType, typeDescriptor);
|
||||
convertedValue = convertToTypedMap(map, propertyName, requiredType, typeDescriptor);
|
||||
standardConversion = true;
|
||||
}
|
||||
if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {
|
||||
@@ -191,7 +189,7 @@ class TypeConverterDelegate {
|
||||
// We can stringify any primitive value...
|
||||
return (T) convertedValue.toString();
|
||||
}
|
||||
else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
|
||||
else if (convertedValue instanceof String text && !requiredType.isInstance(convertedValue)) {
|
||||
if (conversionAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {
|
||||
try {
|
||||
Constructor<T> strCtor = requiredType.getConstructor(String.class);
|
||||
@@ -209,7 +207,7 @@ class TypeConverterDelegate {
|
||||
}
|
||||
}
|
||||
}
|
||||
String trimmedValue = ((String) convertedValue).trim();
|
||||
String trimmedValue = text.trim();
|
||||
if (requiredType.isEnum() && trimmedValue.isEmpty()) {
|
||||
// It's an empty enum identifier: reset the enum value to null.
|
||||
return null;
|
||||
@@ -217,9 +215,8 @@ class TypeConverterDelegate {
|
||||
convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue);
|
||||
standardConversion = true;
|
||||
}
|
||||
else if (convertedValue instanceof Number && Number.class.isAssignableFrom(requiredType)) {
|
||||
convertedValue = NumberUtils.convertNumberToTargetClass(
|
||||
(Number) convertedValue, (Class<Number>) requiredType);
|
||||
else if (convertedValue instanceof Number num && Number.class.isAssignableFrom(requiredType)) {
|
||||
convertedValue = NumberUtils.convertNumberToTargetClass(num, (Class<Number>) requiredType);
|
||||
standardConversion = true;
|
||||
}
|
||||
}
|
||||
@@ -382,23 +379,22 @@ class TypeConverterDelegate {
|
||||
|
||||
Object returnValue = convertedValue;
|
||||
|
||||
if (requiredType != null && !requiredType.isArray() && convertedValue instanceof String[]) {
|
||||
if (requiredType != null && !requiredType.isArray() && convertedValue instanceof String[] array) {
|
||||
// Convert String array to a comma-separated String.
|
||||
// Only applies if no PropertyEditor converted the String array before.
|
||||
// The CSV String will be passed into a PropertyEditor's setAsText method, if any.
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Converting String array to comma-delimited String [" + convertedValue + "]");
|
||||
}
|
||||
convertedValue = StringUtils.arrayToCommaDelimitedString((String[]) convertedValue);
|
||||
convertedValue = StringUtils.arrayToCommaDelimitedString(array);
|
||||
}
|
||||
|
||||
if (convertedValue instanceof String) {
|
||||
if (convertedValue instanceof String newTextValue) {
|
||||
if (editor != null) {
|
||||
// Use PropertyEditor's setAsText in case of a String value.
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Converting String to [" + requiredType + "] using property editor [" + editor + "]");
|
||||
}
|
||||
String newTextValue = (String) convertedValue;
|
||||
return doConvertTextValue(oldValue, newTextValue, editor);
|
||||
}
|
||||
else if (String.class == requiredType) {
|
||||
@@ -431,9 +427,8 @@ class TypeConverterDelegate {
|
||||
}
|
||||
|
||||
private Object convertToTypedArray(Object input, @Nullable String propertyName, Class<?> componentType) {
|
||||
if (input instanceof Collection) {
|
||||
if (input instanceof Collection<?> coll) {
|
||||
// Convert Collection elements to array elements.
|
||||
Collection<?> coll = (Collection<?>) input;
|
||||
Object result = Array.newInstance(componentType, coll.size());
|
||||
int i = 0;
|
||||
for (Iterator<?> it = coll.iterator(); it.hasNext(); i++) {
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -204,8 +204,7 @@ public class BeanCreationException extends FatalBeanException {
|
||||
}
|
||||
if (this.relatedCauses != null) {
|
||||
for (Throwable relatedCause : this.relatedCauses) {
|
||||
if (relatedCause instanceof NestedRuntimeException &&
|
||||
((NestedRuntimeException) relatedCause).contains(exClass)) {
|
||||
if (relatedCause instanceof NestedRuntimeException nested && nested.contains(exClass)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -266,11 +266,11 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
|
||||
if (!(beanFactory instanceof ConfigurableListableBeanFactory clbf)) {
|
||||
throw new IllegalArgumentException(
|
||||
"AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory: " + beanFactory);
|
||||
}
|
||||
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
|
||||
this.beanFactory = clbf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
-4
@@ -281,8 +281,8 @@ public class InjectionMetadata {
|
||||
this.skip = true;
|
||||
return true;
|
||||
}
|
||||
else if (pvs instanceof MutablePropertyValues) {
|
||||
((MutablePropertyValues) pvs).registerProcessedProperty(this.pd.getName());
|
||||
else if (pvs instanceof MutablePropertyValues mpvs) {
|
||||
mpvs.registerProcessedProperty(this.pd.getName());
|
||||
}
|
||||
}
|
||||
this.skip = false;
|
||||
@@ -299,8 +299,8 @@ public class InjectionMetadata {
|
||||
return;
|
||||
}
|
||||
synchronized (pvs) {
|
||||
if (Boolean.FALSE.equals(this.skip) && this.pd != null && pvs instanceof MutablePropertyValues) {
|
||||
((MutablePropertyValues) pvs).clearProcessedProperty(this.pd.getName());
|
||||
if (Boolean.FALSE.equals(this.skip) && this.pd != null && pvs instanceof MutablePropertyValues mpvs) {
|
||||
mpvs.clearProcessedProperty(this.pd.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -279,7 +279,7 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
|
||||
actualValue = bd.getAttribute(attributeName);
|
||||
}
|
||||
if (actualValue == null && attributeName.equals(AutowireCandidateQualifier.VALUE_KEY) &&
|
||||
expectedValue instanceof String && bdHolder.matchesName((String) expectedValue)) {
|
||||
expectedValue instanceof String name && bdHolder.matchesName(name)) {
|
||||
// Fall back on bean name (or alias) match
|
||||
continue;
|
||||
}
|
||||
|
||||
+8
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,6 +35,7 @@ import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.support.AutowireCandidateResolver;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -45,6 +46,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
* @author Sebastien Deleuze
|
||||
* @since 6.0
|
||||
* @see BeanDefinitionMethodGeneratorFactory
|
||||
*/
|
||||
@@ -68,12 +70,17 @@ class BeanDefinitionMethodGenerator {
|
||||
* @param registeredBean the registered bean
|
||||
* @param currentPropertyName the current property name
|
||||
* @param aotContributions the AOT contributions
|
||||
* @throws IllegalArgumentException if the bean definition defines an instance supplier since this can't be supported for code generation
|
||||
*/
|
||||
BeanDefinitionMethodGenerator(
|
||||
BeanDefinitionMethodGeneratorFactory methodGeneratorFactory,
|
||||
RegisteredBean registeredBean, @Nullable String currentPropertyName,
|
||||
List<BeanRegistrationAotContribution> aotContributions) {
|
||||
|
||||
RootBeanDefinition mbd = registeredBean.getMergedBeanDefinition();
|
||||
if (mbd.getInstanceSupplier() != null && aotContributions.isEmpty()) {
|
||||
throw new IllegalArgumentException("Code generation is not supported for bean definitions declaring an instance supplier callback : " + mbd);
|
||||
}
|
||||
this.methodGeneratorFactory = methodGeneratorFactory;
|
||||
this.registeredBean = registeredBean;
|
||||
this.constructorOrFactoryMethod = registeredBean.resolveConstructorOrFactoryMethod();
|
||||
|
||||
+8
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -55,6 +55,7 @@ import org.springframework.util.ObjectUtils;
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @author Sebastien Deleuze
|
||||
* @since 6.0
|
||||
*/
|
||||
class BeanDefinitionPropertyValueCodeGenerator {
|
||||
@@ -448,7 +449,12 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
||||
return CodeBlock.of("new $T($L)", LinkedHashSet.class,
|
||||
generateCollectionOf(set, List.class, elementType));
|
||||
}
|
||||
set = orderForCodeConsistency(set);
|
||||
try {
|
||||
set = orderForCodeConsistency(set);
|
||||
}
|
||||
catch (ClassCastException ex) {
|
||||
// If elements are not comparable, just keep the original set
|
||||
}
|
||||
return super.generateCollectionCode(elementType, set);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -212,11 +212,11 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
||||
}
|
||||
|
||||
private T invokeBeanSupplier(Executable executable, ThrowingSupplier<T> beanSupplier) {
|
||||
if (!(executable instanceof Method)) {
|
||||
if (!(executable instanceof Method method)) {
|
||||
return beanSupplier.get();
|
||||
}
|
||||
try {
|
||||
SimpleInstantiationStrategy.setCurrentlyInvokedFactoryMethod((Method) executable);
|
||||
SimpleInstantiationStrategy.setCurrentlyInvokedFactoryMethod(method);
|
||||
return beanSupplier.get();
|
||||
}
|
||||
finally {
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ import org.springframework.util.function.ThrowingSupplier;
|
||||
* the form of a {@link BeanInstanceSupplier} that retains the executable
|
||||
* that is used to instantiate the bean.
|
||||
*
|
||||
* <p>Generated code is usually a method reference that generate the
|
||||
* <p>Generated code is usually a method reference that generates the
|
||||
* {@link BeanInstanceSupplier}, but some shortcut can be used as well such as:
|
||||
* <pre class="code">
|
||||
* {@code InstanceSupplier.of(TheGeneratedClass::getMyBeanInstance);}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -124,8 +124,8 @@ public abstract class AbstractFactoryBean<T>
|
||||
*/
|
||||
protected TypeConverter getBeanTypeConverter() {
|
||||
BeanFactory beanFactory = getBeanFactory();
|
||||
if (beanFactory instanceof ConfigurableBeanFactory) {
|
||||
return ((ConfigurableBeanFactory) beanFactory).getTypeConverter();
|
||||
if (beanFactory instanceof ConfigurableBeanFactory cbf) {
|
||||
return cbf.getTypeConverter();
|
||||
}
|
||||
else {
|
||||
return new SimpleTypeConverter();
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -130,6 +130,8 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
* {@link BeanPostProcessor BeanPostProcessors}.
|
||||
* <p>Note: This is intended for creating a fresh instance, populating annotated
|
||||
* fields and methods as well as applying all standard bean initialization callbacks.
|
||||
* Constructor resolution is done via {@link #AUTOWIRE_CONSTRUCTOR}, also influenced
|
||||
* by {@link SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors}.
|
||||
* It does <i>not</i> imply traditional by-name or by-type autowiring of properties;
|
||||
* use {@link #createBean(Class, int, boolean)} for those purposes.
|
||||
* @param beanClass the class of the bean to create
|
||||
|
||||
+15
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -172,11 +172,11 @@ public class BeanDefinitionVisitor {
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Nullable
|
||||
protected Object resolveValue(@Nullable Object value) {
|
||||
if (value instanceof BeanDefinition) {
|
||||
visitBeanDefinition((BeanDefinition) value);
|
||||
if (value instanceof BeanDefinition beanDef) {
|
||||
visitBeanDefinition(beanDef);
|
||||
}
|
||||
else if (value instanceof BeanDefinitionHolder) {
|
||||
visitBeanDefinition(((BeanDefinitionHolder) value).getBeanDefinition());
|
||||
else if (value instanceof BeanDefinitionHolder beanDefHolder) {
|
||||
visitBeanDefinition(beanDefHolder.getBeanDefinition());
|
||||
}
|
||||
else if (value instanceof RuntimeBeanReference ref) {
|
||||
String newBeanName = resolveStringValue(ref.getBeanName());
|
||||
@@ -196,17 +196,17 @@ public class BeanDefinitionVisitor {
|
||||
return new RuntimeBeanNameReference(newBeanName);
|
||||
}
|
||||
}
|
||||
else if (value instanceof Object[]) {
|
||||
visitArray((Object[]) value);
|
||||
else if (value instanceof Object[] array) {
|
||||
visitArray(array);
|
||||
}
|
||||
else if (value instanceof List) {
|
||||
visitList((List) value);
|
||||
else if (value instanceof List list) {
|
||||
visitList(list);
|
||||
}
|
||||
else if (value instanceof Set) {
|
||||
visitSet((Set) value);
|
||||
else if (value instanceof Set set) {
|
||||
visitSet(set);
|
||||
}
|
||||
else if (value instanceof Map) {
|
||||
visitMap((Map) value);
|
||||
else if (value instanceof Map map) {
|
||||
visitMap(map);
|
||||
}
|
||||
else if (value instanceof TypedStringValue typedStringValue) {
|
||||
String stringValue = typedStringValue.getValue();
|
||||
@@ -215,8 +215,8 @@ public class BeanDefinitionVisitor {
|
||||
typedStringValue.setValue(visitedString);
|
||||
}
|
||||
}
|
||||
else if (value instanceof String) {
|
||||
return resolveStringValue((String) value);
|
||||
else if (value instanceof String strValue) {
|
||||
return resolveStringValue(strValue);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -147,7 +147,7 @@ public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, Single
|
||||
BeanExpressionResolver getBeanExpressionResolver();
|
||||
|
||||
/**
|
||||
* Specify a Spring 3.0 ConversionService to use for converting
|
||||
* Specify a {@link ConversionService} to use for converting
|
||||
* property values, as an alternative to JavaBeans PropertyEditors.
|
||||
* @since 3.0
|
||||
*/
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -98,15 +98,15 @@ public class CustomScopeConfigurer implements BeanFactoryPostProcessor, BeanClas
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
if (this.scopes != null) {
|
||||
this.scopes.forEach((scopeKey, value) -> {
|
||||
if (value instanceof Scope) {
|
||||
beanFactory.registerScope(scopeKey, (Scope) value);
|
||||
if (value instanceof Scope scope) {
|
||||
beanFactory.registerScope(scopeKey, scope);
|
||||
}
|
||||
else if (value instanceof Class<?> scopeClass) {
|
||||
Assert.isAssignable(Scope.class, scopeClass, "Invalid scope class");
|
||||
beanFactory.registerScope(scopeKey, (Scope) BeanUtils.instantiateClass(scopeClass));
|
||||
}
|
||||
else if (value instanceof String) {
|
||||
Class<?> scopeClass = ClassUtils.resolveClassName((String) value, this.beanClassLoader);
|
||||
else if (value instanceof String scopeClassName) {
|
||||
Class<?> scopeClass = ClassUtils.resolveClassName(scopeClassName, this.beanClassLoader);
|
||||
Assert.isAssignable(Scope.class, scopeClass, "Invalid scope class");
|
||||
beanFactory.registerScope(scopeKey, (Scope) BeanUtils.instantiateClass(scopeClass));
|
||||
}
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -86,8 +86,8 @@ public class MethodInvokingBean extends ArgumentConvertingMethodInvoker
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (beanFactory instanceof ConfigurableBeanFactory) {
|
||||
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
|
||||
if (beanFactory instanceof ConfigurableBeanFactory cbf) {
|
||||
this.beanFactory = cbf;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,11 +123,11 @@ public class MethodInvokingBean extends ArgumentConvertingMethodInvoker
|
||||
return invoke();
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
if (ex.getTargetException() instanceof Exception) {
|
||||
throw (Exception) ex.getTargetException();
|
||||
if (ex.getTargetException() instanceof Exception exception) {
|
||||
throw exception;
|
||||
}
|
||||
if (ex.getTargetException() instanceof Error) {
|
||||
throw (Error) ex.getTargetException();
|
||||
if (ex.getTargetException() instanceof Error error) {
|
||||
throw error;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -232,10 +232,10 @@ public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfi
|
||||
}
|
||||
}
|
||||
|
||||
// New in Spring 2.5: resolve placeholders in alias target names and aliases as well.
|
||||
// Resolve placeholders in alias target names and aliases as well.
|
||||
beanFactoryToProcess.resolveAliases(valueResolver);
|
||||
|
||||
// New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes.
|
||||
// Resolve placeholders in embedded values such as annotation attributes.
|
||||
beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -206,8 +206,8 @@ public class PropertyPathFactoryBean implements FactoryBean<Object>, BeanNameAwa
|
||||
BeanWrapper target = this.targetBeanWrapper;
|
||||
if (target != null) {
|
||||
if (logger.isWarnEnabled() && this.targetBeanName != null &&
|
||||
this.beanFactory instanceof ConfigurableBeanFactory &&
|
||||
((ConfigurableBeanFactory) this.beanFactory).isCurrentlyInCreation(this.targetBeanName)) {
|
||||
this.beanFactory instanceof ConfigurableBeanFactory cbf &&
|
||||
cbf.isCurrentlyInCreation(this.targetBeanName)) {
|
||||
logger.warn("Target bean '" + this.targetBeanName + "' is still in creation due to a circular " +
|
||||
"reference - obtained value for property '" + this.propertyPath + "' may be outdated!");
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -250,11 +250,11 @@ public class ServiceLocatorFactoryBean implements FactoryBean<Object>, BeanFacto
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
if (!(beanFactory instanceof ListableBeanFactory)) {
|
||||
if (!(beanFactory instanceof ListableBeanFactory lbf)) {
|
||||
throw new FatalBeanException(
|
||||
"ServiceLocatorFactoryBean needs to run in a BeanFactory that is a ListableBeanFactory");
|
||||
}
|
||||
this.beanFactory = (ListableBeanFactory) beanFactory;
|
||||
this.beanFactory = lbf;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -129,10 +129,9 @@ public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean<Map
|
||||
private void merge(Map<String, Object> output, Map<String, Object> map) {
|
||||
map.forEach((key, value) -> {
|
||||
Object existing = output.get(key);
|
||||
if (value instanceof Map && existing instanceof Map) {
|
||||
// Inner cast required by Eclipse IDE.
|
||||
Map<String, Object> result = new LinkedHashMap<>((Map<String, Object>) existing);
|
||||
merge(result, (Map) value);
|
||||
if (value instanceof Map valueMap && existing instanceof Map existingMap) {
|
||||
Map<String, Object> result = new LinkedHashMap<>(existingMap);
|
||||
merge(result, valueMap);
|
||||
output.put(key, result);
|
||||
}
|
||||
else {
|
||||
|
||||
+6
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -226,17 +226,16 @@ public abstract class YamlProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private Map<String, Object> asMap(Object object) {
|
||||
// YAML can have numbers as keys
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
if (!(object instanceof Map)) {
|
||||
if (!(object instanceof Map map)) {
|
||||
// A document can be a text literal
|
||||
result.put("document", object);
|
||||
return result;
|
||||
}
|
||||
|
||||
Map<Object, Object> map = (Map<Object, Object>) object;
|
||||
map.forEach((key, value) -> {
|
||||
if (value instanceof Map) {
|
||||
value = asMap(value);
|
||||
@@ -306,6 +305,7 @@ public abstract class YamlProcessor {
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private void buildFlattenedMap(Map<String, Object> result, Map<String, Object> source, @Nullable String path) {
|
||||
source.forEach((key, value) -> {
|
||||
if (StringUtils.hasText(path)) {
|
||||
@@ -319,16 +319,12 @@ public abstract class YamlProcessor {
|
||||
if (value instanceof String) {
|
||||
result.put(key, value);
|
||||
}
|
||||
else if (value instanceof Map) {
|
||||
else if (value instanceof Map map) {
|
||||
// Need a compound key
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = (Map<String, Object>) value;
|
||||
buildFlattenedMap(result, map, key);
|
||||
}
|
||||
else if (value instanceof Collection) {
|
||||
else if (value instanceof Collection collection) {
|
||||
// Need a compound key
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<Object> collection = (Collection<Object>) value;
|
||||
if (collection.isEmpty()) {
|
||||
result.put(key, "");
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -318,8 +318,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
if (!ObjectUtils.isEmpty(args)) {
|
||||
int index = args.length;
|
||||
Object lastArg = args[index - 1];
|
||||
if (lastArg instanceof Closure<?>) {
|
||||
callable = (Closure<?>) lastArg;
|
||||
if (lastArg instanceof Closure<?> closure) {
|
||||
callable = closure;
|
||||
index--;
|
||||
}
|
||||
constructorArgs = resolveConstructorArguments(args, 0, index);
|
||||
|
||||
+9
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -139,22 +139,22 @@ class GroovyBeanDefinitionWrapper extends GroovyObjectSupport {
|
||||
if (obj == null) {
|
||||
throw new IllegalArgumentException("Parent bean cannot be set to a null runtime bean reference!");
|
||||
}
|
||||
if (obj instanceof String) {
|
||||
this.parentName = (String) obj;
|
||||
if (obj instanceof String name) {
|
||||
this.parentName = name;
|
||||
}
|
||||
else if (obj instanceof RuntimeBeanReference) {
|
||||
this.parentName = ((RuntimeBeanReference) obj).getBeanName();
|
||||
else if (obj instanceof RuntimeBeanReference runtimeBeanReference) {
|
||||
this.parentName = runtimeBeanReference.getBeanName();
|
||||
}
|
||||
else if (obj instanceof GroovyBeanDefinitionWrapper) {
|
||||
this.parentName = ((GroovyBeanDefinitionWrapper) obj).getBeanName();
|
||||
else if (obj instanceof GroovyBeanDefinitionWrapper wrapper) {
|
||||
this.parentName = wrapper.getBeanName();
|
||||
}
|
||||
getBeanDefinition().setParentName(this.parentName);
|
||||
getBeanDefinition().setAbstract(false);
|
||||
}
|
||||
|
||||
public GroovyBeanDefinitionWrapper addProperty(String propertyName, Object propertyValue) {
|
||||
if (propertyValue instanceof GroovyBeanDefinitionWrapper) {
|
||||
propertyValue = ((GroovyBeanDefinitionWrapper) propertyValue).getBeanDefinition();
|
||||
if (propertyValue instanceof GroovyBeanDefinitionWrapper wrapper) {
|
||||
propertyValue = wrapper.getBeanDefinition();
|
||||
}
|
||||
getBeanDefinition().getPropertyValues().add(propertyName, propertyValue);
|
||||
return this;
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -73,14 +73,14 @@ public class BeanComponentDefinition extends BeanDefinitionHolder implements Com
|
||||
PropertyValues propertyValues = beanDefinitionHolder.getBeanDefinition().getPropertyValues();
|
||||
for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
|
||||
Object value = propertyValue.getValue();
|
||||
if (value instanceof BeanDefinitionHolder) {
|
||||
innerBeans.add(((BeanDefinitionHolder) value).getBeanDefinition());
|
||||
if (value instanceof BeanDefinitionHolder beanDefHolder) {
|
||||
innerBeans.add(beanDefHolder.getBeanDefinition());
|
||||
}
|
||||
else if (value instanceof BeanDefinition) {
|
||||
innerBeans.add((BeanDefinition) value);
|
||||
else if (value instanceof BeanDefinition beanDef) {
|
||||
innerBeans.add(beanDef);
|
||||
}
|
||||
else if (value instanceof BeanReference) {
|
||||
references.add((BeanReference) value);
|
||||
else if (value instanceof BeanReference beanRef) {
|
||||
references.add(beanRef);
|
||||
}
|
||||
}
|
||||
this.innerBeanDefinitions = innerBeans.toArray(new BeanDefinition[0]);
|
||||
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -314,8 +314,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T createBean(Class<T> beanClass) throws BeansException {
|
||||
// Use prototype bean definition, to avoid registering bean as dependent bean.
|
||||
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
|
||||
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
|
||||
bd.setAutowireMode(AUTOWIRE_CONSTRUCTOR);
|
||||
bd.setScope(SCOPE_PROTOTYPE);
|
||||
bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader());
|
||||
return (T) createBean(beanClass.getName(), bd, null);
|
||||
@@ -1618,8 +1619,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
MutablePropertyValues mpvs = null;
|
||||
List<PropertyValue> original;
|
||||
|
||||
if (pvs instanceof MutablePropertyValues) {
|
||||
mpvs = (MutablePropertyValues) pvs;
|
||||
if (pvs instanceof MutablePropertyValues _mpvs) {
|
||||
mpvs = _mpvs;
|
||||
if (mpvs.isConverted()) {
|
||||
// Shortcut: use the pre-converted values as-is.
|
||||
try {
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -86,16 +86,16 @@ public abstract class AbstractBeanDefinitionReader implements BeanDefinitionRead
|
||||
this.registry = registry;
|
||||
|
||||
// Determine ResourceLoader to use.
|
||||
if (this.registry instanceof ResourceLoader) {
|
||||
this.resourceLoader = (ResourceLoader) this.registry;
|
||||
if (this.registry instanceof ResourceLoader _resourceLoader) {
|
||||
this.resourceLoader = _resourceLoader;
|
||||
}
|
||||
else {
|
||||
this.resourceLoader = new PathMatchingResourcePatternResolver();
|
||||
}
|
||||
|
||||
// Inherit Environment if possible
|
||||
if (this.registry instanceof EnvironmentCapable) {
|
||||
this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
|
||||
if (this.registry instanceof EnvironmentCapable environmentCapable) {
|
||||
this.environment = environmentCapable.getEnvironment();
|
||||
}
|
||||
else {
|
||||
this.environment = new StandardEnvironment();
|
||||
@@ -213,10 +213,10 @@ public abstract class AbstractBeanDefinitionReader implements BeanDefinitionRead
|
||||
"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
|
||||
}
|
||||
|
||||
if (resourceLoader instanceof ResourcePatternResolver) {
|
||||
if (resourceLoader instanceof ResourcePatternResolver resourcePatternResolver) {
|
||||
// Resource pattern matching available.
|
||||
try {
|
||||
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
|
||||
Resource[] resources = resourcePatternResolver.getResources(location);
|
||||
int count = loadBeanDefinitions(resources);
|
||||
if (actualResources != null) {
|
||||
Collections.addAll(actualResources, resources);
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1540,8 +1540,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
if (evaluated instanceof Class<?> clazz) {
|
||||
return clazz;
|
||||
}
|
||||
else if (evaluated instanceof String str) {
|
||||
className = str;
|
||||
else if (evaluated instanceof String name) {
|
||||
className = name;
|
||||
freshResolve = true;
|
||||
}
|
||||
else {
|
||||
|
||||
+19
-23
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -128,8 +128,7 @@ abstract class AutowireUtils {
|
||||
* @return the resolved value
|
||||
*/
|
||||
public static Object resolveAutowiringValue(Object autowiringValue, Class<?> requiredType) {
|
||||
if (autowiringValue instanceof ObjectFactory && !requiredType.isInstance(autowiringValue)) {
|
||||
ObjectFactory<?> factory = (ObjectFactory<?>) autowiringValue;
|
||||
if (autowiringValue instanceof ObjectFactory<?> factory && !requiredType.isInstance(autowiringValue)) {
|
||||
if (autowiringValue instanceof Serializable && requiredType.isInterface()) {
|
||||
autowiringValue = Proxy.newProxyInstance(requiredType.getClassLoader(),
|
||||
new Class<?>[] {requiredType}, new ObjectFactoryDelegatingInvocationHandler(factory));
|
||||
@@ -223,13 +222,13 @@ abstract class AutowireUtils {
|
||||
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
|
||||
for (Type typeArg : actualTypeArguments) {
|
||||
if (typeArg.equals(genericReturnType)) {
|
||||
if (arg instanceof Class) {
|
||||
return (Class<?>) arg;
|
||||
if (arg instanceof Class<?> clazz) {
|
||||
return clazz;
|
||||
}
|
||||
else {
|
||||
String className = null;
|
||||
if (arg instanceof String) {
|
||||
className = (String) arg;
|
||||
if (arg instanceof String name) {
|
||||
className = name;
|
||||
}
|
||||
else if (arg instanceof TypedStringValue typedValue) {
|
||||
String targetTypeName = typedValue.getTargetTypeName();
|
||||
@@ -275,22 +274,19 @@ abstract class AutowireUtils {
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
switch (method.getName()) {
|
||||
case "equals":
|
||||
// Only consider equal when proxies are identical.
|
||||
return (proxy == args[0]);
|
||||
case "hashCode":
|
||||
// Use hashCode of proxy.
|
||||
return System.identityHashCode(proxy);
|
||||
case "toString":
|
||||
return this.objectFactory.toString();
|
||||
}
|
||||
try {
|
||||
return method.invoke(this.objectFactory.getObject(), args);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw ex.getTargetException();
|
||||
}
|
||||
return switch (method.getName()) {
|
||||
case "equals" -> (proxy == args[0]); // Only consider equal when proxies are identical.
|
||||
case "hashCode" -> System.identityHashCode(proxy); // Use hashCode of proxy.
|
||||
case "toString" -> this.objectFactory.toString();
|
||||
default -> {
|
||||
try {
|
||||
yield method.invoke(this.objectFactory.getObject(), args);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw ex.getTargetException();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -81,9 +81,9 @@ class BeanDefinitionResource extends AbstractResource {
|
||||
* This implementation compares the underlying BeanDefinition.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(@Nullable Object other) {
|
||||
return (this == other || (other instanceof BeanDefinitionResource &&
|
||||
((BeanDefinitionResource) other).beanDefinition.equals(this.beanDefinition)));
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return (this == obj || (obj instanceof BeanDefinitionResource that &&
|
||||
this.beanDefinition.equals(that.beanDefinition)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -154,8 +154,8 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
|
||||
enhancer.setSuperclass(beanDefinition.getBeanClass());
|
||||
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
|
||||
enhancer.setAttemptLoad(true);
|
||||
if (this.owner instanceof ConfigurableBeanFactory) {
|
||||
ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader();
|
||||
if (this.owner instanceof ConfigurableBeanFactory cbf) {
|
||||
ClassLoader cl = cbf.getBeanClassLoader();
|
||||
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
|
||||
}
|
||||
enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -766,8 +766,8 @@ class ConstructorResolver {
|
||||
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
|
||||
}
|
||||
Object sourceHolder = valueHolder.getSource();
|
||||
if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
|
||||
Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
|
||||
if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder constructorValueHolder) {
|
||||
Object sourceValue = constructorValueHolder.getValue();
|
||||
args.resolveNecessary = true;
|
||||
args.preparedArguments[paramIndex] = sourceValue;
|
||||
}
|
||||
@@ -834,8 +834,8 @@ class ConstructorResolver {
|
||||
else if (argValue instanceof BeanMetadataElement) {
|
||||
argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
|
||||
}
|
||||
else if (argValue instanceof String) {
|
||||
argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd);
|
||||
else if (argValue instanceof String text) {
|
||||
argValue = this.beanFactory.evaluateBeanDefinitionString(text, mbd);
|
||||
}
|
||||
Class<?> paramType = paramTypes[argIndex];
|
||||
try {
|
||||
|
||||
+35
-24
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -200,12 +200,15 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
((DisposableBean) this.bean).destroy();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.warn(msg, ex);
|
||||
}
|
||||
else {
|
||||
logger.warn(msg + ": " + ex);
|
||||
if (logger.isWarnEnabled()) {
|
||||
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
|
||||
if (logger.isDebugEnabled()) {
|
||||
// Log at warn level like below but add the exception stacktrace only with debug level
|
||||
logger.warn(msg, ex);
|
||||
}
|
||||
else {
|
||||
logger.warn(msg + ": " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,12 +221,15 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
((AutoCloseable) this.bean).close();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
String msg = "Invocation of close method failed on bean with name '" + this.beanName + "'";
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.warn(msg, ex);
|
||||
}
|
||||
else {
|
||||
logger.warn(msg + ": " + ex);
|
||||
if (logger.isWarnEnabled()) {
|
||||
String msg = "Invocation of close method failed on bean with name '" + this.beanName + "'";
|
||||
if (logger.isDebugEnabled()) {
|
||||
// Log at warn level like below but add the exception stacktrace only with debug level
|
||||
logger.warn(msg, ex);
|
||||
}
|
||||
else {
|
||||
logger.warn(msg + ": " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -283,18 +289,23 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
destroyMethod.invoke(this.bean, args);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
String msg = "Custom destroy method '" + destroyMethod.getName() + "' on bean with name '" +
|
||||
this.beanName + "' threw an exception";
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.warn(msg, ex.getTargetException());
|
||||
}
|
||||
else {
|
||||
logger.warn(msg + ": " + ex.getTargetException());
|
||||
if (logger.isWarnEnabled()) {
|
||||
String msg = "Custom destroy method '" + destroyMethod.getName() + "' on bean with name '" +
|
||||
this.beanName + "' threw an exception";
|
||||
if (logger.isDebugEnabled()) {
|
||||
// Log at warn level like below but add the exception stacktrace only with debug level
|
||||
logger.warn(msg, ex.getTargetException());
|
||||
}
|
||||
else {
|
||||
logger.warn(msg + ": " + ex.getTargetException());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.warn("Failed to invoke custom destroy method '" + destroyMethod.getName() +
|
||||
"' on bean with name '" + this.beanName + "'", ex);
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Failed to invoke custom destroy method '" + destroyMethod.getName() +
|
||||
"' on bean with name '" + this.beanName + "'", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,8 +336,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
* @param beanDefinition the corresponding bean definition
|
||||
*/
|
||||
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
|
||||
return (bean instanceof DisposableBean
|
||||
|| inferDestroyMethodsIfNecessary(bean.getClass(), beanDefinition) != null);
|
||||
return (bean instanceof DisposableBean ||
|
||||
inferDestroyMethodsIfNecessary(bean.getClass(), beanDefinition) != null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -188,11 +188,11 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||
* @throws BeansException if the given bean cannot be exposed as a FactoryBean
|
||||
*/
|
||||
protected FactoryBean<?> getFactoryBean(String beanName, Object beanInstance) throws BeansException {
|
||||
if (!(beanInstance instanceof FactoryBean)) {
|
||||
if (!(beanInstance instanceof FactoryBean<?> factoryBean)) {
|
||||
throw new BeanCreationException(beanName,
|
||||
"Bean instance of type [" + beanInstance.getClass() + "] is not a FactoryBean");
|
||||
}
|
||||
return (FactoryBean<?>) beanInstance;
|
||||
return factoryBean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -83,8 +83,8 @@ public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCan
|
||||
ResolvableType targetType = null;
|
||||
boolean cacheType = false;
|
||||
RootBeanDefinition rbd = null;
|
||||
if (bdHolder.getBeanDefinition() instanceof RootBeanDefinition) {
|
||||
rbd = (RootBeanDefinition) bdHolder.getBeanDefinition();
|
||||
if (bdHolder.getBeanDefinition() instanceof RootBeanDefinition rootBeanDef) {
|
||||
rbd = rootBeanDef;
|
||||
}
|
||||
if (rbd != null) {
|
||||
targetType = rbd.targetType;
|
||||
@@ -161,8 +161,8 @@ public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCan
|
||||
if (decDef != null && this.beanFactory instanceof ConfigurableListableBeanFactory clbf) {
|
||||
if (clbf.containsBeanDefinition(decDef.getBeanName())) {
|
||||
BeanDefinition dbd = clbf.getMergedBeanDefinition(decDef.getBeanName());
|
||||
if (dbd instanceof RootBeanDefinition) {
|
||||
return (RootBeanDefinition) dbd;
|
||||
if (dbd instanceof RootBeanDefinition rootBeanDef) {
|
||||
return rootBeanDef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -75,11 +75,11 @@ public class ManagedProperties extends Properties implements Mergeable, BeanMeta
|
||||
if (parent == null) {
|
||||
return this;
|
||||
}
|
||||
if (!(parent instanceof Properties)) {
|
||||
if (!(parent instanceof Properties properties)) {
|
||||
throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]");
|
||||
}
|
||||
Properties merged = new ManagedProperties();
|
||||
merged.putAll((Properties) parent);
|
||||
merged.putAll(properties);
|
||||
merged.putAll(this);
|
||||
return merged;
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -433,10 +433,10 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {
|
||||
super.setInstanceSupplier(instanceSupplier);
|
||||
Method factoryMethod = (instanceSupplier instanceof InstanceSupplier<?> ?
|
||||
((InstanceSupplier<?>) instanceSupplier).getFactoryMethod() : null);
|
||||
public void setInstanceSupplier(@Nullable Supplier<?> supplier) {
|
||||
super.setInstanceSupplier(supplier);
|
||||
Method factoryMethod = (supplier instanceof InstanceSupplier<?> instanceSupplier ?
|
||||
instanceSupplier.getFactoryMethod() : null);
|
||||
if (factoryMethod != null) {
|
||||
setResolvedFactoryMethod(factoryMethod);
|
||||
}
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -365,8 +365,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
|
||||
for (Map.Entry<String, Object> entry : this.beans.entrySet()) {
|
||||
String beanName = entry.getKey();
|
||||
Object beanInstance = entry.getValue();
|
||||
if (beanInstance instanceof FactoryBean && !isFactoryType) {
|
||||
FactoryBean<?> factoryBean = (FactoryBean<?>) beanInstance;
|
||||
if (beanInstance instanceof FactoryBean<?> factoryBean && !isFactoryType) {
|
||||
Class<?> objectType = factoryBean.getObjectType();
|
||||
if ((includeNonSingletons || factoryBean.isSingleton()) &&
|
||||
objectType != null && (type == null || type.isAssignableFrom(objectType))) {
|
||||
@@ -409,9 +408,8 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
|
||||
String beanName = entry.getKey();
|
||||
Object beanInstance = entry.getValue();
|
||||
// Is bean a FactoryBean?
|
||||
if (beanInstance instanceof FactoryBean && !isFactoryType) {
|
||||
if (beanInstance instanceof FactoryBean<?> factory && !isFactoryType) {
|
||||
// Match object created by FactoryBean.
|
||||
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
|
||||
Class<?> objectType = factory.getObjectType();
|
||||
if ((includeNonSingletons || factory.isSingleton()) &&
|
||||
objectType != null && (type == null || type.isAssignableFrom(objectType))) {
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -76,11 +76,11 @@ public class BeanConfigurerSupport implements BeanFactoryAware, InitializingBean
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
|
||||
if (!(beanFactory instanceof ConfigurableListableBeanFactory clbf)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Bean configurer aspect needs to run in a ConfigurableListableBeanFactory: " + beanFactory);
|
||||
}
|
||||
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
|
||||
this.beanFactory = clbf;
|
||||
if (this.beanWiringInfoResolver == null) {
|
||||
this.beanWiringInfoResolver = createDefaultBeanWiringInfoResolver();
|
||||
}
|
||||
@@ -158,8 +158,7 @@ public class BeanConfigurerSupport implements BeanFactoryAware, InitializingBean
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
Throwable rootCause = ex.getMostSpecificCause();
|
||||
if (rootCause instanceof BeanCurrentlyInCreationException) {
|
||||
BeanCreationException bce = (BeanCreationException) rootCause;
|
||||
if (rootCause instanceof BeanCurrentlyInCreationException bce) {
|
||||
String bceBeanName = bce.getBeanName();
|
||||
if (bceBeanName != null && beanFactory.isCurrentlyInCreation(bceBeanName)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -916,14 +916,14 @@ public class BeanDefinitionParserDelegate {
|
||||
Element subElement = null;
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
Node node = nl.item(i);
|
||||
if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
|
||||
if (node instanceof Element currentElement && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
|
||||
!nodeNameEquals(node, META_ELEMENT)) {
|
||||
// Child element is what we're looking for.
|
||||
if (subElement != null) {
|
||||
error(elementName + " must not contain more than one sub-element", ele);
|
||||
}
|
||||
else {
|
||||
subElement = (Element) node;
|
||||
subElement = currentElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1158,8 +1158,8 @@ public class BeanDefinitionParserDelegate {
|
||||
|
||||
for (int i = 0; i < elementNodes.getLength(); i++) {
|
||||
Node node = elementNodes.item(i);
|
||||
if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
|
||||
target.add(parsePropertySubElement((Element) node, bd, defaultElementType));
|
||||
if (node instanceof Element currentElement && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
|
||||
target.add(parsePropertySubElement(currentElement, bd, defaultElementType));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1309,13 +1309,13 @@ public class BeanDefinitionParserDelegate {
|
||||
Element subElement = null;
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
Node node = nl.item(i);
|
||||
if (node instanceof Element) {
|
||||
if (node instanceof Element currentElement) {
|
||||
// Child element is what we're looking for.
|
||||
if (subElement != null) {
|
||||
error("<key> element must not contain more than one value sub-element", keyEle);
|
||||
}
|
||||
else {
|
||||
subElement = (Element) node;
|
||||
subElement = currentElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -120,8 +120,8 @@ public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver
|
||||
if (handlerOrClassName == null) {
|
||||
return null;
|
||||
}
|
||||
else if (handlerOrClassName instanceof NamespaceHandler) {
|
||||
return (NamespaceHandler) handlerOrClassName;
|
||||
else if (handlerOrClassName instanceof NamespaceHandler namespaceHandler) {
|
||||
return namespaceHandler;
|
||||
}
|
||||
else {
|
||||
String className = (String) handlerOrClassName;
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,8 +52,8 @@ public class XmlBeanDefinitionStoreException extends BeanDefinitionStoreExceptio
|
||||
*/
|
||||
public int getLineNumber() {
|
||||
Throwable cause = getCause();
|
||||
if (cause instanceof SAXParseException) {
|
||||
return ((SAXParseException) cause).getLineNumber();
|
||||
if (cause instanceof SAXParseException parseEx) {
|
||||
return parseEx.getLineNumber();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user