mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5acffaa72d |
@@ -1,4 +1,4 @@
|
||||
# <img src="src/docs/spring-framework.png" width="80" height="80"> Spring Framework [](https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-5.3.x?groups=Build") [](https://ge.spring.io/scans?search.rootProjectNames=spring)
|
||||
# <img src="src/docs/spring-framework.png" width="80" height="80"> Spring Framework [](https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-5.3.x?groups=Build")
|
||||
|
||||
This is the home of the Spring Framework: the foundation for all [Spring projects](https://spring.io/projects). Collectively the Spring Framework and the family of Spring projects are often referred to simply as "Spring".
|
||||
|
||||
|
||||
+32
-32
@@ -1,7 +1,7 @@
|
||||
plugins {
|
||||
id 'io.spring.dependency-management' version '1.0.9.RELEASE' apply false
|
||||
id 'io.spring.nohttp' version '0.0.5.RELEASE'
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.4.21' apply false
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.4.10' apply false
|
||||
id 'org.jetbrains.dokka' version '0.10.1' apply false
|
||||
id 'org.asciidoctor.jvm.convert' version '3.1.0'
|
||||
id 'org.asciidoctor.jvm.pdf' version '3.1.0'
|
||||
@@ -9,7 +9,7 @@ plugins {
|
||||
id "io.freefair.aspectj" version '5.1.1' apply false
|
||||
id "com.github.ben-manes.versions" version '0.28.0'
|
||||
id "me.champeau.gradle.jmh" version "0.5.0" apply false
|
||||
id "org.jetbrains.kotlin.plugin.serialization" version "1.4.21" apply false
|
||||
id "org.jetbrains.kotlin.plugin.serialization" version "1.4.10" apply false
|
||||
}
|
||||
|
||||
ext {
|
||||
@@ -25,18 +25,18 @@ configure(allprojects) { project ->
|
||||
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom "com.fasterxml.jackson:jackson-bom:2.12.0"
|
||||
mavenBom "io.netty:netty-bom:4.1.56.Final"
|
||||
mavenBom "io.projectreactor:reactor-bom:2020.0.3"
|
||||
mavenBom "com.fasterxml.jackson:jackson-bom:2.11.3"
|
||||
mavenBom "io.netty:netty-bom:4.1.53.Final"
|
||||
mavenBom "io.projectreactor:reactor-bom:2020.0.0"
|
||||
mavenBom "io.r2dbc:r2dbc-bom:Arabba-SR8"
|
||||
mavenBom "io.rsocket:rsocket-bom:1.1.0"
|
||||
mavenBom "org.eclipse.jetty:jetty-bom:9.4.35.v20201120"
|
||||
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.4.21"
|
||||
mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.4.2"
|
||||
mavenBom "org.eclipse.jetty:jetty-bom:9.4.33.v20201020"
|
||||
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.4.10"
|
||||
mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.4.0"
|
||||
mavenBom "org.junit:junit-bom:5.7.0"
|
||||
}
|
||||
dependencies {
|
||||
dependencySet(group: 'org.apache.logging.log4j', version: '2.14.0') {
|
||||
dependencySet(group: 'org.apache.logging.log4j', version: '2.13.3') {
|
||||
entry 'log4j-api'
|
||||
entry 'log4j-core'
|
||||
entry 'log4j-jul'
|
||||
@@ -53,7 +53,7 @@ configure(allprojects) { project ->
|
||||
entry 'aspectjtools'
|
||||
entry 'aspectjweaver'
|
||||
}
|
||||
dependencySet(group: 'org.codehaus.groovy', version: '3.0.7') {
|
||||
dependencySet(group: 'org.codehaus.groovy', version: '3.0.6') {
|
||||
entry 'groovy'
|
||||
entry 'groovy-jsr223'
|
||||
entry 'groovy-templates' // requires findbugs for warning-free compilation
|
||||
@@ -63,8 +63,8 @@ configure(allprojects) { project ->
|
||||
|
||||
dependency "io.reactivex:rxjava:1.3.8"
|
||||
dependency "io.reactivex:rxjava-reactive-streams:1.2.1"
|
||||
dependency "io.reactivex.rxjava2:rxjava:2.2.20"
|
||||
dependency "io.reactivex.rxjava3:rxjava:3.0.9"
|
||||
dependency "io.reactivex.rxjava2:rxjava:2.2.19"
|
||||
dependency "io.reactivex.rxjava3:rxjava:3.0.7"
|
||||
dependency "io.projectreactor.tools:blockhound:1.0.4.RELEASE"
|
||||
|
||||
dependency "com.caucho:hessian:4.0.63"
|
||||
@@ -73,9 +73,9 @@ configure(allprojects) { project ->
|
||||
exclude group: "stax", name: "stax-api"
|
||||
}
|
||||
dependency "com.google.code.gson:gson:2.8.6"
|
||||
dependency "com.google.protobuf:protobuf-java-util:3.14.0"
|
||||
dependency "com.google.protobuf:protobuf-java-util:3.13.0"
|
||||
dependency "com.googlecode.protobuf-java-format:protobuf-java-format:1.4"
|
||||
dependency("com.thoughtworks.xstream:xstream:1.4.14") {
|
||||
dependency("com.thoughtworks.xstream:xstream:1.4.13") {
|
||||
exclude group: "xpp3", name: "xpp3_min"
|
||||
exclude group: "xmlpull", name: "xmlpull"
|
||||
}
|
||||
@@ -95,8 +95,8 @@ configure(allprojects) { project ->
|
||||
}
|
||||
|
||||
dependency "com.h2database:h2:1.4.200"
|
||||
dependency "com.github.ben-manes.caffeine:caffeine:2.8.8"
|
||||
dependency "com.github.librepdf:openpdf:1.3.24"
|
||||
dependency "com.github.ben-manes.caffeine:caffeine:2.8.6"
|
||||
dependency "com.github.librepdf:openpdf:1.3.22"
|
||||
dependency "com.rometools:rome:1.15.0"
|
||||
dependency "commons-io:commons-io:2.5"
|
||||
dependency "io.vavr:vavr:0.10.3"
|
||||
@@ -123,23 +123,23 @@ configure(allprojects) { project ->
|
||||
dependency "net.sf.ehcache:ehcache:2.10.6"
|
||||
dependency "org.ehcache:jcache:1.0.1"
|
||||
dependency "org.ehcache:ehcache:3.4.0"
|
||||
dependency "org.hibernate:hibernate-core:5.4.27.Final"
|
||||
dependency "org.hibernate:hibernate-validator:6.2.0.Final"
|
||||
dependency "org.hibernate:hibernate-core:5.4.22.Final"
|
||||
dependency "org.hibernate:hibernate-validator:6.1.6.Final"
|
||||
dependency "org.webjars:webjars-locator-core:0.46"
|
||||
dependency "org.webjars:underscorejs:1.8.3"
|
||||
|
||||
dependencySet(group: 'org.apache.tomcat', version: '9.0.41') {
|
||||
dependencySet(group: 'org.apache.tomcat', version: '9.0.39') {
|
||||
entry 'tomcat-util'
|
||||
entry('tomcat-websocket') {
|
||||
exclude group: "org.apache.tomcat", name: "tomcat-websocket-api"
|
||||
exclude group: "org.apache.tomcat", name: "tomcat-servlet-api"
|
||||
}
|
||||
}
|
||||
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.41') {
|
||||
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.39') {
|
||||
entry 'tomcat-embed-core'
|
||||
entry 'tomcat-embed-websocket'
|
||||
}
|
||||
dependencySet(group: 'io.undertow', version: '2.2.3.Final') {
|
||||
dependencySet(group: 'io.undertow', version: '2.2.2.Final') {
|
||||
entry 'undertow-core'
|
||||
entry('undertow-websockets-jsr') {
|
||||
exclude group: "org.jboss.spec.javax.websocket", name: "jboss-websocket-api_1.1_spec"
|
||||
@@ -154,15 +154,15 @@ configure(allprojects) { project ->
|
||||
entry 'okhttp'
|
||||
entry 'mockwebserver'
|
||||
}
|
||||
dependency("org.apache.httpcomponents:httpclient:4.5.13") {
|
||||
dependency("org.apache.httpcomponents:httpclient:4.5.12") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.apache.httpcomponents:httpasyncclient:4.1.4") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency 'org.apache.httpcomponents.client5:httpclient5:5.0.3'
|
||||
dependency 'org.apache.httpcomponents.core5:httpcore5-reactive:5.0.3'
|
||||
dependency "org.eclipse.jetty:jetty-reactive-httpclient:1.1.5"
|
||||
dependency 'org.apache.httpcomponents.core5:httpcore5-reactive:5.0.2'
|
||||
dependency "org.eclipse.jetty:jetty-reactive-httpclient:1.1.4"
|
||||
|
||||
dependency "org.jruby:jruby:9.2.13.0"
|
||||
dependency "org.python:jython-standalone:2.7.1"
|
||||
@@ -190,25 +190,25 @@ configure(allprojects) { project ->
|
||||
dependency "org.testng:testng:7.3.0"
|
||||
dependency "org.hamcrest:hamcrest:2.1"
|
||||
dependency "org.awaitility:awaitility:3.1.6"
|
||||
dependency "org.assertj:assertj-core:3.18.1"
|
||||
dependencySet(group: 'org.xmlunit', version: '2.8.2') {
|
||||
dependency "org.assertj:assertj-core:3.17.2"
|
||||
dependencySet(group: 'org.xmlunit', version: '2.6.2') {
|
||||
entry 'xmlunit-assertj'
|
||||
entry('xmlunit-matchers') {
|
||||
exclude group: "org.hamcrest", name: "hamcrest-core"
|
||||
}
|
||||
}
|
||||
dependencySet(group: 'org.mockito', version: '3.7.0') {
|
||||
dependencySet(group: 'org.mockito', version: '3.5.15') {
|
||||
entry('mockito-core') {
|
||||
exclude group: "org.hamcrest", name: "hamcrest-core"
|
||||
}
|
||||
entry 'mockito-junit-jupiter'
|
||||
}
|
||||
dependency "io.mockk:mockk:1.10.2"
|
||||
dependency "io.mockk:mockk:1.10.0"
|
||||
|
||||
dependency("net.sourceforge.htmlunit:htmlunit:2.46.0") {
|
||||
dependency("net.sourceforge.htmlunit:htmlunit:2.44.0") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.seleniumhq.selenium:htmlunit-driver:2.46.0") {
|
||||
dependency("org.seleniumhq.selenium:htmlunit-driver:2.44.0") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.seleniumhq.selenium:selenium-java:3.141.59") {
|
||||
@@ -236,7 +236,7 @@ configure(allprojects) { project ->
|
||||
|
||||
dependency "com.ibm.websphere:uow:6.0.2.17"
|
||||
dependency "com.jamonapi:jamon:2.82"
|
||||
dependency "joda-time:joda-time:2.10.9"
|
||||
dependency "joda-time:joda-time:2.10.6"
|
||||
dependency "org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.7"
|
||||
dependency "org.javamoney:moneta:1.3"
|
||||
|
||||
@@ -339,7 +339,7 @@ configure([rootProject] + javaProjects) { project ->
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
toolVersion = "8.39"
|
||||
toolVersion = "8.36.2"
|
||||
configDirectory.set(rootProject.file("src/checkstyle"))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
logging:
|
||||
level:
|
||||
io.spring.concourse: DEBUG
|
||||
distribute:
|
||||
optional-deployments:
|
||||
- '.*\\.zip'
|
||||
spring:
|
||||
main:
|
||||
banner-mode: off
|
||||
@@ -3,13 +3,16 @@ set -e
|
||||
|
||||
case "$1" in
|
||||
java8)
|
||||
echo "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u275-b01/OpenJDK8U-jdk_x64_linux_hotspot_8u275b01.tar.gz"
|
||||
echo "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u265-b01/OpenJDK8U-jdk_x64_linux_hotspot_8u265b01.tar.gz"
|
||||
;;
|
||||
java11)
|
||||
echo "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.9.1%2B1/OpenJDK11U-jdk_x64_linux_hotspot_11.0.9.1_1.tar.gz"
|
||||
echo "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.8%2B10/OpenJDK11U-jdk_x64_linux_hotspot_11.0.8_10.tar.gz"
|
||||
;;
|
||||
java14)
|
||||
echo "https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/download/jdk-14.0.2%2B12/OpenJDK14U-jdk_x64_linux_hotspot_14.0.2_12.tar.gz"
|
||||
;;
|
||||
java15)
|
||||
echo "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15.0.1%2B9/OpenJDK15U-jdk_x64_linux_hotspot_15.0.1_9.tar.gz"
|
||||
echo "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15%2B36/OpenJDK15U-jdk_x64_linux_hotspot_15_36.tar.gz"
|
||||
;;
|
||||
*)
|
||||
echo $"Unknown java version"
|
||||
|
||||
+1
-4
@@ -5,11 +5,8 @@ set -ex
|
||||
# UTILS
|
||||
###########################################################
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update
|
||||
apt-get install --no-install-recommends -y tzdata ca-certificates net-tools libxml2-utils git curl libudev1 libxml2-utils iptables iproute2 jq fontconfig
|
||||
ln -fs /usr/share/zoneinfo/UTC /etc/localtime
|
||||
dpkg-reconfigure --frontend noninteractive tzdata
|
||||
apt-get install --no-install-recommends -y ca-certificates net-tools libxml2-utils git curl libudev1 libxml2-utils iptables iproute2 jq fontconfig
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
curl https://raw.githubusercontent.com/spring-io/concourse-java-scripts/v0.0.3/concourse-java.sh > /opt/concourse-java.sh
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:focal-20201106
|
||||
FROM ubuntu:bionic-20200713
|
||||
|
||||
ADD setup.sh /setup.sh
|
||||
ADD get-jdk-url.sh /get-jdk-url.sh
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:focal-20201106
|
||||
FROM ubuntu:bionic-20200713
|
||||
|
||||
ADD setup.sh /setup.sh
|
||||
ADD get-jdk-url.sh /get-jdk-url.sh
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
FROM ubuntu:bionic-20200713
|
||||
|
||||
ADD setup.sh /setup.sh
|
||||
ADD get-jdk-url.sh /get-jdk-url.sh
|
||||
RUN ./setup.sh java14
|
||||
|
||||
ENV JAVA_HOME /opt/openjdk
|
||||
ENV PATH $JAVA_HOME/bin:$PATH
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:focal-20201106
|
||||
FROM ubuntu:bionic-20200713
|
||||
|
||||
ADD setup.sh /setup.sh
|
||||
ADD get-jdk-url.sh /get-jdk-url.sh
|
||||
|
||||
+50
-4
@@ -37,17 +37,17 @@ anchors:
|
||||
|
||||
resource_types:
|
||||
- name: artifactory-resource
|
||||
type: registry-image
|
||||
type: docker-image
|
||||
source:
|
||||
repository: springio/artifactory-resource
|
||||
tag: 0.0.12
|
||||
- name: github-status-resource
|
||||
type: registry-image
|
||||
type: docker-image
|
||||
source:
|
||||
repository: dpb587/github-status-resource
|
||||
tag: master
|
||||
- name: slack-notification
|
||||
type: registry-image
|
||||
type: docker-image
|
||||
source:
|
||||
repository: cfcommunity/slack-notification-resource
|
||||
tag: latest
|
||||
@@ -87,6 +87,12 @@ resources:
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: ((docker-hub-organization))/spring-framework-jdk11-ci-image
|
||||
- name: spring-framework-jdk14-ci-image
|
||||
type: docker-image
|
||||
icon: docker
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: ((docker-hub-organization))/spring-framework-jdk14-ci-image
|
||||
- name: spring-framework-jdk15-ci-image
|
||||
type: docker-image
|
||||
icon: docker
|
||||
@@ -117,6 +123,14 @@ resources:
|
||||
access_token: ((github-ci-status-token))
|
||||
branch: ((branch))
|
||||
context: jdk11-build
|
||||
- name: repo-status-jdk14-build
|
||||
type: github-status-resource
|
||||
icon: eye-check-outline
|
||||
source:
|
||||
repository: ((github-repo-name))
|
||||
access_token: ((github-ci-status-token))
|
||||
branch: ((branch))
|
||||
context: jdk14-build
|
||||
- name: repo-status-jdk15-build
|
||||
type: github-status-resource
|
||||
icon: eye-check-outline
|
||||
@@ -162,6 +176,10 @@ jobs:
|
||||
params:
|
||||
build: ci-images-git-repo/ci/images
|
||||
dockerfile: ci-images-git-repo/ci/images/spring-framework-jdk11-ci-image/Dockerfile
|
||||
- put: spring-framework-jdk14-ci-image
|
||||
params:
|
||||
build: ci-images-git-repo/ci/images
|
||||
dockerfile: ci-images-git-repo/ci/images/spring-framework-jdk14-ci-image/Dockerfile
|
||||
- put: spring-framework-jdk15-ci-image
|
||||
params:
|
||||
build: ci-images-git-repo/ci/images
|
||||
@@ -250,6 +268,34 @@ jobs:
|
||||
<<: *slack-fail-params
|
||||
- put: repo-status-jdk11-build
|
||||
params: { state: "success", commit: "git-repo" }
|
||||
- name: jdk14-build
|
||||
serial: true
|
||||
public: true
|
||||
plan:
|
||||
- get: spring-framework-jdk14-ci-image
|
||||
- get: git-repo
|
||||
- get: every-morning
|
||||
trigger: true
|
||||
- put: repo-status-jdk14-build
|
||||
params: { state: "pending", commit: "git-repo" }
|
||||
- do:
|
||||
- task: check-project
|
||||
privileged: true
|
||||
timeout: ((task-timeout))
|
||||
image: spring-framework-jdk14-ci-image
|
||||
file: git-repo/ci/tasks/check-project.yml
|
||||
params:
|
||||
BRANCH: ((branch))
|
||||
<<: *gradle-enterprise-task-params
|
||||
on_failure:
|
||||
do:
|
||||
- put: repo-status-jdk14-build
|
||||
params: { state: "failure", commit: "git-repo" }
|
||||
- put: slack-alert
|
||||
params:
|
||||
<<: *slack-fail-params
|
||||
- put: repo-status-jdk14-build
|
||||
params: { state: "success", commit: "git-repo" }
|
||||
- name: jdk15-build
|
||||
serial: true
|
||||
public: true
|
||||
@@ -434,7 +480,7 @@ jobs:
|
||||
|
||||
groups:
|
||||
- name: "builds"
|
||||
jobs: ["build", "jdk11-build", "jdk15-build"]
|
||||
jobs: ["build", "jdk11-build", "jdk14-build", "jdk15-build"]
|
||||
- name: "releases"
|
||||
jobs: ["stage-milestone", "stage-rc", "stage-release", "promote-milestone","promote-rc", "promote-release", "sync-to-maven-central"]
|
||||
- name: "ci-images"
|
||||
|
||||
@@ -6,11 +6,11 @@ CONFIG_DIR=git-repo/ci/config
|
||||
version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
|
||||
export BUILD_INFO_LOCATION=$(pwd)/artifactory-repo/build-info.json
|
||||
|
||||
java -jar /opt/concourse-release-scripts.jar promote $RELEASE_TYPE $BUILD_INFO_LOCATION || { exit 1; }
|
||||
java -jar /opt/concourse-release-scripts.jar promote $RELEASE_TYPE $BUILD_INFO_LOCATION > /dev/null || { exit 1; }
|
||||
|
||||
java -jar /opt/concourse-release-scripts.jar \
|
||||
--spring.config.location=${CONFIG_DIR}/release-scripts.yml \
|
||||
distribute $RELEASE_TYPE $BUILD_INFO_LOCATION || { exit 1; }
|
||||
distribute $RELEASE_TYPE $BUILD_INFO_LOCATION > /dev/null || { exit 1; }
|
||||
|
||||
echo "Promotion complete"
|
||||
echo $version > version/version
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
version=5.3.3
|
||||
version=5.3.0
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
org.gradle.caching=true
|
||||
org.gradle.parallel=true
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@ configurations {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
asciidoctorExt("io.spring.asciidoctor:spring-asciidoctor-extensions-block-switch:0.5.0")
|
||||
asciidoctorExt("io.spring.asciidoctor:spring-asciidoctor-extensions-block-switch:0.4.3.RELEASE")
|
||||
}
|
||||
|
||||
repositories {
|
||||
@@ -113,7 +113,7 @@ dokka {
|
||||
}
|
||||
|
||||
task downloadResources(type: Download) {
|
||||
def version = "0.2.5"
|
||||
def version = "0.2.2.RELEASE"
|
||||
src "https://repo.spring.io/release/io/spring/docresources/" +
|
||||
"spring-doc-resources/$version/spring-doc-resources-${version}.zip"
|
||||
dest project.file("$buildDir/docs/spring-doc-resources.zip")
|
||||
|
||||
+2
-18
@@ -29,11 +29,12 @@ eclipse.classpath.file.whenMerged { classpath ->
|
||||
classpath.entries.removeAll { entry -> (entry.path =~ /(?!.*?repack.*\.jar).*?\/([^\/]+)\/build\/libs\/[^\/]+\.jar/) }
|
||||
}
|
||||
|
||||
|
||||
// Use separate main/test outputs (prevents WTP from packaging test classes)
|
||||
eclipse.classpath.defaultOutputDir = file(project.name+"/bin/eclipse")
|
||||
eclipse.classpath.file.beforeMerged { classpath ->
|
||||
classpath.entries.findAll{ it instanceof SourceFolder }.each {
|
||||
if (it.output.startsWith("bin/")) {
|
||||
if(it.output.startsWith("bin/")) {
|
||||
it.output = null
|
||||
}
|
||||
}
|
||||
@@ -55,23 +56,6 @@ eclipse.classpath.file.whenMerged { classpath ->
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that test fixture dependencies are handled properly in Gradle 6.7.
|
||||
// Bug fixed in Gradle 6.8: https://github.com/gradle/gradle/issues/14932
|
||||
eclipse.classpath.file.whenMerged {
|
||||
entries.findAll { it instanceof ProjectDependency }.each {
|
||||
it.entryAttributes.remove('without_test_code')
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that JMH sources and resources are treated as test classpath entries
|
||||
// so that they can see test fixtures.
|
||||
// https://github.com/melix/jmh-gradle-plugin/issues/157
|
||||
eclipse.classpath.file.whenMerged {
|
||||
entries.findAll { it.path =~ /src\/jmh\/(java|resources)/ }.each {
|
||||
it.entryAttributes['test'] = 'true'
|
||||
}
|
||||
}
|
||||
|
||||
// Allow projects to be used as WTP modules
|
||||
eclipse.project.natures "org.eclipse.wst.common.project.facet.core.nature"
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
+13
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -350,8 +350,17 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
return this.discoveredThrowingType;
|
||||
}
|
||||
|
||||
private static boolean isVariableName(String name) {
|
||||
return AspectJProxyUtils.isVariableName(name);
|
||||
private boolean isVariableName(String name) {
|
||||
char[] chars = name.toCharArray();
|
||||
if (!Character.isJavaIdentifierStart(chars[0])) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 1; i < chars.length; i++) {
|
||||
if (!Character.isJavaIdentifierPart(chars[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -631,6 +640,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
try {
|
||||
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
|
||||
// TODO AopUtils.invokeJoinpointUsingReflection
|
||||
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
|
||||
+14
-2
@@ -470,10 +470,22 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
*/
|
||||
@Nullable
|
||||
private String maybeExtractVariableName(@Nullable String candidateToken) {
|
||||
if (AspectJProxyUtils.isVariableName(candidateToken)) {
|
||||
if (!StringUtils.hasLength(candidateToken)) {
|
||||
return null;
|
||||
}
|
||||
if (Character.isJavaIdentifierStart(candidateToken.charAt(0)) &&
|
||||
Character.isLowerCase(candidateToken.charAt(0))) {
|
||||
char[] tokenChars = candidateToken.toCharArray();
|
||||
for (char tokenChar : tokenChars) {
|
||||
if (!Character.isJavaIdentifierPart(tokenChar)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return candidateToken;
|
||||
}
|
||||
return null;
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,8 +21,6 @@ import java.util.List;
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.PointcutAdvisor;
|
||||
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Utility methods for working with AspectJ proxies.
|
||||
@@ -75,19 +73,4 @@ public abstract class AspectJProxyUtils {
|
||||
((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut));
|
||||
}
|
||||
|
||||
static boolean isVariableName(@Nullable String name) {
|
||||
if (!StringUtils.hasLength(name)) {
|
||||
return false;
|
||||
}
|
||||
if (!Character.isJavaIdentifierStart(name.charAt(0))) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 1; i < name.length(); i++) {
|
||||
if (!Character.isJavaIdentifierPart(name.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-5
@@ -221,12 +221,10 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
@Override
|
||||
@Nullable
|
||||
public String[] getParameterNames() {
|
||||
String[] parameterNames = this.parameterNames;
|
||||
if (parameterNames == null) {
|
||||
parameterNames = parameterNameDiscoverer.getParameterNames(getMethod());
|
||||
this.parameterNames = parameterNames;
|
||||
if (this.parameterNames == null) {
|
||||
this.parameterNames = parameterNameDiscoverer.getParameterNames(getMethod());
|
||||
}
|
||||
return parameterNames;
|
||||
return this.parameterNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+16
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -160,12 +160,23 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the singleton aspect instance for the supplied aspect type.
|
||||
* An instance is created if one cannot be found in the instance cache.
|
||||
* Get the singleton aspect instance for the supplied aspect type. An instance
|
||||
* is created if one cannot be found in the instance cache.
|
||||
*/
|
||||
private Object getSingletonAspectInstance(Class<?> aspectClass) {
|
||||
return aspectCache.computeIfAbsent(aspectClass,
|
||||
clazz -> new SimpleAspectInstanceFactory(clazz).getAspectInstance());
|
||||
// Quick check without a lock...
|
||||
Object instance = aspectCache.get(aspectClass);
|
||||
if (instance == null) {
|
||||
synchronized (aspectCache) {
|
||||
// To be safe, check within full lock now...
|
||||
instance = aspectCache.get(aspectClass);
|
||||
if (instance == null) {
|
||||
instance = new SimpleAspectInstanceFactory(aspectClass).getAspectInstance();
|
||||
aspectCache.put(aspectClass, instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+10
-10
@@ -51,7 +51,6 @@ import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConvertingComparator;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.ReflectionUtils.MethodFilter;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.comparator.InstanceComparator;
|
||||
|
||||
@@ -71,11 +70,7 @@ import org.springframework.util.comparator.InstanceComparator;
|
||||
@SuppressWarnings("serial")
|
||||
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
|
||||
|
||||
// Exclude @Pointcut methods
|
||||
private static final MethodFilter adviceMethodFilter = ReflectionUtils.USER_DECLARED_METHODS
|
||||
.and(method -> (AnnotationUtils.getAnnotation(method, Pointcut.class) == null));
|
||||
|
||||
private static final Comparator<Method> adviceMethodComparator;
|
||||
private static final Comparator<Method> METHOD_COMPARATOR;
|
||||
|
||||
static {
|
||||
// Note: although @After is ordered before @AfterReturning and @AfterThrowing,
|
||||
@@ -91,7 +86,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
return (ann != null ? ann.getAnnotation() : null);
|
||||
});
|
||||
Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
|
||||
adviceMethodComparator = adviceKindComparator.thenComparing(methodNameComparator);
|
||||
METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
|
||||
}
|
||||
|
||||
|
||||
@@ -165,10 +160,15 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
}
|
||||
|
||||
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
|
||||
List<Method> methods = new ArrayList<>();
|
||||
ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter);
|
||||
final List<Method> methods = new ArrayList<>();
|
||||
ReflectionUtils.doWithMethods(aspectClass, method -> {
|
||||
// Exclude pointcuts
|
||||
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
|
||||
methods.add(method);
|
||||
}
|
||||
}, ReflectionUtils.USER_DECLARED_METHODS);
|
||||
if (methods.size() > 1) {
|
||||
methods.sort(adviceMethodComparator);
|
||||
methods.sort(METHOD_COMPARATOR);
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -114,15 +114,6 @@ public interface Advised extends TargetClassAware {
|
||||
*/
|
||||
Advisor[] getAdvisors();
|
||||
|
||||
/**
|
||||
* Return the number of advisors applying to this proxy.
|
||||
* <p>The default implementation delegates to {@code getAdvisors().length}.
|
||||
* @since 5.3.1
|
||||
*/
|
||||
default int getAdvisorCount() {
|
||||
return getAdvisors().length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an advisor at the end of the advisor chain.
|
||||
* <p>The Advisor may be an {@link org.springframework.aop.IntroductionAdvisor},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -95,6 +95,12 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
*/
|
||||
private List<Advisor> advisors = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Array updated on changes to the advisors list, which is easier
|
||||
* to manipulate internally.
|
||||
*/
|
||||
private Advisor[] advisorArray = new Advisor[0];
|
||||
|
||||
|
||||
/**
|
||||
* No-arg constructor for use as a JavaBean.
|
||||
@@ -238,12 +244,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
|
||||
@Override
|
||||
public final Advisor[] getAdvisors() {
|
||||
return this.advisors.toArray(new Advisor[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAdvisorCount() {
|
||||
return this.advisors.size();
|
||||
return this.advisorArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -291,6 +292,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
}
|
||||
}
|
||||
|
||||
updateAdvisorArray();
|
||||
adviceChanged();
|
||||
}
|
||||
|
||||
@@ -337,6 +339,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
Assert.notNull(advisor, "Advisor must not be null");
|
||||
this.advisors.add(advisor);
|
||||
}
|
||||
updateAdvisorArray();
|
||||
adviceChanged();
|
||||
}
|
||||
}
|
||||
@@ -360,18 +363,27 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
"Illegal position " + pos + " in advisor list with size " + this.advisors.size());
|
||||
}
|
||||
this.advisors.add(pos, advisor);
|
||||
updateAdvisorArray();
|
||||
adviceChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Bring the array up to date with the list.
|
||||
*/
|
||||
protected final void updateAdvisorArray() {
|
||||
this.advisorArray = this.advisors.toArray(new Advisor[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows uncontrolled access to the {@link List} of {@link Advisor Advisors}.
|
||||
* <p>Use with care, and remember to {@link #adviceChanged() fire advice changed events}
|
||||
* when making any modifications.
|
||||
* <p>Use with care, and remember to {@link #updateAdvisorArray() refresh the advisor array}
|
||||
* and {@link #adviceChanged() fire advice changed events} when making any modifications.
|
||||
*/
|
||||
protected final List<Advisor> getAdvisorsInternal() {
|
||||
return this.advisors;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addAdvice(Advice advice) throws AopConfigException {
|
||||
int pos = this.advisors.size();
|
||||
@@ -509,6 +521,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
Assert.notNull(advisor, "Advisor must not be null");
|
||||
this.advisors.add(advisor);
|
||||
}
|
||||
updateAdvisorArray();
|
||||
adviceChanged();
|
||||
}
|
||||
|
||||
@@ -523,6 +536,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
copy.advisorChainFactory = this.advisorChainFactory;
|
||||
copy.interfaces = this.interfaces;
|
||||
copy.advisors = this.advisors;
|
||||
copy.updateAdvisorArray();
|
||||
return copy;
|
||||
}
|
||||
|
||||
@@ -539,6 +553,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
this.methodCache = new ConcurrentHashMap<>(32);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toProxyConfigString() {
|
||||
return toString();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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,7 +206,7 @@ public abstract class AopProxyUtils {
|
||||
* Check equality of the advisors behind the given AdvisedSupport objects.
|
||||
*/
|
||||
public static boolean equalsAdvisors(AdvisedSupport a, AdvisedSupport b) {
|
||||
return a.getAdvisorCount() == b.getAdvisorCount() && Arrays.equals(a.getAdvisors(), b.getAdvisors());
|
||||
return Arrays.equals(a.getAdvisors(), b.getAdvisors());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ import org.springframework.cglib.proxy.Factory;
|
||||
import org.springframework.cglib.proxy.MethodInterceptor;
|
||||
import org.springframework.cglib.proxy.MethodProxy;
|
||||
import org.springframework.cglib.proxy.NoOp;
|
||||
import org.springframework.core.KotlinDetector;
|
||||
import org.springframework.core.SmartClassLoader;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -126,7 +125,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
*/
|
||||
public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
|
||||
Assert.notNull(config, "AdvisedSupport must not be null");
|
||||
if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
|
||||
if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
|
||||
throw new AopConfigException("No advisors and no TargetSource specified");
|
||||
}
|
||||
this.advised = config;
|
||||
@@ -753,17 +752,10 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ReflectionUtils.declaresException(getMethod(), ex.getClass()) ||
|
||||
KotlinDetector.isKotlinType(getMethod().getDeclaringClass())) {
|
||||
// Propagate original exception if declared on the target method
|
||||
// (with callers expecting it). Always propagate it for Kotlin code
|
||||
// since checked exceptions do not have to be explicitly declared there.
|
||||
if (ReflectionUtils.declaresException(getMethod(), ex.getClass())) {
|
||||
throw ex;
|
||||
}
|
||||
else {
|
||||
// Checked exception thrown in the interceptor but not declared on the
|
||||
// target method signature -> apply an UndeclaredThrowableException,
|
||||
// aligned with standard JDK dynamic proxy behavior.
|
||||
throw new UndeclaredThrowableException(ex);
|
||||
}
|
||||
}
|
||||
@@ -950,11 +942,11 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
// Advice instance identity is unimportant to the proxy class:
|
||||
// All that matters is type and ordering.
|
||||
if (this.advised.getAdvisorCount() != otherAdvised.getAdvisorCount()) {
|
||||
return false;
|
||||
}
|
||||
Advisor[] thisAdvisors = this.advised.getAdvisors();
|
||||
Advisor[] thatAdvisors = otherAdvised.getAdvisors();
|
||||
if (thisAdvisors.length != thatAdvisors.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < thisAdvisors.length; i++) {
|
||||
Advisor thisAdvisor = thisAdvisors[i];
|
||||
Advisor thatAdvisor = thatAdvisors[i];
|
||||
|
||||
@@ -104,7 +104,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
*/
|
||||
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
|
||||
Assert.notNull(config, "AdvisedSupport must not be null");
|
||||
if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
|
||||
if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
|
||||
throw new AopConfigException("No advisors and no TargetSource specified");
|
||||
}
|
||||
this.advised = config;
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2017 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,8 +59,7 @@ public abstract aspect AbstractTransactionAspect extends TransactionAspectSuppor
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// An aspect is basically a singleton -> cleanup on destruction
|
||||
clearTransactionManagerCache();
|
||||
clearTransactionManagerCache(); // An aspect is basically a singleton
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
|
||||
+3
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -422,12 +422,9 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (this.suppressNotWritablePropertyException) {
|
||||
// Optimization for common ignoreUnknown=true scenario since the
|
||||
// exception would be caught and swallowed higher up anyway...
|
||||
return;
|
||||
else {
|
||||
throw createNotWritablePropertyException(tokens.canonicalName);
|
||||
}
|
||||
throw createNotWritablePropertyException(tokens.canonicalName);
|
||||
}
|
||||
|
||||
Object oldValue = null;
|
||||
|
||||
+22
-35
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -40,8 +40,6 @@ public abstract class AbstractPropertyAccessor extends TypeConverterSupport impl
|
||||
|
||||
private boolean autoGrowNestedPaths = false;
|
||||
|
||||
boolean suppressNotWritablePropertyException = false;
|
||||
|
||||
|
||||
@Override
|
||||
public void setExtractOldValueForEditor(boolean extractOldValueForEditor) {
|
||||
@@ -91,41 +89,30 @@ public abstract class AbstractPropertyAccessor extends TypeConverterSupport impl
|
||||
List<PropertyAccessException> propertyAccessExceptions = null;
|
||||
List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ?
|
||||
((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));
|
||||
|
||||
if (ignoreUnknown) {
|
||||
this.suppressNotWritablePropertyException = true;
|
||||
}
|
||||
try {
|
||||
for (PropertyValue pv : propertyValues) {
|
||||
// setPropertyValue may throw any BeansException, which won't be caught
|
||||
for (PropertyValue pv : propertyValues) {
|
||||
try {
|
||||
// This method may throw any BeansException, which won't be caught
|
||||
// here, if there is a critical failure such as no matching field.
|
||||
// We can attempt to deal only with less serious exceptions.
|
||||
try {
|
||||
setPropertyValue(pv);
|
||||
}
|
||||
catch (NotWritablePropertyException ex) {
|
||||
if (!ignoreUnknown) {
|
||||
throw ex;
|
||||
}
|
||||
// Otherwise, just ignore it and continue...
|
||||
}
|
||||
catch (NullValueInNestedPathException ex) {
|
||||
if (!ignoreInvalid) {
|
||||
throw ex;
|
||||
}
|
||||
// Otherwise, just ignore it and continue...
|
||||
}
|
||||
catch (PropertyAccessException ex) {
|
||||
if (propertyAccessExceptions == null) {
|
||||
propertyAccessExceptions = new ArrayList<>();
|
||||
}
|
||||
propertyAccessExceptions.add(ex);
|
||||
}
|
||||
setPropertyValue(pv);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (ignoreUnknown) {
|
||||
this.suppressNotWritablePropertyException = false;
|
||||
catch (NotWritablePropertyException ex) {
|
||||
if (!ignoreUnknown) {
|
||||
throw ex;
|
||||
}
|
||||
// Otherwise, just ignore it and continue...
|
||||
}
|
||||
catch (NullValueInNestedPathException ex) {
|
||||
if (!ignoreInvalid) {
|
||||
throw ex;
|
||||
}
|
||||
// Otherwise, just ignore it and continue...
|
||||
}
|
||||
catch (PropertyAccessException ex) {
|
||||
if (propertyAccessExceptions == null) {
|
||||
propertyAccessExceptions = new ArrayList<>();
|
||||
}
|
||||
propertyAccessExceptions.add(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -543,7 +543,6 @@ public abstract class BeanUtils {
|
||||
if (targetType == null || targetType.isArray() || unknownEditorTypes.contains(targetType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ClassLoader cl = targetType.getClassLoader();
|
||||
if (cl == null) {
|
||||
try {
|
||||
@@ -560,34 +559,28 @@ public abstract class BeanUtils {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String targetTypeName = targetType.getName();
|
||||
String editorName = targetTypeName + "Editor";
|
||||
try {
|
||||
Class<?> editorClass = cl.loadClass(editorName);
|
||||
if (editorClass != null) {
|
||||
if (!PropertyEditor.class.isAssignableFrom(editorClass)) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Editor class [" + editorName +
|
||||
"] does not implement [java.beans.PropertyEditor] interface");
|
||||
}
|
||||
unknownEditorTypes.add(targetType);
|
||||
return null;
|
||||
if (!PropertyEditor.class.isAssignableFrom(editorClass)) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Editor class [" + editorName +
|
||||
"] does not implement [java.beans.PropertyEditor] interface");
|
||||
}
|
||||
return (PropertyEditor) instantiateClass(editorClass);
|
||||
unknownEditorTypes.add(targetType);
|
||||
return null;
|
||||
}
|
||||
// Misbehaving ClassLoader returned null instead of ClassNotFoundException
|
||||
// - fall back to unknown editor type registration below
|
||||
return (PropertyEditor) instantiateClass(editorClass);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Ignore - fall back to unknown editor type registration below
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("No property editor [" + editorName + "] found for type " +
|
||||
targetTypeName + " according to 'Editor' suffix convention");
|
||||
}
|
||||
unknownEditorTypes.add(targetType);
|
||||
return null;
|
||||
}
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("No property editor [" + editorName + "] found for type " +
|
||||
targetTypeName + " according to 'Editor' suffix convention");
|
||||
}
|
||||
unknownEditorTypes.add(targetType);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -92,7 +92,8 @@ public class DirectFieldAccessor extends AbstractNestablePropertyAccessor {
|
||||
@Override
|
||||
protected NotWritablePropertyException createNotWritablePropertyException(String propertyName) {
|
||||
PropertyMatches matches = PropertyMatches.forField(propertyName, getRootClass());
|
||||
throw new NotWritablePropertyException(getRootClass(), getNestedPath() + propertyName,
|
||||
throw new NotWritablePropertyException(
|
||||
getRootClass(), getNestedPath() + propertyName,
|
||||
matches.buildErrorMessage(), matches.getPossibleMatches());
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -644,20 +644,21 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
}
|
||||
synchronized (this) {
|
||||
if (!this.cached) {
|
||||
Object cachedFieldValue = null;
|
||||
if (value != null || this.required) {
|
||||
cachedFieldValue = desc;
|
||||
this.cachedFieldValue = desc;
|
||||
registerDependentBeans(beanName, autowiredBeanNames);
|
||||
if (autowiredBeanNames.size() == 1) {
|
||||
String autowiredBeanName = autowiredBeanNames.iterator().next();
|
||||
if (beanFactory.containsBean(autowiredBeanName) &&
|
||||
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
|
||||
cachedFieldValue = new ShortcutDependencyDescriptor(
|
||||
this.cachedFieldValue = new ShortcutDependencyDescriptor(
|
||||
desc, autowiredBeanName, field.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
this.cachedFieldValue = cachedFieldValue;
|
||||
else {
|
||||
this.cachedFieldValue = null;
|
||||
}
|
||||
this.cached = true;
|
||||
}
|
||||
}
|
||||
|
||||
+14
-3
@@ -26,6 +26,9 @@ import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.PropertyValues;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
@@ -66,6 +69,8 @@ public class InjectionMetadata {
|
||||
};
|
||||
|
||||
|
||||
private static final Log logger = LogFactory.getLog(InjectionMetadata.class);
|
||||
|
||||
private final Class<?> targetClass;
|
||||
|
||||
private final Collection<InjectedElement> injectedElements;
|
||||
@@ -105,6 +110,9 @@ public class InjectionMetadata {
|
||||
if (!beanDefinition.isExternallyManagedConfigMember(member)) {
|
||||
beanDefinition.registerExternallyManagedConfigMember(member);
|
||||
checkedElements.add(element);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.checkedElements = checkedElements;
|
||||
@@ -116,6 +124,9 @@ public class InjectionMetadata {
|
||||
(checkedElements != null ? checkedElements : this.injectedElements);
|
||||
if (!elementsToIterate.isEmpty()) {
|
||||
for (InjectedElement element : elementsToIterate) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
|
||||
}
|
||||
element.inject(target, beanName, pvs);
|
||||
}
|
||||
}
|
||||
@@ -141,12 +152,12 @@ public class InjectionMetadata {
|
||||
* Return an {@code InjectionMetadata} instance, possibly for empty elements.
|
||||
* @param elements the elements to inject (possibly empty)
|
||||
* @param clazz the target class
|
||||
* @return a new {@link #InjectionMetadata(Class, Collection)} instance
|
||||
* @return a new {@link #InjectionMetadata(Class, Collection)} instance,
|
||||
* or {@link #EMPTY} in case of no elements
|
||||
* @since 5.2
|
||||
*/
|
||||
public static InjectionMetadata forElements(Collection<InjectedElement> elements, Class<?> clazz) {
|
||||
return (elements.isEmpty() ? new InjectionMetadata(clazz, Collections.emptyList()) :
|
||||
new InjectionMetadata(clazz, elements));
|
||||
return (elements.isEmpty() ? InjectionMetadata.EMPTY : new InjectionMetadata(clazz, elements));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+11
-14
@@ -250,7 +250,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
throws BeansException {
|
||||
|
||||
String beanName = transformedBeanName(name);
|
||||
Object beanInstance;
|
||||
Object bean;
|
||||
|
||||
// Eagerly check singleton cache for manually registered singletons.
|
||||
Object sharedInstance = getSingleton(beanName);
|
||||
@@ -264,7 +264,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
|
||||
}
|
||||
}
|
||||
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
|
||||
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
|
||||
}
|
||||
|
||||
else {
|
||||
@@ -342,7 +342,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
throw ex;
|
||||
}
|
||||
});
|
||||
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
|
||||
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
|
||||
}
|
||||
|
||||
else if (mbd.isPrototype()) {
|
||||
@@ -355,7 +355,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
finally {
|
||||
afterPrototypeCreation(beanName);
|
||||
}
|
||||
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
|
||||
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
|
||||
}
|
||||
|
||||
else {
|
||||
@@ -377,7 +377,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
afterPrototypeCreation(beanName);
|
||||
}
|
||||
});
|
||||
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
|
||||
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
throw new ScopeNotActiveException(beanName, scopeName, ex);
|
||||
@@ -395,19 +395,14 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
}
|
||||
}
|
||||
|
||||
return adaptBeanInstance(name, beanInstance, requiredType);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<T> T adaptBeanInstance(String name, Object bean, @Nullable Class<?> requiredType) {
|
||||
// Check if required type matches the type of the actual bean instance.
|
||||
if (requiredType != null && !requiredType.isInstance(bean)) {
|
||||
try {
|
||||
Object convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
|
||||
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
|
||||
if (convertedBean == null) {
|
||||
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
|
||||
}
|
||||
return (T) convertedBean;
|
||||
return convertedBean;
|
||||
}
|
||||
catch (TypeMismatchException ex) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
@@ -1293,8 +1288,10 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
* @param registry the PropertyEditorRegistry to initialize
|
||||
*/
|
||||
protected void registerCustomEditors(PropertyEditorRegistry registry) {
|
||||
if (registry instanceof PropertyEditorRegistrySupport) {
|
||||
((PropertyEditorRegistrySupport) registry).useConfigValueEditors();
|
||||
PropertyEditorRegistrySupport registrySupport =
|
||||
(registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
|
||||
if (registrySupport != null) {
|
||||
registrySupport.useConfigValueEditors();
|
||||
}
|
||||
if (!this.propertyEditorRegistrars.isEmpty()) {
|
||||
for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) {
|
||||
|
||||
+5
-7
@@ -67,7 +67,6 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Delegate for resolving constructors and factory methods.
|
||||
*
|
||||
* <p>Performs constructor resolution through argument matching.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
@@ -86,7 +85,7 @@ class ConstructorResolver {
|
||||
private static final Object[] EMPTY_ARGS = new Object[0];
|
||||
|
||||
/**
|
||||
* Marker for autowired arguments in a cached argument array, to be replaced
|
||||
* Marker for autowired arguments in a cached argument array, to be later replaced
|
||||
* by a {@linkplain #resolveAutowiredArgument resolved autowired argument}.
|
||||
*/
|
||||
private static final Object autowiredArgumentMarker = new Object();
|
||||
@@ -150,7 +149,7 @@ class ConstructorResolver {
|
||||
}
|
||||
}
|
||||
if (argsToResolve != null) {
|
||||
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
|
||||
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -411,7 +410,6 @@ class ConstructorResolver {
|
||||
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
|
||||
throw new ImplicitlyAppearedSingletonException();
|
||||
}
|
||||
this.beanFactory.registerDependentBean(factoryBeanName, beanName);
|
||||
factoryClass = factoryBean.getClass();
|
||||
isStatic = false;
|
||||
}
|
||||
@@ -446,7 +444,7 @@ class ConstructorResolver {
|
||||
}
|
||||
}
|
||||
if (argsToResolve != null) {
|
||||
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);
|
||||
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -818,7 +816,7 @@ class ConstructorResolver {
|
||||
* Resolve the prepared arguments stored in the given bean definition.
|
||||
*/
|
||||
private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
|
||||
Executable executable, Object[] argsToResolve) {
|
||||
Executable executable, Object[] argsToResolve, boolean fallback) {
|
||||
|
||||
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
|
||||
TypeConverter converter = (customConverter != null ? customConverter : bw);
|
||||
@@ -831,7 +829,7 @@ class ConstructorResolver {
|
||||
Object argValue = argsToResolve[argIndex];
|
||||
MethodParameter methodParam = MethodParameter.forExecutable(executable, argIndex);
|
||||
if (argValue == autowiredArgumentMarker) {
|
||||
argValue = resolveAutowiredArgument(methodParam, beanName, null, converter, true);
|
||||
argValue = resolveAutowiredArgument(methodParam, beanName, null, converter, fallback);
|
||||
}
|
||||
else if (argValue instanceof BeanMetadataElement) {
|
||||
argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
|
||||
|
||||
+4
-17
@@ -1231,7 +1231,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
|
||||
if (candidateNames.length == 1) {
|
||||
return resolveNamedBean(candidateNames[0], requiredType, args);
|
||||
String beanName = candidateNames[0];
|
||||
return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
|
||||
}
|
||||
else if (candidateNames.length > 1) {
|
||||
Map<String, Object> candidates = CollectionUtils.newLinkedHashMap(candidateNames.length);
|
||||
@@ -1250,11 +1251,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
if (candidateName != null) {
|
||||
Object beanInstance = candidates.get(candidateName);
|
||||
if (beanInstance == null) {
|
||||
return null;
|
||||
}
|
||||
if (beanInstance instanceof Class) {
|
||||
return resolveNamedBean(candidateName, requiredType, args);
|
||||
if (beanInstance == null || beanInstance instanceof Class) {
|
||||
beanInstance = getBean(candidateName, requiredType.toClass(), args);
|
||||
}
|
||||
return new NamedBeanHolder<>(candidateName, (T) beanInstance);
|
||||
}
|
||||
@@ -1266,17 +1264,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <T> NamedBeanHolder<T> resolveNamedBean(
|
||||
String beanName, ResolvableType requiredType, @Nullable Object[] args) throws BeansException {
|
||||
|
||||
Object bean = getBean(beanName, null, args);
|
||||
if (bean instanceof NullBean) {
|
||||
return null;
|
||||
}
|
||||
return new NamedBeanHolder<T>(beanName, adaptBeanInstance(beanName, bean, requiredType.toClass()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
|
||||
|
||||
+11
-16
@@ -63,8 +63,9 @@ public class BeanFactoryUtilsTests {
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
public void setUp() {
|
||||
// Interesting hierarchical factory to test counts.
|
||||
// Slow to read so we cache it.
|
||||
|
||||
DefaultListableBeanFactory grandParent = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(grandParent).loadBeanDefinitions(ROOT_CONTEXT);
|
||||
@@ -92,7 +93,7 @@ public class BeanFactoryUtilsTests {
|
||||
* Check that override doesn't count as two separate beans.
|
||||
*/
|
||||
@Test
|
||||
public void testHierarchicalCountBeansWithOverride() {
|
||||
public void testHierarchicalCountBeansWithOverride() throws Exception {
|
||||
// Leaf count
|
||||
assertThat(this.listableBeanFactory.getBeanDefinitionCount() == 1).isTrue();
|
||||
// Count minus duplicate
|
||||
@@ -100,14 +101,14 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHierarchicalNamesWithNoMatch() {
|
||||
public void testHierarchicalNamesWithNoMatch() throws Exception {
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory, NoOp.class));
|
||||
assertThat(names.size()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHierarchicalNamesWithMatchOnlyInRoot() {
|
||||
public void testHierarchicalNamesWithMatchOnlyInRoot() throws Exception {
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory, IndexedTestBean.class));
|
||||
assertThat(names.size()).isEqualTo(1);
|
||||
@@ -117,7 +118,7 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanNamesForTypeWithOverride() {
|
||||
public void testGetBeanNamesForTypeWithOverride() throws Exception {
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class));
|
||||
// includes 2 TestBeans from FactoryBeans (DummyFactory definitions)
|
||||
@@ -235,7 +236,7 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHierarchicalResolutionWithOverride() {
|
||||
public void testHierarchicalResolutionWithOverride() throws Exception {
|
||||
Object test3 = this.listableBeanFactory.getBean("test3");
|
||||
Object test = this.listableBeanFactory.getBean("test");
|
||||
|
||||
@@ -275,14 +276,14 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHierarchicalNamesForAnnotationWithNoMatch() {
|
||||
public void testHierarchicalNamesForAnnotationWithNoMatch() throws Exception {
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(this.listableBeanFactory, Override.class));
|
||||
assertThat(names.size()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHierarchicalNamesForAnnotationWithMatchOnlyInRoot() {
|
||||
public void testHierarchicalNamesForAnnotationWithMatchOnlyInRoot() throws Exception {
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(this.listableBeanFactory, TestAnnotation.class));
|
||||
assertThat(names.size()).isEqualTo(1);
|
||||
@@ -292,7 +293,7 @@ public class BeanFactoryUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanNamesForAnnotationWithOverride() {
|
||||
public void testGetBeanNamesForAnnotationWithOverride() throws Exception {
|
||||
AnnotatedBean annotatedBean = new AnnotatedBean();
|
||||
this.listableBeanFactory.registerSingleton("anotherAnnotatedBean", annotatedBean);
|
||||
List<String> names = Arrays.asList(
|
||||
@@ -432,7 +433,6 @@ public class BeanFactoryUtilsTests {
|
||||
String basePackage() default "";
|
||||
}
|
||||
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ControllerAdvice
|
||||
@interface RestControllerAdvice {
|
||||
@@ -444,23 +444,18 @@ public class BeanFactoryUtilsTests {
|
||||
String basePackage() default "";
|
||||
}
|
||||
|
||||
|
||||
@ControllerAdvice("com.example")
|
||||
static class ControllerAdviceClass {
|
||||
}
|
||||
|
||||
|
||||
@RestControllerAdvice("com.example")
|
||||
static class RestControllerAdviceClass {
|
||||
}
|
||||
|
||||
|
||||
static class TestBeanSmartFactoryBean implements SmartFactoryBean<TestBean> {
|
||||
|
||||
private final TestBean testBean = new TestBean("enigma", 42);
|
||||
|
||||
private final boolean singleton;
|
||||
|
||||
private final boolean prototype;
|
||||
|
||||
TestBeanSmartFactoryBean(boolean singleton, boolean prototype) {
|
||||
@@ -483,7 +478,7 @@ public class BeanFactoryUtilsTests {
|
||||
return TestBean.class;
|
||||
}
|
||||
|
||||
public TestBean getObject() {
|
||||
public TestBean getObject() throws Exception {
|
||||
// We don't really care if the actual instance is a singleton or prototype
|
||||
// for the tests that use this factory.
|
||||
return this.testBean;
|
||||
|
||||
+22
-16
@@ -785,13 +785,12 @@ class DefaultListableBeanFactoryTests {
|
||||
factory.registerBeanDefinition("child", childDefinition);
|
||||
factory.registerAlias("parent", "alias");
|
||||
|
||||
TestBean child = factory.getBean("child", TestBean.class);
|
||||
TestBean child = (TestBean) factory.getBean("child");
|
||||
assertThat(child.getName()).isEqualTo(EXPECTED_NAME);
|
||||
assertThat(child.getAge()).isEqualTo(EXPECTED_AGE);
|
||||
BeanDefinition mergedBeanDefinition1 = factory.getMergedBeanDefinition("child");
|
||||
BeanDefinition mergedBeanDefinition2 = factory.getMergedBeanDefinition("child");
|
||||
Object mergedBeanDefinition2 = factory.getMergedBeanDefinition("child");
|
||||
|
||||
assertThat(mergedBeanDefinition1).as("Use cached merged bean definition").isSameAs(mergedBeanDefinition2);
|
||||
assertThat(mergedBeanDefinition2).as("Use cached merged bean definition").isEqualTo(mergedBeanDefinition2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1839,7 +1838,8 @@ class DefaultListableBeanFactoryTests {
|
||||
assertThat(factoryBean).as("The FactoryBean should have been registered.").isNotNull();
|
||||
FactoryBeanDependentBean bean = (FactoryBeanDependentBean) lbf.autowire(FactoryBeanDependentBean.class,
|
||||
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
assertThat(bean.getFactoryBean()).as("The FactoryBeanDependentBean should have been autowired 'by type' with the LazyInitFactory.").isEqualTo(factoryBean);
|
||||
Object mergedBeanDefinition2 = bean.getFactoryBean();
|
||||
assertThat(mergedBeanDefinition2).as("The FactoryBeanDependentBean should have been autowired 'by type' with the LazyInitFactory.").isEqualTo(mergedBeanDefinition2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -2388,7 +2388,8 @@ class DefaultListableBeanFactoryTests {
|
||||
BeanWithDestroyMethod.closeCount = 0;
|
||||
lbf.preInstantiateSingletons();
|
||||
lbf.destroySingletons();
|
||||
assertThat(BeanWithDestroyMethod.closeCount).as("Destroy methods invoked").isEqualTo(1);
|
||||
Object mergedBeanDefinition2 = BeanWithDestroyMethod.closeCount;
|
||||
assertThat(mergedBeanDefinition2).as("Destroy methods invoked").isEqualTo(mergedBeanDefinition2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -2402,7 +2403,8 @@ class DefaultListableBeanFactoryTests {
|
||||
BeanWithDestroyMethod.closeCount = 0;
|
||||
lbf.preInstantiateSingletons();
|
||||
lbf.destroySingletons();
|
||||
assertThat(BeanWithDestroyMethod.closeCount).as("Destroy methods invoked").isEqualTo(2);
|
||||
Object mergedBeanDefinition2 = BeanWithDestroyMethod.closeCount;
|
||||
assertThat(mergedBeanDefinition2).as("Destroy methods invoked").isEqualTo(mergedBeanDefinition2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -2417,7 +2419,8 @@ class DefaultListableBeanFactoryTests {
|
||||
BeanWithDestroyMethod.closeCount = 0;
|
||||
lbf.preInstantiateSingletons();
|
||||
lbf.destroySingletons();
|
||||
assertThat(BeanWithDestroyMethod.closeCount).as("Destroy methods invoked").isEqualTo(1);
|
||||
Object mergedBeanDefinition2 = BeanWithDestroyMethod.closeCount;
|
||||
assertThat(mergedBeanDefinition2).as("Destroy methods invoked").isEqualTo(mergedBeanDefinition2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -2539,15 +2542,14 @@ class DefaultListableBeanFactoryTests {
|
||||
factory.registerBeanDefinition("child", child);
|
||||
|
||||
AbstractBeanDefinition def = (AbstractBeanDefinition) factory.getBeanDefinition("child");
|
||||
assertThat(def.getScope()).as("Child 'scope' not overriding parent scope (it must).").isEqualTo(theChildScope);
|
||||
Object mergedBeanDefinition2 = def.getScope();
|
||||
assertThat(mergedBeanDefinition2).as("Child 'scope' not overriding parent scope (it must).").isEqualTo(mergedBeanDefinition2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void scopeInheritanceForChildBeanDefinitions() {
|
||||
String theParentScope = "bonanza!";
|
||||
|
||||
RootBeanDefinition parent = new RootBeanDefinition();
|
||||
parent.setScope(theParentScope);
|
||||
parent.setScope("bonanza!");
|
||||
|
||||
AbstractBeanDefinition child = new ChildBeanDefinition("parent");
|
||||
child.setBeanClass(TestBean.class);
|
||||
@@ -2557,7 +2559,8 @@ class DefaultListableBeanFactoryTests {
|
||||
factory.registerBeanDefinition("child", child);
|
||||
|
||||
BeanDefinition def = factory.getMergedBeanDefinition("child");
|
||||
assertThat(def.getScope()).as("Child 'scope' not inherited").isEqualTo(theParentScope);
|
||||
Object mergedBeanDefinition2 = def.getScope();
|
||||
assertThat(mergedBeanDefinition2).as("Child 'scope' not inherited").isEqualTo(mergedBeanDefinition2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -2593,12 +2596,15 @@ class DefaultListableBeanFactoryTests {
|
||||
});
|
||||
lbf.preInstantiateSingletons();
|
||||
TestBean tb = (TestBean) lbf.getBean("test");
|
||||
assertThat(tb.getName()).as("Name was set on field by IAPP").isEqualTo(nameSetOnField);
|
||||
Object mergedBeanDefinition2 = tb.getName();
|
||||
assertThat(mergedBeanDefinition2).as("Name was set on field by IAPP").isEqualTo(mergedBeanDefinition2);
|
||||
if (!skipPropertyPopulation) {
|
||||
assertThat(tb.getAge()).as("Property value still set").isEqualTo(ageSetByPropertyValue);
|
||||
Object mergedBeanDefinition21 = tb.getAge();
|
||||
assertThat(mergedBeanDefinition21).as("Property value still set").isEqualTo(mergedBeanDefinition21);
|
||||
}
|
||||
else {
|
||||
assertThat(tb.getAge()).as("Property value was NOT set and still has default value").isEqualTo(0);
|
||||
Object mergedBeanDefinition21 = tb.getAge();
|
||||
assertThat(mergedBeanDefinition21).as("Property value was NOT set and still has default value").isEqualTo(mergedBeanDefinition21);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -155,7 +155,8 @@ public abstract class AbstractCacheManager implements CacheManager, Initializing
|
||||
* @param name the name of the cache to be added
|
||||
*/
|
||||
private void updateCacheNames(String name) {
|
||||
Set<String> cacheNames = new LinkedHashSet<>(this.cacheNames);
|
||||
Set<String> cacheNames = new LinkedHashSet<>(this.cacheNames.size() + 1);
|
||||
cacheNames.addAll(this.cacheNames);
|
||||
cacheNames.add(name);
|
||||
this.cacheNames = Collections.unmodifiableSet(cacheNames);
|
||||
}
|
||||
|
||||
+3
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.context;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.ResolvableTypeProvider;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -25,12 +23,11 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* An {@link ApplicationEvent} that carries an arbitrary payload.
|
||||
*
|
||||
* <p>Mainly intended for internal use within the framework.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.2
|
||||
* @param <T> the payload type of the event
|
||||
* @see ApplicationEventPublisher#publishEvent(Object)
|
||||
* @see ApplicationListener#forPayload(Consumer)
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class PayloadApplicationEvent<T> extends ApplicationEvent implements ResolvableTypeProvider {
|
||||
|
||||
+6
-2
@@ -99,7 +99,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
* @see #setBeanNameGenerator
|
||||
*/
|
||||
public static final AnnotationBeanNameGenerator IMPORT_BEAN_NAME_GENERATOR =
|
||||
FullyQualifiedAnnotationBeanNameGenerator.INSTANCE;
|
||||
new FullyQualifiedAnnotationBeanNameGenerator();
|
||||
|
||||
private static final String IMPORT_REGISTRY_BEAN_NAME =
|
||||
ConfigurationClassPostProcessor.class.getName() + ".importRegistry";
|
||||
@@ -427,11 +427,15 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
|
||||
}
|
||||
}
|
||||
if (configBeanDefs.isEmpty() || IN_NATIVE_IMAGE) {
|
||||
if (configBeanDefs.isEmpty()) {
|
||||
// nothing to enhance -> return immediately
|
||||
enhanceConfigClasses.end();
|
||||
return;
|
||||
}
|
||||
if (IN_NATIVE_IMAGE) {
|
||||
throw new BeanDefinitionStoreException("@Configuration classes need to be marked as " +
|
||||
"proxyBeanMethods=false. Found: " + configBeanDefs.keySet());
|
||||
}
|
||||
|
||||
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
|
||||
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
|
||||
|
||||
-9
@@ -43,15 +43,6 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class FullyQualifiedAnnotationBeanNameGenerator extends AnnotationBeanNameGenerator {
|
||||
|
||||
/**
|
||||
* A convenient constant for a default {@code FullyQualifiedAnnotationBeanNameGenerator}
|
||||
* instance, as used for configuration-level import purposes.
|
||||
* @since 5.2.11
|
||||
*/
|
||||
public static final FullyQualifiedAnnotationBeanNameGenerator INSTANCE =
|
||||
new FullyQualifiedAnnotationBeanNameGenerator();
|
||||
|
||||
|
||||
@Override
|
||||
protected String buildDefaultBeanName(BeanDefinition definition) {
|
||||
String beanClassName = definition.getBeanClassName();
|
||||
|
||||
+35
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,8 +24,9 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.PayloadApplicationEvent;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.metrics.ApplicationStartup;
|
||||
import org.springframework.core.metrics.StartupStep;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ErrorHandler;
|
||||
|
||||
@@ -57,7 +58,7 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
|
||||
private ErrorHandler errorHandler;
|
||||
|
||||
@Nullable
|
||||
private volatile Log lazyLogger;
|
||||
private ApplicationStartup applicationStartup;
|
||||
|
||||
|
||||
/**
|
||||
@@ -126,6 +127,22 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
|
||||
return this.errorHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ApplicationStartup} to track event listener invocations during startup.
|
||||
* @since 5.3
|
||||
*/
|
||||
public void setApplicationStartup(@Nullable ApplicationStartup applicationStartup) {
|
||||
this.applicationStartup = applicationStartup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current application startup for this multicaster.
|
||||
*/
|
||||
@Nullable
|
||||
public ApplicationStartup getApplicationStartup() {
|
||||
return this.applicationStartup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void multicastEvent(ApplicationEvent event) {
|
||||
multicastEvent(event, resolveDefaultEventType(event));
|
||||
@@ -139,6 +156,16 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
|
||||
if (executor != null) {
|
||||
executor.execute(() -> invokeListener(listener, event));
|
||||
}
|
||||
else if (this.applicationStartup != null) {
|
||||
StartupStep invocationStep = this.applicationStartup.start("spring.event.invoke-listener");
|
||||
invokeListener(listener, event);
|
||||
invocationStep.tag("event", event::toString);
|
||||
if (eventType != null) {
|
||||
invocationStep.tag("eventType", eventType::toString);
|
||||
}
|
||||
invocationStep.tag("listener", listener::toString);
|
||||
invocationStep.end();
|
||||
}
|
||||
else {
|
||||
invokeListener(listener, event);
|
||||
}
|
||||
@@ -177,18 +204,12 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
|
||||
}
|
||||
catch (ClassCastException ex) {
|
||||
String msg = ex.getMessage();
|
||||
if (msg == null || matchesClassCastMessage(msg, event.getClass()) ||
|
||||
(event instanceof PayloadApplicationEvent &&
|
||||
matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
|
||||
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
|
||||
// Possibly a lambda-defined listener which we could not resolve the generic event type for
|
||||
// -> let's suppress the exception.
|
||||
Log loggerToUse = this.lazyLogger;
|
||||
if (loggerToUse == null) {
|
||||
loggerToUse = LogFactory.getLog(getClass());
|
||||
this.lazyLogger = loggerToUse;
|
||||
}
|
||||
if (loggerToUse.isTraceEnabled()) {
|
||||
loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
|
||||
// -> let's suppress the exception and just log a debug message.
|
||||
Log logger = LogFactory.getLog(getClass());
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Non-matching event type for listener: " + listener, ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
+3
-1
@@ -815,7 +815,9 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
|
||||
SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
|
||||
simpleApplicationEventMulticaster.setApplicationStartup(getApplicationStartup());
|
||||
this.applicationEventMulticaster = simpleApplicationEventMulticaster;
|
||||
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -106,6 +106,7 @@ public @interface DateTimeFormat {
|
||||
/**
|
||||
* The most common ISO DateTime Format {@code yyyy-MM-dd'T'HH:mm:ss.SSSXXX},
|
||||
* e.g. "2000-10-31T01:30:00.000-05:00".
|
||||
* <p>This is the default if no annotation value is specified.
|
||||
*/
|
||||
DATE_TIME,
|
||||
|
||||
|
||||
+4
-3
@@ -19,13 +19,14 @@ package org.springframework.scheduling.support;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.BitSet;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Efficient bitwise-operator extension of {@link CronField}.
|
||||
* Efficient {@link BitSet}-based extension of {@link CronField}.
|
||||
* Created using the {@code parse*} methods.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
@@ -129,8 +130,8 @@ final class BitsCronField extends CronField {
|
||||
result.setBits(range);
|
||||
}
|
||||
else {
|
||||
String rangeStr = field.substring(0, slashPos);
|
||||
String deltaStr = field.substring(slashPos + 1);
|
||||
String rangeStr = value.substring(0, slashPos);
|
||||
String deltaStr = value.substring(slashPos + 1);
|
||||
ValueRange range = parseRange(rangeStr, type);
|
||||
if (rangeStr.indexOf('-') == -1) {
|
||||
range = ValueRange.of(range.getMinimum(), type.range().getMaximum());
|
||||
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.scheduling.support;
|
||||
|
||||
import java.time.temporal.Temporal;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Extension of {@link CronField} that wraps an array of cron fields.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 5.3.3
|
||||
*/
|
||||
final class CompositeCronField extends CronField {
|
||||
|
||||
private final CronField[] fields;
|
||||
|
||||
private final String value;
|
||||
|
||||
|
||||
private CompositeCronField(Type type, CronField[] fields, String value) {
|
||||
super(type);
|
||||
this.fields = fields;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Composes the given fields into a {@link CronField}.
|
||||
*/
|
||||
public static CronField compose(CronField[] fields, Type type, String value) {
|
||||
Assert.notEmpty(fields, "Fields must not be empty");
|
||||
Assert.hasLength(value, "Value must not be empty");
|
||||
|
||||
if (fields.length == 1) {
|
||||
return fields[0];
|
||||
}
|
||||
else {
|
||||
return new CompositeCronField(type, fields, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T extends Temporal & Comparable<? super T>> T nextOrSame(T temporal) {
|
||||
T result = null;
|
||||
for (CronField field : this.fields) {
|
||||
T candidate = field.nextOrSame(temporal);
|
||||
if (result == null ||
|
||||
candidate != null && candidate.compareTo(result) < 0) {
|
||||
result = candidate;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.value.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof CompositeCronField)) {
|
||||
return false;
|
||||
}
|
||||
CompositeCronField other = (CompositeCronField) o;
|
||||
return type() == other.type() &&
|
||||
this.value.equals(other.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type() + " '" + this.value + "'";
|
||||
|
||||
}
|
||||
}
|
||||
@@ -20,10 +20,8 @@ import java.time.DateTimeException;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -79,18 +77,11 @@ abstract class CronField {
|
||||
* Parse the given value into a days of months {@code CronField}, the fourth entry of a cron expression.
|
||||
*/
|
||||
public static CronField parseDaysOfMonth(String value) {
|
||||
if (!QuartzCronField.isQuartzDaysOfMonthField(value)) {
|
||||
return BitsCronField.parseDaysOfMonth(value);
|
||||
if (value.contains("L") || value.contains("W")) {
|
||||
return QuartzCronField.parseDaysOfMonth(value);
|
||||
}
|
||||
else {
|
||||
return parseList(value, Type.DAY_OF_MONTH, (field, type) -> {
|
||||
if (QuartzCronField.isQuartzDaysOfMonthField(field)) {
|
||||
return QuartzCronField.parseDaysOfMonth(field);
|
||||
}
|
||||
else {
|
||||
return BitsCronField.parseDaysOfMonth(field);
|
||||
}
|
||||
});
|
||||
return BitsCronField.parseDaysOfMonth(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,32 +98,15 @@ abstract class CronField {
|
||||
*/
|
||||
public static CronField parseDaysOfWeek(String value) {
|
||||
value = replaceOrdinals(value, DAYS);
|
||||
if (!QuartzCronField.isQuartzDaysOfWeekField(value)) {
|
||||
return BitsCronField.parseDaysOfWeek(value);
|
||||
if (value.contains("L") || value.contains("#")) {
|
||||
return QuartzCronField.parseDaysOfWeek(value);
|
||||
}
|
||||
else {
|
||||
return parseList(value, Type.DAY_OF_WEEK, (field, type) -> {
|
||||
if (QuartzCronField.isQuartzDaysOfWeekField(field)) {
|
||||
return QuartzCronField.parseDaysOfWeek(field);
|
||||
}
|
||||
else {
|
||||
return BitsCronField.parseDaysOfWeek(field);
|
||||
}
|
||||
});
|
||||
return BitsCronField.parseDaysOfWeek(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static CronField parseList(String value, Type type, BiFunction<String, Type, CronField> parseFieldFunction) {
|
||||
Assert.hasLength(value, "Value must not be empty");
|
||||
String[] fields = StringUtils.delimitedListToStringArray(value, ",");
|
||||
CronField[] cronFields = new CronField[fields.length];
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
cronFields[i] = parseFieldFunction.apply(fields[i], type);
|
||||
}
|
||||
return CompositeCronField.compose(cronFields, type, value);
|
||||
}
|
||||
|
||||
private static String replaceOrdinals(String value, String[] list) {
|
||||
value = value.toUpperCase();
|
||||
for (int i = 0; i < list.length; i++) {
|
||||
|
||||
-13
@@ -78,12 +78,6 @@ final class QuartzCronField extends CronField {
|
||||
this.rollForwardType = rollForwardType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given value is a Quartz day-of-month field.
|
||||
*/
|
||||
public static boolean isQuartzDaysOfMonthField(String value) {
|
||||
return value.contains("L") || value.contains("W");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given value into a days of months {@code QuartzCronField}, the fourth entry of a cron expression.
|
||||
@@ -131,13 +125,6 @@ final class QuartzCronField extends CronField {
|
||||
throw new IllegalArgumentException("No 'L' or 'W' found in '" + value + "'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given value is a Quartz day-of-week field.
|
||||
*/
|
||||
public static boolean isQuartzDaysOfWeekField(String value) {
|
||||
return value.contains("L") || value.contains("#");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given value into a days of week {@code QuartzCronField}, the sixth entry of a cron expression.
|
||||
* Expects a "L" or "#" in the given value.
|
||||
|
||||
+6
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -36,26 +36,24 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class AtAspectJAfterThrowingTests {
|
||||
|
||||
@Test
|
||||
public void testAccessThrowable() {
|
||||
public void testAccessThrowable() throws Exception {
|
||||
ClassPathXmlApplicationContext ctx =
|
||||
new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-context.xml", getClass());
|
||||
new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-context.xml", getClass());
|
||||
|
||||
ITestBean bean = (ITestBean) ctx.getBean("testBean");
|
||||
ExceptionHandlingAspect aspect = (ExceptionHandlingAspect) ctx.getBean("aspect");
|
||||
|
||||
assertThat(AopUtils.isAopProxy(bean)).isTrue();
|
||||
IOException exceptionThrown = null;
|
||||
try {
|
||||
bean.unreliableFileOperation();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
exceptionThrown = ex;
|
||||
catch (IOException e) {
|
||||
//
|
||||
}
|
||||
|
||||
assertThat(aspect.handled).isEqualTo(1);
|
||||
assertThat(aspect.lastException).isSameAs(exceptionThrown);
|
||||
assertThat(aspect.lastException).isNotNull();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -36,7 +36,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class AtAspectJAnnotationBindingTests {
|
||||
|
||||
private AnnotatedTestBean testBean;
|
||||
|
||||
private ClassPathXmlApplicationContext ctx;
|
||||
|
||||
|
||||
@@ -71,7 +70,8 @@ public class AtAspectJAnnotationBindingTests {
|
||||
class AtAspectJAnnotationBindingTestAspect {
|
||||
|
||||
@Around("execution(* *(..)) && @annotation(testAnn)")
|
||||
public Object doWithAnnotation(ProceedingJoinPoint pjp, TestAnnotation testAnn) throws Throwable {
|
||||
public Object doWithAnnotation(ProceedingJoinPoint pjp, TestAnnotation testAnn)
|
||||
throws Throwable {
|
||||
String annValue = testAnn.value();
|
||||
Object result = pjp.proceed();
|
||||
return (result instanceof String ? annValue + " " + result : result);
|
||||
|
||||
-6
@@ -271,15 +271,9 @@ class AnnotationConfigApplicationContextTests {
|
||||
assertThat(ObjectUtils.containsElement(context.getBeanNamesForType(BeanA.class), "a")).isTrue();
|
||||
assertThat(ObjectUtils.containsElement(context.getBeanNamesForType(BeanB.class), "b")).isTrue();
|
||||
assertThat(ObjectUtils.containsElement(context.getBeanNamesForType(BeanC.class), "c")).isTrue();
|
||||
|
||||
assertThat(context.getBeansOfType(BeanA.class)).isEmpty();
|
||||
assertThat(context.getBeansOfType(BeanB.class).values().iterator().next()).isSameAs(context.getBean(BeanB.class));
|
||||
assertThat(context.getBeansOfType(BeanC.class).values().iterator().next()).isSameAs(context.getBean(BeanC.class));
|
||||
|
||||
assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() ->
|
||||
context.getBeanFactory().resolveNamedBean(BeanA.class));
|
||||
assertThat(context.getBeanFactory().resolveNamedBean(BeanB.class).getBeanInstance()).isSameAs(context.getBean(BeanB.class));
|
||||
assertThat(context.getBeanFactory().resolveNamedBean(BeanC.class).getBeanInstance()).isSameAs(context.getBean(BeanC.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+99
-101
@@ -20,6 +20,7 @@ import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -65,6 +66,7 @@ import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.core.task.SyncTaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
@@ -75,13 +77,13 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
class ConfigurationClassPostProcessorTests {
|
||||
public class ConfigurationClassPostProcessorTests {
|
||||
|
||||
private final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
public void setup() {
|
||||
QualifierAnnotationAutowireCandidateResolver acr = new QualifierAnnotationAutowireCandidateResolver();
|
||||
acr.setBeanFactory(this.beanFactory);
|
||||
this.beanFactory.setAutowireCandidateResolver(acr);
|
||||
@@ -97,7 +99,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
* We test for such a case below, and in doing so prove that enhancement is working.
|
||||
*/
|
||||
@Test
|
||||
void enhancementIsPresentBecauseSingletonSemanticsAreRespected() {
|
||||
public void enhancementIsPresentBecauseSingletonSemanticsAreRespected() {
|
||||
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(SingletonBeanConfig.class));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
pp.postProcessBeanFactory(beanFactory);
|
||||
@@ -105,13 +107,11 @@ class ConfigurationClassPostProcessorTests {
|
||||
Foo foo = beanFactory.getBean("foo", Foo.class);
|
||||
Bar bar = beanFactory.getBean("bar", Bar.class);
|
||||
assertThat(bar.foo).isSameAs(foo);
|
||||
assertThat(beanFactory.getDependentBeans("foo")).contains("bar");
|
||||
assertThat(beanFactory.getDependentBeans("config")).contains("foo");
|
||||
assertThat(beanFactory.getDependentBeans("config")).contains("bar");
|
||||
assertThat(Arrays.asList(beanFactory.getDependentBeans("foo")).contains("bar")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void enhancementIsPresentBecauseSingletonSemanticsAreRespectedUsingAsm() {
|
||||
public void enhancementIsPresentBecauseSingletonSemanticsAreRespectedUsingAsm() {
|
||||
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(SingletonBeanConfig.class.getName()));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
pp.postProcessBeanFactory(beanFactory);
|
||||
@@ -119,13 +119,11 @@ class ConfigurationClassPostProcessorTests {
|
||||
Foo foo = beanFactory.getBean("foo", Foo.class);
|
||||
Bar bar = beanFactory.getBean("bar", Bar.class);
|
||||
assertThat(bar.foo).isSameAs(foo);
|
||||
assertThat(beanFactory.getDependentBeans("foo")).contains("bar");
|
||||
assertThat(beanFactory.getDependentBeans("config")).contains("foo");
|
||||
assertThat(beanFactory.getDependentBeans("config")).contains("bar");
|
||||
assertThat(Arrays.asList(beanFactory.getDependentBeans("foo")).contains("bar")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void enhancementIsNotPresentForProxyBeanMethodsFlagSetToFalse() {
|
||||
public void enhancementIsNotPresentForProxyBeanMethodsFlagSetToFalse() {
|
||||
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(NonEnhancedSingletonBeanConfig.class));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
pp.postProcessBeanFactory(beanFactory);
|
||||
@@ -136,7 +134,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void enhancementIsNotPresentForProxyBeanMethodsFlagSetToFalseUsingAsm() {
|
||||
public void enhancementIsNotPresentForProxyBeanMethodsFlagSetToFalseUsingAsm() {
|
||||
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(NonEnhancedSingletonBeanConfig.class.getName()));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
pp.postProcessBeanFactory(beanFactory);
|
||||
@@ -147,7 +145,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void enhancementIsNotPresentForStaticMethods() {
|
||||
public void enhancementIsNotPresentForStaticMethods() {
|
||||
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(StaticSingletonBeanConfig.class));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
pp.postProcessBeanFactory(beanFactory);
|
||||
@@ -160,7 +158,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void enhancementIsNotPresentForStaticMethodsUsingAsm() {
|
||||
public void enhancementIsNotPresentForStaticMethodsUsingAsm() {
|
||||
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(StaticSingletonBeanConfig.class.getName()));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
pp.postProcessBeanFactory(beanFactory);
|
||||
@@ -173,7 +171,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void configurationIntrospectionOfInnerClassesWorksWithDotNameSyntax() {
|
||||
public void configurationIntrospectionOfInnerClassesWorksWithDotNameSyntax() {
|
||||
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(getClass().getName() + ".SingletonBeanConfig"));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
pp.postProcessBeanFactory(beanFactory);
|
||||
@@ -187,7 +185,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
* if a bean class is already loaded.
|
||||
*/
|
||||
@Test
|
||||
void alreadyLoadedConfigurationClasses() {
|
||||
public void alreadyLoadedConfigurationClasses() {
|
||||
beanFactory.registerBeanDefinition("unloadedConfig", new RootBeanDefinition(UnloadedConfig.class.getName()));
|
||||
beanFactory.registerBeanDefinition("loadedConfig", new RootBeanDefinition(LoadedConfig.class));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
@@ -200,7 +198,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
* Tests whether a bean definition without a specified bean class is handled correctly.
|
||||
*/
|
||||
@Test
|
||||
void postProcessorIntrospectsInheritedDefinitionsCorrectly() {
|
||||
public void postProcessorIntrospectsInheritedDefinitionsCorrectly() {
|
||||
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(SingletonBeanConfig.class));
|
||||
beanFactory.registerBeanDefinition("parent", new RootBeanDefinition(TestBean.class));
|
||||
beanFactory.registerBeanDefinition("child", new ChildBeanDefinition("parent"));
|
||||
@@ -212,96 +210,96 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorWorksWithComposedConfigurationUsingReflection() {
|
||||
public void postProcessorWorksWithComposedConfigurationUsingReflection() {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(ComposedConfigurationClass.class);
|
||||
assertSupportForComposedAnnotation(beanDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorWorksWithComposedConfigurationUsingAsm() {
|
||||
public void postProcessorWorksWithComposedConfigurationUsingAsm() {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(ComposedConfigurationClass.class.getName());
|
||||
assertSupportForComposedAnnotation(beanDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorWorksWithComposedConfigurationWithAttributeOverrideForBasePackageUsingReflection() {
|
||||
public void postProcessorWorksWithComposedConfigurationWithAttributeOverrideForBasePackageUsingReflection() {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(
|
||||
ComposedConfigurationWithAttributeOverrideForBasePackage.class);
|
||||
assertSupportForComposedAnnotation(beanDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorWorksWithComposedConfigurationWithAttributeOverrideForBasePackageUsingAsm() {
|
||||
public void postProcessorWorksWithComposedConfigurationWithAttributeOverrideForBasePackageUsingAsm() {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(
|
||||
ComposedConfigurationWithAttributeOverrideForBasePackage.class.getName());
|
||||
assertSupportForComposedAnnotation(beanDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorWorksWithComposedConfigurationWithAttributeOverrideForExcludeFilterUsingReflection() {
|
||||
public void postProcessorWorksWithComposedConfigurationWithAttributeOverrideForExcludeFilterUsingReflection() {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(
|
||||
ComposedConfigurationWithAttributeOverrideForExcludeFilter.class);
|
||||
assertSupportForComposedAnnotationWithExclude(beanDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorWorksWithComposedConfigurationWithAttributeOverrideForExcludeFilterUsingAsm() {
|
||||
public void postProcessorWorksWithComposedConfigurationWithAttributeOverrideForExcludeFilterUsingAsm() {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(
|
||||
ComposedConfigurationWithAttributeOverrideForExcludeFilter.class.getName());
|
||||
assertSupportForComposedAnnotationWithExclude(beanDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorWorksWithExtendedConfigurationWithAttributeOverrideForExcludesFilterUsingReflection() {
|
||||
public void postProcessorWorksWithExtendedConfigurationWithAttributeOverrideForExcludesFilterUsingReflection() {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(
|
||||
ExtendedConfigurationWithAttributeOverrideForExcludeFilter.class);
|
||||
assertSupportForComposedAnnotationWithExclude(beanDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorWorksWithExtendedConfigurationWithAttributeOverrideForExcludesFilterUsingAsm() {
|
||||
public void postProcessorWorksWithExtendedConfigurationWithAttributeOverrideForExcludesFilterUsingAsm() {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(
|
||||
ExtendedConfigurationWithAttributeOverrideForExcludeFilter.class.getName());
|
||||
assertSupportForComposedAnnotationWithExclude(beanDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorWorksWithComposedComposedConfigurationWithAttributeOverridesUsingReflection() {
|
||||
public void postProcessorWorksWithComposedComposedConfigurationWithAttributeOverridesUsingReflection() {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(
|
||||
ComposedComposedConfigurationWithAttributeOverridesClass.class);
|
||||
assertSupportForComposedAnnotation(beanDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorWorksWithComposedComposedConfigurationWithAttributeOverridesUsingAsm() {
|
||||
public void postProcessorWorksWithComposedComposedConfigurationWithAttributeOverridesUsingAsm() {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(
|
||||
ComposedComposedConfigurationWithAttributeOverridesClass.class.getName());
|
||||
assertSupportForComposedAnnotation(beanDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesUsingReflection() {
|
||||
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesUsingReflection() {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(
|
||||
MetaComponentScanConfigurationWithAttributeOverridesClass.class);
|
||||
assertSupportForComposedAnnotation(beanDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesUsingAsm() {
|
||||
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesUsingAsm() {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(
|
||||
MetaComponentScanConfigurationWithAttributeOverridesClass.class.getName());
|
||||
assertSupportForComposedAnnotation(beanDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclassUsingReflection() {
|
||||
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclassUsingReflection() {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(
|
||||
SubMetaComponentScanConfigurationWithAttributeOverridesClass.class);
|
||||
assertSupportForComposedAnnotation(beanDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclassUsingAsm() {
|
||||
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclassUsingAsm() {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(
|
||||
SubMetaComponentScanConfigurationWithAttributeOverridesClass.class.getName());
|
||||
assertSupportForComposedAnnotation(beanDefinition);
|
||||
@@ -326,7 +324,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorOverridesNonApplicationBeanDefinitions() {
|
||||
public void postProcessorOverridesNonApplicationBeanDefinitions() {
|
||||
RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
|
||||
rbd.setRole(RootBeanDefinition.ROLE_SUPPORT);
|
||||
beanFactory.registerBeanDefinition("bar", rbd);
|
||||
@@ -339,7 +337,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorDoesNotOverrideRegularBeanDefinitions() {
|
||||
public void postProcessorDoesNotOverrideRegularBeanDefinitions() {
|
||||
RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
|
||||
rbd.setResource(new DescriptiveResource("XML or something"));
|
||||
beanFactory.registerBeanDefinition("bar", rbd);
|
||||
@@ -351,7 +349,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorDoesNotOverrideRegularBeanDefinitionsEvenWithScopedProxy() {
|
||||
public void postProcessorDoesNotOverrideRegularBeanDefinitionsEvenWithScopedProxy() {
|
||||
RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
|
||||
rbd.setResource(new DescriptiveResource("XML or something"));
|
||||
BeanDefinitionHolder proxied = ScopedProxyUtils.createScopedProxy(
|
||||
@@ -365,7 +363,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessorFailsOnImplicitOverrideIfOverridingIsNotAllowed() {
|
||||
public void postProcessorFailsOnImplicitOverrideIfOverridingIsNotAllowed() {
|
||||
RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
|
||||
rbd.setResource(new DescriptiveResource("XML or something"));
|
||||
beanFactory.registerBeanDefinition("bar", rbd);
|
||||
@@ -380,7 +378,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test // gh-25430
|
||||
void detectAliasOverride() {
|
||||
public void detectAliasOverride() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
|
||||
beanFactory.setAllowBeanDefinitionOverriding(false);
|
||||
@@ -392,7 +390,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void configurationClassesProcessedInCorrectOrder() {
|
||||
public void configurationClassesProcessedInCorrectOrder() {
|
||||
beanFactory.registerBeanDefinition("config1", new RootBeanDefinition(OverridingSingletonBeanConfig.class));
|
||||
beanFactory.registerBeanDefinition("config2", new RootBeanDefinition(SingletonBeanConfig.class));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
@@ -406,7 +404,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void configurationClassesWithValidOverridingForProgrammaticCall() {
|
||||
public void configurationClassesWithValidOverridingForProgrammaticCall() {
|
||||
beanFactory.registerBeanDefinition("config1", new RootBeanDefinition(OverridingAgainSingletonBeanConfig.class));
|
||||
beanFactory.registerBeanDefinition("config2", new RootBeanDefinition(OverridingSingletonBeanConfig.class));
|
||||
beanFactory.registerBeanDefinition("config3", new RootBeanDefinition(SingletonBeanConfig.class));
|
||||
@@ -421,7 +419,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void configurationClassesWithInvalidOverridingForProgrammaticCall() {
|
||||
public void configurationClassesWithInvalidOverridingForProgrammaticCall() {
|
||||
beanFactory.registerBeanDefinition("config1", new RootBeanDefinition(InvalidOverridingSingletonBeanConfig.class));
|
||||
beanFactory.registerBeanDefinition("config2", new RootBeanDefinition(OverridingSingletonBeanConfig.class));
|
||||
beanFactory.registerBeanDefinition("config3", new RootBeanDefinition(SingletonBeanConfig.class));
|
||||
@@ -437,7 +435,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test // SPR-15384
|
||||
void nestedConfigurationClassesProcessedInCorrectOrder() {
|
||||
public void nestedConfigurationClassesProcessedInCorrectOrder() {
|
||||
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(ConfigWithOrderedNestedClasses.class));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
pp.postProcessBeanFactory(beanFactory);
|
||||
@@ -450,7 +448,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test // SPR-16734
|
||||
void innerConfigurationClassesProcessedInCorrectOrder() {
|
||||
public void innerConfigurationClassesProcessedInCorrectOrder() {
|
||||
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(ConfigWithOrderedInnerClasses.class));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
pp.postProcessBeanFactory(beanFactory);
|
||||
@@ -464,7 +462,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void scopedProxyTargetMarkedAsNonAutowireCandidate() {
|
||||
public void scopedProxyTargetMarkedAsNonAutowireCandidate() {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(beanFactory);
|
||||
beanFactory.addBeanPostProcessor(bpp);
|
||||
@@ -481,7 +479,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void processingAllowedOnlyOncePerProcessorRegistryPair() {
|
||||
public void processingAllowedOnlyOncePerProcessorRegistryPair() {
|
||||
DefaultListableBeanFactory bf1 = new DefaultListableBeanFactory();
|
||||
DefaultListableBeanFactory bf2 = new DefaultListableBeanFactory();
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
@@ -494,7 +492,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjection() {
|
||||
public void genericsBasedInjection() {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(beanFactory);
|
||||
beanFactory.addBeanPostProcessor(bpp);
|
||||
@@ -511,7 +509,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithScoped() {
|
||||
public void genericsBasedInjectionWithScoped() {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(beanFactory);
|
||||
beanFactory.addBeanPostProcessor(bpp);
|
||||
@@ -528,7 +526,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithScopedProxy() {
|
||||
public void genericsBasedInjectionWithScopedProxy() {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(beanFactory);
|
||||
beanFactory.addBeanPostProcessor(bpp);
|
||||
@@ -548,7 +546,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithScopedProxyUsingAsm() {
|
||||
public void genericsBasedInjectionWithScopedProxyUsingAsm() {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(beanFactory);
|
||||
beanFactory.addBeanPostProcessor(bpp);
|
||||
@@ -568,7 +566,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithImplTypeAtInjectionPoint() {
|
||||
public void genericsBasedInjectionWithImplTypeAtInjectionPoint() {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(beanFactory);
|
||||
beanFactory.addBeanPostProcessor(bpp);
|
||||
@@ -585,7 +583,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithFactoryBean() {
|
||||
public void genericsBasedInjectionWithFactoryBean() {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(beanFactory);
|
||||
beanFactory.addBeanPostProcessor(bpp);
|
||||
@@ -604,7 +602,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithRawMatch() {
|
||||
public void genericsBasedInjectionWithRawMatch() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawMatchingConfiguration.class));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
pp.postProcessBeanFactory(beanFactory);
|
||||
@@ -613,7 +611,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithWildcardMatch() {
|
||||
public void genericsBasedInjectionWithWildcardMatch() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(WildcardMatchingConfiguration.class));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
pp.postProcessBeanFactory(beanFactory);
|
||||
@@ -622,7 +620,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithWildcardWithExtendsMatch() {
|
||||
public void genericsBasedInjectionWithWildcardWithExtendsMatch() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(WildcardWithExtendsConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
|
||||
@@ -630,7 +628,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithWildcardWithGenericExtendsMatch() {
|
||||
public void genericsBasedInjectionWithWildcardWithGenericExtendsMatch() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(WildcardWithGenericExtendsConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
|
||||
@@ -638,12 +636,12 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithEarlyGenericsMatching() {
|
||||
public void genericsBasedInjectionWithEarlyGenericsMatching() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RepositoryConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
|
||||
assertThat(beanNames).contains("stringRepo");
|
||||
assertThat(ObjectUtils.containsElement(beanNames, "stringRepo")).isTrue();
|
||||
|
||||
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
|
||||
assertThat(beanNames.length).isEqualTo(1);
|
||||
@@ -655,13 +653,13 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithLateGenericsMatching() {
|
||||
public void genericsBasedInjectionWithLateGenericsMatching() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RepositoryConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
beanFactory.preInstantiateSingletons();
|
||||
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
|
||||
assertThat(beanNames).contains("stringRepo");
|
||||
assertThat(ObjectUtils.containsElement(beanNames, "stringRepo")).isTrue();
|
||||
|
||||
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
|
||||
assertThat(beanNames.length).isEqualTo(1);
|
||||
@@ -673,12 +671,12 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithEarlyGenericsMatchingAndRawFactoryMethod() {
|
||||
public void genericsBasedInjectionWithEarlyGenericsMatchingAndRawFactoryMethod() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawFactoryMethodRepositoryConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
|
||||
assertThat(beanNames).contains("stringRepo");
|
||||
assertThat(ObjectUtils.containsElement(beanNames, "stringRepo")).isTrue();
|
||||
|
||||
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
|
||||
assertThat(beanNames.length).isEqualTo(0);
|
||||
@@ -688,13 +686,13 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithLateGenericsMatchingAndRawFactoryMethod() {
|
||||
public void genericsBasedInjectionWithLateGenericsMatchingAndRawFactoryMethod() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawFactoryMethodRepositoryConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
beanFactory.preInstantiateSingletons();
|
||||
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
|
||||
assertThat(beanNames).contains("stringRepo");
|
||||
assertThat(ObjectUtils.containsElement(beanNames, "stringRepo")).isTrue();
|
||||
|
||||
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
|
||||
assertThat(beanNames.length).isEqualTo(1);
|
||||
@@ -706,12 +704,12 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithEarlyGenericsMatchingAndRawInstance() {
|
||||
public void genericsBasedInjectionWithEarlyGenericsMatchingAndRawInstance() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawInstanceRepositoryConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
|
||||
assertThat(beanNames).contains("stringRepo");
|
||||
assertThat(ObjectUtils.containsElement(beanNames, "stringRepo")).isTrue();
|
||||
|
||||
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
|
||||
assertThat(beanNames.length).isEqualTo(1);
|
||||
@@ -723,13 +721,13 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithLateGenericsMatchingAndRawInstance() {
|
||||
public void genericsBasedInjectionWithLateGenericsMatchingAndRawInstance() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawInstanceRepositoryConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
beanFactory.preInstantiateSingletons();
|
||||
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
|
||||
assertThat(beanNames).contains("stringRepo");
|
||||
assertThat(ObjectUtils.containsElement(beanNames, "stringRepo")).isTrue();
|
||||
|
||||
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
|
||||
assertThat(beanNames.length).isEqualTo(1);
|
||||
@@ -741,7 +739,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithEarlyGenericsMatchingOnCglibProxy() {
|
||||
public void genericsBasedInjectionWithEarlyGenericsMatchingOnCglibProxy() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RepositoryConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
|
||||
@@ -751,7 +749,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
beanFactory.registerSingleton("traceInterceptor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor()));
|
||||
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
|
||||
assertThat(beanNames).contains("stringRepo");
|
||||
assertThat(ObjectUtils.containsElement(beanNames, "stringRepo")).isTrue();
|
||||
|
||||
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
|
||||
assertThat(beanNames.length).isEqualTo(1);
|
||||
@@ -765,7 +763,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithLateGenericsMatchingOnCglibProxy() {
|
||||
public void genericsBasedInjectionWithLateGenericsMatchingOnCglibProxy() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RepositoryConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
|
||||
@@ -776,7 +774,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
beanFactory.preInstantiateSingletons();
|
||||
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
|
||||
assertThat(beanNames).contains("stringRepo");
|
||||
assertThat(ObjectUtils.containsElement(beanNames, "stringRepo")).isTrue();
|
||||
|
||||
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
|
||||
assertThat(beanNames.length).isEqualTo(1);
|
||||
@@ -790,7 +788,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithLateGenericsMatchingOnCglibProxyAndRawFactoryMethod() {
|
||||
public void genericsBasedInjectionWithLateGenericsMatchingOnCglibProxyAndRawFactoryMethod() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawFactoryMethodRepositoryConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
|
||||
@@ -801,7 +799,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
beanFactory.preInstantiateSingletons();
|
||||
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
|
||||
assertThat(beanNames).contains("stringRepo");
|
||||
assertThat(ObjectUtils.containsElement(beanNames, "stringRepo")).isTrue();
|
||||
|
||||
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
|
||||
assertThat(beanNames.length).isEqualTo(1);
|
||||
@@ -815,7 +813,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithLateGenericsMatchingOnCglibProxyAndRawInstance() {
|
||||
public void genericsBasedInjectionWithLateGenericsMatchingOnCglibProxyAndRawInstance() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawInstanceRepositoryConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
|
||||
@@ -826,7 +824,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
beanFactory.preInstantiateSingletons();
|
||||
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
|
||||
assertThat(beanNames).contains("stringRepo");
|
||||
assertThat(ObjectUtils.containsElement(beanNames, "stringRepo")).isTrue();
|
||||
|
||||
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
|
||||
assertThat(beanNames.length).isEqualTo(1);
|
||||
@@ -840,7 +838,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithEarlyGenericsMatchingOnJdkProxy() {
|
||||
public void genericsBasedInjectionWithEarlyGenericsMatchingOnJdkProxy() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RepositoryConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
|
||||
@@ -849,7 +847,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
beanFactory.registerSingleton("traceInterceptor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor()));
|
||||
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(RepositoryInterface.class);
|
||||
assertThat(beanNames).contains("stringRepo");
|
||||
assertThat(ObjectUtils.containsElement(beanNames, "stringRepo")).isTrue();
|
||||
|
||||
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(RepositoryInterface.class, String.class));
|
||||
assertThat(beanNames.length).isEqualTo(1);
|
||||
@@ -863,7 +861,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithLateGenericsMatchingOnJdkProxy() {
|
||||
public void genericsBasedInjectionWithLateGenericsMatchingOnJdkProxy() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RepositoryConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
|
||||
@@ -873,7 +871,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
beanFactory.preInstantiateSingletons();
|
||||
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(RepositoryInterface.class);
|
||||
assertThat(beanNames).contains("stringRepo");
|
||||
assertThat(ObjectUtils.containsElement(beanNames, "stringRepo")).isTrue();
|
||||
|
||||
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(RepositoryInterface.class, String.class));
|
||||
assertThat(beanNames.length).isEqualTo(1);
|
||||
@@ -887,7 +885,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithLateGenericsMatchingOnJdkProxyAndRawFactoryMethod() {
|
||||
public void genericsBasedInjectionWithLateGenericsMatchingOnJdkProxyAndRawFactoryMethod() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawFactoryMethodRepositoryConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
|
||||
@@ -897,7 +895,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
beanFactory.preInstantiateSingletons();
|
||||
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(RepositoryInterface.class);
|
||||
assertThat(beanNames).contains("stringRepo");
|
||||
assertThat(ObjectUtils.containsElement(beanNames, "stringRepo")).isTrue();
|
||||
|
||||
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(RepositoryInterface.class, String.class));
|
||||
assertThat(beanNames.length).isEqualTo(1);
|
||||
@@ -911,7 +909,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericsBasedInjectionWithLateGenericsMatchingOnJdkProxyAndRawInstance() {
|
||||
public void genericsBasedInjectionWithLateGenericsMatchingOnJdkProxyAndRawInstance() {
|
||||
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawInstanceRepositoryConfiguration.class));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
|
||||
@@ -921,7 +919,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
beanFactory.preInstantiateSingletons();
|
||||
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(RepositoryInterface.class);
|
||||
assertThat(beanNames).contains("stringRepo");
|
||||
assertThat(ObjectUtils.containsElement(beanNames, "stringRepo")).isTrue();
|
||||
|
||||
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(RepositoryInterface.class, String.class));
|
||||
assertThat(beanNames.length).isEqualTo(1);
|
||||
@@ -935,7 +933,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSelfReferenceExclusionForFactoryMethodOnSameBean() {
|
||||
public void testSelfReferenceExclusionForFactoryMethodOnSameBean() {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(beanFactory);
|
||||
beanFactory.addBeanPostProcessor(bpp);
|
||||
@@ -949,7 +947,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConfigWithDefaultMethods() {
|
||||
public void testConfigWithDefaultMethods() {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(beanFactory);
|
||||
beanFactory.addBeanPostProcessor(bpp);
|
||||
@@ -963,7 +961,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConfigWithDefaultMethodsUsingAsm() {
|
||||
public void testConfigWithDefaultMethodsUsingAsm() {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(beanFactory);
|
||||
beanFactory.addBeanPostProcessor(bpp);
|
||||
@@ -977,7 +975,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCircularDependency() {
|
||||
public void testCircularDependency() {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(beanFactory);
|
||||
beanFactory.addBeanPostProcessor(bpp);
|
||||
@@ -990,38 +988,38 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCircularDependencyWithApplicationContext() {
|
||||
public void testCircularDependencyWithApplicationContext() {
|
||||
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
|
||||
new AnnotationConfigApplicationContext(A.class, AStrich.class))
|
||||
.withMessageContaining("Circular reference");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPrototypeArgumentThroughBeanMethodCall() {
|
||||
public void testPrototypeArgumentThroughBeanMethodCall() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanArgumentConfigWithPrototype.class);
|
||||
ctx.getBean(FooFactory.class).createFoo(new BarArgument());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSingletonArgumentThroughBeanMethodCall() {
|
||||
public void testSingletonArgumentThroughBeanMethodCall() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanArgumentConfigWithSingleton.class);
|
||||
ctx.getBean(FooFactory.class).createFoo(new BarArgument());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNullArgumentThroughBeanMethodCall() {
|
||||
public void testNullArgumentThroughBeanMethodCall() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanArgumentConfigWithNull.class);
|
||||
ctx.getBean("aFoo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInjectionPointMatchForNarrowTargetReturnType() {
|
||||
public void testInjectionPointMatchForNarrowTargetReturnType() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(FooBarConfiguration.class);
|
||||
assertThat(ctx.getBean(FooImpl.class).bar).isSameAs(ctx.getBean(BarImpl.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testVarargOnBeanMethod() {
|
||||
public void testVarargOnBeanMethod() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(VarargConfiguration.class, TestBean.class);
|
||||
VarargConfiguration bean = ctx.getBean(VarargConfiguration.class);
|
||||
assertThat(bean.testBeans).isNotNull();
|
||||
@@ -1030,7 +1028,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmptyVarargOnBeanMethod() {
|
||||
public void testEmptyVarargOnBeanMethod() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(VarargConfiguration.class);
|
||||
VarargConfiguration bean = ctx.getBean(VarargConfiguration.class);
|
||||
assertThat(bean.testBeans).isNotNull();
|
||||
@@ -1038,7 +1036,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCollectionArgumentOnBeanMethod() {
|
||||
public void testCollectionArgumentOnBeanMethod() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(CollectionArgumentConfiguration.class, TestBean.class);
|
||||
CollectionArgumentConfiguration bean = ctx.getBean(CollectionArgumentConfiguration.class);
|
||||
assertThat(bean.testBeans).isNotNull();
|
||||
@@ -1047,7 +1045,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmptyCollectionArgumentOnBeanMethod() {
|
||||
public void testEmptyCollectionArgumentOnBeanMethod() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(CollectionArgumentConfiguration.class);
|
||||
CollectionArgumentConfiguration bean = ctx.getBean(CollectionArgumentConfiguration.class);
|
||||
assertThat(bean.testBeans).isNotNull();
|
||||
@@ -1055,7 +1053,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMapArgumentOnBeanMethod() {
|
||||
public void testMapArgumentOnBeanMethod() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(MapArgumentConfiguration.class, DummyRunnable.class);
|
||||
MapArgumentConfiguration bean = ctx.getBean(MapArgumentConfiguration.class);
|
||||
assertThat(bean.testBeans).isNotNull();
|
||||
@@ -1064,7 +1062,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmptyMapArgumentOnBeanMethod() {
|
||||
public void testEmptyMapArgumentOnBeanMethod() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(MapArgumentConfiguration.class);
|
||||
MapArgumentConfiguration bean = ctx.getBean(MapArgumentConfiguration.class);
|
||||
assertThat(bean.testBeans).isNotNull();
|
||||
@@ -1072,7 +1070,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCollectionInjectionFromSameConfigurationClass() {
|
||||
public void testCollectionInjectionFromSameConfigurationClass() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(CollectionInjectionConfiguration.class);
|
||||
CollectionInjectionConfiguration bean = ctx.getBean(CollectionInjectionConfiguration.class);
|
||||
assertThat(bean.testBeans).isNotNull();
|
||||
@@ -1081,7 +1079,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMapInjectionFromSameConfigurationClass() {
|
||||
public void testMapInjectionFromSameConfigurationClass() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(MapInjectionConfiguration.class);
|
||||
MapInjectionConfiguration bean = ctx.getBean(MapInjectionConfiguration.class);
|
||||
assertThat(bean.testBeans).isNotNull();
|
||||
@@ -1090,7 +1088,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBeanLookupFromSameConfigurationClass() {
|
||||
public void testBeanLookupFromSameConfigurationClass() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanLookupConfiguration.class);
|
||||
BeanLookupConfiguration bean = ctx.getBean(BeanLookupConfiguration.class);
|
||||
assertThat(bean.getTestBean()).isNotNull();
|
||||
@@ -1098,7 +1096,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNameClashBetweenConfigurationClassAndBean() {
|
||||
public void testNameClashBetweenConfigurationClassAndBean() {
|
||||
assertThatExceptionOfType(BeanDefinitionStoreException.class).isThrownBy(() -> {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(MyTestBean.class);
|
||||
ctx.getBean("myTestBean", TestBean.class);
|
||||
@@ -1106,7 +1104,7 @@ class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBeanDefinitionRegistryPostProcessorConfig() {
|
||||
public void testBeanDefinitionRegistryPostProcessorConfig() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanDefinitionRegistryPostProcessorConfig.class);
|
||||
boolean condition = ctx.getBean("myTestBean") instanceof TestBean;
|
||||
assertThat(condition).isTrue();
|
||||
|
||||
+91
-129
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -18,10 +18,8 @@ package org.springframework.context.annotation;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
@@ -33,7 +31,6 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
@@ -50,13 +47,13 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
* @since 3.1
|
||||
*/
|
||||
class PropertySourceAnnotationTests {
|
||||
public class PropertySourceAnnotationTests {
|
||||
|
||||
|
||||
@Test
|
||||
void withExplicitName() {
|
||||
public void withExplicitName() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ConfigWithExplicitName.class);
|
||||
ctx.refresh();
|
||||
@@ -76,25 +73,29 @@ class PropertySourceAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void withImplicitName() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithImplicitName.class);
|
||||
public void withImplicitName() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ConfigWithImplicitName.class);
|
||||
ctx.refresh();
|
||||
assertThat(ctx.getEnvironment().getPropertySources().contains("class path resource [org/springframework/context/annotation/p1.properties]")).as("property source p1 was not added").isTrue();
|
||||
assertThat(ctx.getBean(TestBean.class).getName()).isEqualTo("p1TestBean");
|
||||
}
|
||||
|
||||
@Test
|
||||
void withTestProfileBeans() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithTestProfileBeans.class);
|
||||
public void withTestProfileBeans() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ConfigWithTestProfileBeans.class);
|
||||
ctx.refresh();
|
||||
assertThat(ctx.containsBean("testBean")).isTrue();
|
||||
assertThat(ctx.containsBean("testProfileBean")).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the LIFO behavior of @PropertySource annotations.
|
||||
* <p>The last one registered should 'win'.
|
||||
* Tests the LIFO behavior of @PropertySource annotaitons.
|
||||
* The last one registered should 'win'.
|
||||
*/
|
||||
@Test
|
||||
void orderingIsLifo() {
|
||||
public void orderingIsLifo() {
|
||||
{
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ConfigWithImplicitName.class, P2Config.class);
|
||||
@@ -113,7 +114,7 @@ class PropertySourceAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void withCustomFactory() {
|
||||
public void withCustomFactory() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ConfigWithImplicitName.class, WithCustomFactory.class);
|
||||
ctx.refresh();
|
||||
@@ -121,7 +122,7 @@ class PropertySourceAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void withCustomFactoryAsMeta() {
|
||||
public void withCustomFactoryAsMeta() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ConfigWithImplicitName.class, WithCustomFactoryAsMeta.class);
|
||||
ctx.refresh();
|
||||
@@ -129,43 +130,59 @@ class PropertySourceAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void withUnresolvablePlaceholder() {
|
||||
assertThatExceptionOfType(BeanDefinitionStoreException.class)
|
||||
.isThrownBy(() -> new AnnotationConfigApplicationContext(ConfigWithUnresolvablePlaceholder.class))
|
||||
.withCauseInstanceOf(IllegalArgumentException.class);
|
||||
public void withUnresolvablePlaceholder() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ConfigWithUnresolvablePlaceholder.class);
|
||||
try {
|
||||
ctx.refresh();
|
||||
}
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
assertThat(ex.getCause() instanceof IllegalArgumentException).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void withUnresolvablePlaceholderAndDefault() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithUnresolvablePlaceholderAndDefault.class);
|
||||
public void withUnresolvablePlaceholderAndDefault() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ConfigWithUnresolvablePlaceholderAndDefault.class);
|
||||
ctx.refresh();
|
||||
assertThat(ctx.getBean(TestBean.class).getName()).isEqualTo("p1TestBean");
|
||||
}
|
||||
|
||||
@Test
|
||||
void withResolvablePlaceholder() {
|
||||
public void withResolvablePlaceholder() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ConfigWithResolvablePlaceholder.class);
|
||||
System.setProperty("path.to.properties", "org/springframework/context/annotation");
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithResolvablePlaceholder.class);
|
||||
ctx.refresh();
|
||||
assertThat(ctx.getBean(TestBean.class).getName()).isEqualTo("p1TestBean");
|
||||
System.clearProperty("path.to.properties");
|
||||
}
|
||||
|
||||
@Test
|
||||
void withResolvablePlaceholderAndFactoryBean() {
|
||||
public void withResolvablePlaceholderAndFactoryBean() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ConfigWithResolvablePlaceholderAndFactoryBean.class);
|
||||
System.setProperty("path.to.properties", "org/springframework/context/annotation");
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithResolvablePlaceholderAndFactoryBean.class);
|
||||
ctx.refresh();
|
||||
assertThat(ctx.getBean(TestBean.class).getName()).isEqualTo("p1TestBean");
|
||||
System.clearProperty("path.to.properties");
|
||||
}
|
||||
|
||||
@Test
|
||||
void withEmptyResourceLocations() {
|
||||
assertThatExceptionOfType(BeanDefinitionStoreException.class)
|
||||
.isThrownBy(() -> new AnnotationConfigApplicationContext(ConfigWithEmptyResourceLocations.class))
|
||||
.withCauseInstanceOf(IllegalArgumentException.class);
|
||||
public void withEmptyResourceLocations() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ConfigWithEmptyResourceLocations.class);
|
||||
try {
|
||||
ctx.refresh();
|
||||
}
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
assertThat(ex.getCause() instanceof IllegalArgumentException).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void withNameAndMultipleResourceLocations() {
|
||||
public void withNameAndMultipleResourceLocations() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithNameAndMultipleResourceLocations.class);
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p1")).isTrue();
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p2")).isTrue();
|
||||
@@ -174,7 +191,7 @@ class PropertySourceAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void withMultipleResourceLocations() {
|
||||
public void withMultipleResourceLocations() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithMultipleResourceLocations.class);
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p1")).isTrue();
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p2")).isTrue();
|
||||
@@ -183,7 +200,7 @@ class PropertySourceAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void withRepeatedPropertySourcesInContainerAnnotation() {
|
||||
public void withPropertySources() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithPropertySources.class);
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p1")).isTrue();
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p2")).isTrue();
|
||||
@@ -192,43 +209,7 @@ class PropertySourceAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void withRepeatedPropertySources() {
|
||||
try (AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithRepeatedPropertySourceAnnotations.class)) {
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p1")).isTrue();
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p2")).isTrue();
|
||||
// p2 should 'win' as it was registered last
|
||||
assertThat(ctx.getEnvironment().getProperty("testbean.name")).isEqualTo("p2TestBean");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void withRepeatedPropertySourcesOnComposedAnnotation() {
|
||||
Class<?> configClass = ConfigWithRepeatedPropertySourceAnnotationsOnComposedAnnotation.class;
|
||||
String key = "custom.config.package";
|
||||
|
||||
System.clearProperty(key);
|
||||
try (ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(configClass)) {
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p1")).isTrue();
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p2")).isTrue();
|
||||
// p2 should 'win' as it was registered last
|
||||
assertThat(ctx.getEnvironment().getProperty("testbean.name")).isEqualTo("p2TestBean");
|
||||
}
|
||||
|
||||
System.setProperty(key, "org/springframework/context/annotation");
|
||||
try (ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(configClass)) {
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p1")).isTrue();
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p2")).isTrue();
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p3")).isTrue();
|
||||
// p3 should 'win' as it was registered last
|
||||
assertThat(ctx.getEnvironment().getProperty("testbean.name")).isEqualTo("p3TestBean");
|
||||
}
|
||||
finally {
|
||||
System.clearProperty(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void withNamedPropertySources() {
|
||||
public void withNamedPropertySources() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithNamedPropertySources.class);
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p1")).isTrue();
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p2")).isTrue();
|
||||
@@ -237,21 +218,21 @@ class PropertySourceAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void withMissingPropertySource() {
|
||||
assertThatExceptionOfType(BeanDefinitionStoreException.class)
|
||||
.isThrownBy(() -> new AnnotationConfigApplicationContext(ConfigWithMissingPropertySource.class))
|
||||
public void withMissingPropertySource() {
|
||||
assertThatExceptionOfType(BeanDefinitionStoreException.class).isThrownBy(() ->
|
||||
new AnnotationConfigApplicationContext(ConfigWithMissingPropertySource.class))
|
||||
.withCauseInstanceOf(FileNotFoundException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void withIgnoredPropertySource() {
|
||||
public void withIgnoredPropertySource() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithIgnoredPropertySource.class);
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p1")).isTrue();
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p2")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void withSameSourceImportedInDifferentOrder() {
|
||||
public void withSameSourceImportedInDifferentOrder() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithSameSourceImportedInDifferentOrder.class);
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p1")).isTrue();
|
||||
assertThat(ctx.getEnvironment().containsProperty("from.p2")).isTrue();
|
||||
@@ -259,7 +240,7 @@ class PropertySourceAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void orderingWithAndWithoutNameAndMultipleResourceLocations() {
|
||||
public void orderingWithAndWithoutNameAndMultipleResourceLocations() {
|
||||
// SPR-10820: p2 should 'win' as it was registered last
|
||||
AnnotationConfigApplicationContext ctxWithName = new AnnotationConfigApplicationContext(ConfigWithNameAndMultipleResourceLocations.class);
|
||||
AnnotationConfigApplicationContext ctxWithoutName = new AnnotationConfigApplicationContext(ConfigWithMultipleResourceLocations.class);
|
||||
@@ -268,14 +249,14 @@ class PropertySourceAnnotationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void orderingWithAndWithoutNameAndFourResourceLocations() {
|
||||
public void orderingWithAndWithoutNameAndFourResourceLocations() {
|
||||
// SPR-12198: p4 should 'win' as it was registered last
|
||||
AnnotationConfigApplicationContext ctxWithoutName = new AnnotationConfigApplicationContext(ConfigWithFourResourceLocations.class);
|
||||
assertThat(ctxWithoutName.getEnvironment().getProperty("testbean.name")).isEqualTo("p4TestBean");
|
||||
}
|
||||
|
||||
@Test
|
||||
void orderingDoesntReplaceExisting() throws Exception {
|
||||
public void orderingDoesntReplaceExisting() throws Exception {
|
||||
// SPR-12198: mySource should 'win' as it was registered manually
|
||||
AnnotationConfigApplicationContext ctxWithoutName = new AnnotationConfigApplicationContext();
|
||||
MapPropertySource mySource = new MapPropertySource("mine", Collections.singletonMap("testbean.name", "myTestBean"));
|
||||
@@ -286,51 +267,51 @@ class PropertySourceAnnotationTests {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:${unresolvable}/p1.properties")
|
||||
@PropertySource(value="classpath:${unresolvable}/p1.properties")
|
||||
static class ConfigWithUnresolvablePlaceholder {
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:${unresolvable:org/springframework/context/annotation}/p1.properties")
|
||||
@PropertySource(value="classpath:${unresolvable:org/springframework/context/annotation}/p1.properties")
|
||||
static class ConfigWithUnresolvablePlaceholderAndDefault {
|
||||
|
||||
@Inject Environment env;
|
||||
|
||||
@Bean
|
||||
TestBean testBean() {
|
||||
public TestBean testBean() {
|
||||
return new TestBean(env.getProperty("testbean.name"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:${path.to.properties}/p1.properties")
|
||||
@PropertySource(value="classpath:${path.to.properties}/p1.properties")
|
||||
static class ConfigWithResolvablePlaceholder {
|
||||
|
||||
@Inject Environment env;
|
||||
|
||||
@Bean
|
||||
TestBean testBean() {
|
||||
public TestBean testBean() {
|
||||
return new TestBean(env.getProperty("testbean.name"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:${path.to.properties}/p1.properties")
|
||||
@PropertySource(value="classpath:${path.to.properties}/p1.properties")
|
||||
static class ConfigWithResolvablePlaceholderAndFactoryBean {
|
||||
|
||||
@Inject Environment env;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Bean
|
||||
FactoryBean<TestBean> testBean() {
|
||||
public FactoryBean testBean() {
|
||||
final String name = env.getProperty("testbean.name");
|
||||
return new FactoryBean<TestBean>() {
|
||||
return new FactoryBean() {
|
||||
@Override
|
||||
public TestBean getObject() {
|
||||
public Object getObject() {
|
||||
return new TestBean(name);
|
||||
}
|
||||
@Override
|
||||
@@ -353,7 +334,7 @@ class PropertySourceAnnotationTests {
|
||||
@Inject Environment env;
|
||||
|
||||
@Bean
|
||||
TestBean testBean() {
|
||||
public TestBean testBean() {
|
||||
return new TestBean(env.getProperty("testbean.name"));
|
||||
}
|
||||
}
|
||||
@@ -366,7 +347,7 @@ class PropertySourceAnnotationTests {
|
||||
@Inject Environment env;
|
||||
|
||||
@Bean
|
||||
TestBean testBean() {
|
||||
public TestBean testBean() {
|
||||
return new TestBean(env.getProperty("testbean.name"));
|
||||
}
|
||||
}
|
||||
@@ -380,7 +361,7 @@ class PropertySourceAnnotationTests {
|
||||
@Inject Environment env;
|
||||
|
||||
@Bean @Profile("test")
|
||||
TestBean testBean() {
|
||||
public TestBean testBean() {
|
||||
return new TestBean(env.getProperty("testbean.name"));
|
||||
}
|
||||
}
|
||||
@@ -399,21 +380,21 @@ class PropertySourceAnnotationTests {
|
||||
|
||||
|
||||
@Configuration
|
||||
@MyPropertySource("classpath:org/springframework/context/annotation/p2.properties")
|
||||
@MyPropertySource(value = "classpath:org/springframework/context/annotation/p2.properties")
|
||||
static class WithCustomFactoryAsMeta {
|
||||
}
|
||||
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@PropertySource(value = {}, factory = MyCustomFactory.class)
|
||||
@interface MyPropertySource {
|
||||
public @interface MyPropertySource {
|
||||
|
||||
@AliasFor(annotation = PropertySource.class)
|
||||
String value();
|
||||
}
|
||||
|
||||
|
||||
static class MyCustomFactory implements PropertySourceFactory {
|
||||
public static class MyCustomFactory implements PropertySourceFactory {
|
||||
|
||||
@Override
|
||||
public org.springframework.core.env.PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
|
||||
@@ -441,10 +422,11 @@ class PropertySourceAnnotationTests {
|
||||
|
||||
|
||||
@Configuration
|
||||
@PropertySource({
|
||||
"classpath:org/springframework/context/annotation/p1.properties",
|
||||
"classpath:org/springframework/context/annotation/p2.properties"
|
||||
})
|
||||
@PropertySource(
|
||||
value = {
|
||||
"classpath:org/springframework/context/annotation/p1.properties",
|
||||
"classpath:org/springframework/context/annotation/p2.properties"
|
||||
})
|
||||
static class ConfigWithMultipleResourceLocations {
|
||||
}
|
||||
|
||||
@@ -452,33 +434,12 @@ class PropertySourceAnnotationTests {
|
||||
@Configuration
|
||||
@PropertySources({
|
||||
@PropertySource("classpath:org/springframework/context/annotation/p1.properties"),
|
||||
@PropertySource("classpath:${base.package}/p2.properties")
|
||||
@PropertySource("classpath:${base.package}/p2.properties"),
|
||||
})
|
||||
static class ConfigWithPropertySources {
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:org/springframework/context/annotation/p1.properties")
|
||||
@PropertySource(value = "classpath:${base.package}/p2.properties", ignoreResourceNotFound = true)
|
||||
static class ConfigWithRepeatedPropertySourceAnnotations {
|
||||
}
|
||||
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Configuration
|
||||
@PropertySource("classpath:org/springframework/context/annotation/p1.properties")
|
||||
@PropertySource(value = "classpath:${base.package}/p2.properties", ignoreResourceNotFound = true)
|
||||
@PropertySource(value = "classpath:${custom.config.package:bogus/config}/p3.properties", ignoreResourceNotFound = true)
|
||||
@interface ComposedConfiguration {
|
||||
}
|
||||
|
||||
@ComposedConfiguration
|
||||
static class ConfigWithRepeatedPropertySourceAnnotationsOnComposedAnnotation {
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@PropertySources({
|
||||
@PropertySource(name = "psName", value = "classpath:org/springframework/context/annotation/p1.properties"),
|
||||
@@ -510,7 +471,7 @@ class PropertySourceAnnotationTests {
|
||||
|
||||
|
||||
@Configuration
|
||||
@PropertySource({})
|
||||
@PropertySource(value = {})
|
||||
static class ConfigWithEmptyResourceLocations {
|
||||
}
|
||||
|
||||
@@ -521,7 +482,7 @@ class PropertySourceAnnotationTests {
|
||||
@PropertySource("classpath:org/springframework/context/annotation/p2.properties")
|
||||
})
|
||||
@Configuration
|
||||
static class ConfigWithSameSourceImportedInDifferentOrder {
|
||||
public static class ConfigWithSameSourceImportedInDifferentOrder {
|
||||
|
||||
}
|
||||
|
||||
@@ -531,17 +492,18 @@ class PropertySourceAnnotationTests {
|
||||
@PropertySource("classpath:org/springframework/context/annotation/p2.properties"),
|
||||
@PropertySource("classpath:org/springframework/context/annotation/p1.properties")
|
||||
})
|
||||
static class ConfigImportedWithSameSourceImportedInDifferentOrder {
|
||||
public static class ConfigImportedWithSameSourceImportedInDifferentOrder {
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@PropertySource({
|
||||
"classpath:org/springframework/context/annotation/p1.properties",
|
||||
"classpath:org/springframework/context/annotation/p2.properties",
|
||||
"classpath:org/springframework/context/annotation/p3.properties",
|
||||
"classpath:org/springframework/context/annotation/p4.properties"
|
||||
})
|
||||
@PropertySource(
|
||||
value = {
|
||||
"classpath:org/springframework/context/annotation/p1.properties",
|
||||
"classpath:org/springframework/context/annotation/p2.properties",
|
||||
"classpath:org/springframework/context/annotation/p3.properties",
|
||||
"classpath:org/springframework/context/annotation/p4.properties"
|
||||
})
|
||||
static class ConfigWithFourResourceLocations {
|
||||
}
|
||||
|
||||
|
||||
-55
@@ -307,23 +307,6 @@ public class ConfigurationClassProcessingTests {
|
||||
assertThat(tb.getLawyer()).isEqualTo(ctx.getBean(NestedTestBean.class));
|
||||
}
|
||||
|
||||
@Test // gh-26019
|
||||
public void autowiringWithDynamicPrototypeBeanClass() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
|
||||
ConfigWithDynamicPrototype.class, PrototypeDependency.class);
|
||||
|
||||
PrototypeInterface p1 = ctx.getBean(PrototypeInterface.class, 1);
|
||||
assertThat(p1).isInstanceOf(PrototypeOne.class);
|
||||
assertThat(((PrototypeOne) p1).prototypeDependency).isNotNull();
|
||||
|
||||
PrototypeInterface p2 = ctx.getBean(PrototypeInterface.class, 2);
|
||||
assertThat(p2).isInstanceOf(PrototypeTwo.class);
|
||||
|
||||
PrototypeInterface p3 = ctx.getBean(PrototypeInterface.class, 1);
|
||||
assertThat(p3).isInstanceOf(PrototypeOne.class);
|
||||
assertThat(((PrototypeOne) p3).prototypeDependency).isNotNull();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link BeanFactory}, populates it with a {@link BeanDefinition}
|
||||
@@ -649,42 +632,4 @@ public class ConfigurationClassProcessingTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class PrototypeDependency {
|
||||
}
|
||||
|
||||
interface PrototypeInterface {
|
||||
}
|
||||
|
||||
static class PrototypeOne extends AbstractPrototype {
|
||||
|
||||
@Autowired
|
||||
PrototypeDependency prototypeDependency;
|
||||
|
||||
}
|
||||
|
||||
static class PrototypeTwo extends AbstractPrototype {
|
||||
|
||||
// no autowired dependency here, in contrast to above
|
||||
}
|
||||
|
||||
static class AbstractPrototype implements PrototypeInterface {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ConfigWithDynamicPrototype {
|
||||
|
||||
@Bean
|
||||
@Scope(value = "prototype")
|
||||
public PrototypeInterface getDemoBean( int i) {
|
||||
switch ( i) {
|
||||
case 1: return new PrototypeOne();
|
||||
case 2:
|
||||
default:
|
||||
return new PrototypeTwo();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -49,11 +49,9 @@ public class PayloadApplicationEventTests {
|
||||
public void testProgrammaticEventListener() {
|
||||
List<Auditable> events = new ArrayList<>();
|
||||
ApplicationListener<AuditablePayloadEvent<String>> listener = events::add;
|
||||
ApplicationListener<AuditablePayloadEvent<Integer>> mismatch = (event -> event.getPayload().intValue());
|
||||
|
||||
ConfigurableApplicationContext ac = new GenericApplicationContext();
|
||||
ac.addApplicationListener(listener);
|
||||
ac.addApplicationListener(mismatch);
|
||||
ac.refresh();
|
||||
|
||||
AuditablePayloadEvent<String> event = new AuditablePayloadEvent<>(this, "xyz");
|
||||
@@ -65,11 +63,9 @@ public class PayloadApplicationEventTests {
|
||||
public void testProgrammaticPayloadListener() {
|
||||
List<String> events = new ArrayList<>();
|
||||
ApplicationListener<PayloadApplicationEvent<String>> listener = ApplicationListener.forPayload(events::add);
|
||||
ApplicationListener<PayloadApplicationEvent<Integer>> mismatch = ApplicationListener.forPayload(payload -> payload.intValue());
|
||||
|
||||
ConfigurableApplicationContext ac = new GenericApplicationContext();
|
||||
ac.addApplicationListener(listener);
|
||||
ac.addApplicationListener(mismatch);
|
||||
ac.refresh();
|
||||
|
||||
AuditablePayloadEvent<String> event = new AuditablePayloadEvent<>(this, "xyz");
|
||||
|
||||
+4
-33
@@ -25,47 +25,18 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link BitsCronField}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
class BitsCronFieldTests {
|
||||
public class BitsCronFieldTests {
|
||||
|
||||
@Test
|
||||
void parse() {
|
||||
assertThat(BitsCronField.parseSeconds("42")).has(clearRange(0, 41)).has(set(42)).has(clearRange(43, 59));
|
||||
assertThat(BitsCronField.parseMinutes("1,2,5,9")).has(clear(0)).has(set(1, 2)).has(clearRange(3,4)).has(set(5)).has(clearRange(6,8)).has(set(9)).has(clearRange(10,59));
|
||||
assertThat(BitsCronField.parseSeconds("0-4,8-12")).has(setRange(0, 4)).has(clearRange(5,7)).has(setRange(8, 12)).has(clearRange(13,59));
|
||||
assertThat(BitsCronField.parseSeconds("57/2")).has(clearRange(0, 56)).has(set(57)).has(clear(58)).has(set(59));
|
||||
|
||||
assertThat(BitsCronField.parseMinutes("30")).has(set(30)).has(clearRange(1, 29)).has(clearRange(31, 59));
|
||||
|
||||
assertThat(BitsCronField.parseHours("23")).has(set(23)).has(clearRange(0, 23));
|
||||
assertThat(BitsCronField.parseHours("0-23/2")).has(set(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22)).has(clear(1,3,5,7,9,11,13,15,17,19,21,23));
|
||||
|
||||
assertThat(BitsCronField.parseDaysOfMonth("1")).has(set(1)).has(clearRange(2, 31));
|
||||
|
||||
assertThat(BitsCronField.parseMonth("1")).has(set(1)).has(clearRange(2, 12));
|
||||
|
||||
assertThat(BitsCronField.parseDaysOfWeek("0")).has(set(7, 7)).has(clearRange(0, 6));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseLists() {
|
||||
assertThat(BitsCronField.parseSeconds("15,30")).has(set(15, 30)).has(clearRange(1, 15)).has(clearRange(31, 59));
|
||||
assertThat(BitsCronField.parseMinutes("1,2,5,9")).has(set(1, 2, 5, 9)).has(clear(0)).has(clearRange(3, 4)).has(clearRange(6, 8)).has(clearRange(10, 59));
|
||||
assertThat(BitsCronField.parseHours("1,2,3")).has(set(1, 2, 3)).has(clearRange(4, 23));
|
||||
assertThat(BitsCronField.parseDaysOfMonth("1,2,3")).has(set(1, 2, 3)).has(clearRange(4, 31));
|
||||
assertThat(BitsCronField.parseMonth("1,2,3")).has(set(1, 2, 3)).has(clearRange(4, 12));
|
||||
assertThat(BitsCronField.parseDaysOfWeek("1,2,3")).has(set(1, 2, 3)).has(clearRange(4, 7));
|
||||
|
||||
assertThat(BitsCronField.parseMinutes("5,10-30/2"))
|
||||
.has(clearRange(0, 5))
|
||||
.has(set(5))
|
||||
.has(clearRange(6,10))
|
||||
.has(set(10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30))
|
||||
.has(clear(11, 13, 15, 17, 19, 21, 23, 25, 27, 29))
|
||||
.has(clearRange(31, 60));
|
||||
assertThat(BitsCronField.parseDaysOfWeek("0")).has(clearRange(0, 6)).has(set(7, 7));
|
||||
assertThat(BitsCronField.parseSeconds("57/2")).has(clearRange(0, 56)).has(set(57)).has(clear(58)).has(set(59));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
-95
@@ -31,7 +31,6 @@ import org.junit.jupiter.api.Test;
|
||||
import static java.time.DayOfWeek.FRIDAY;
|
||||
import static java.time.DayOfWeek.MONDAY;
|
||||
import static java.time.DayOfWeek.SUNDAY;
|
||||
import static java.time.DayOfWeek.THURSDAY;
|
||||
import static java.time.DayOfWeek.TUESDAY;
|
||||
import static java.time.DayOfWeek.WEDNESDAY;
|
||||
import static java.time.temporal.TemporalAdjusters.next;
|
||||
@@ -117,7 +116,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.now().withMinute(10);
|
||||
LocalDateTime expected = last.plusMinutes(1).withSecond(0).withNano(0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -151,7 +149,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.of(year, 10, 30, 11, 1);
|
||||
LocalDateTime expected = last.withHour(12).withMinute(0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -176,7 +173,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.now().withDayOfMonth(1);
|
||||
LocalDateTime expected = last.plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -211,7 +207,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.now().withMonth(9).withDayOfMonth(30);
|
||||
LocalDateTime expected = LocalDateTime.of(last.getYear(), 10, 1, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -227,7 +222,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.now().withMonth(8).withDayOfMonth(30);
|
||||
LocalDateTime expected = last.plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -243,7 +237,6 @@ class CronExpressionTests {
|
||||
ZonedDateTime last = ZonedDateTime.now(ZoneId.of("CET")).withMonth(10).withDayOfMonth(30);
|
||||
ZonedDateTime expected = last.withDayOfMonth(31).withHour(0).withMinute(0).withSecond(0).withNano(0);
|
||||
ZonedDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -258,7 +251,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.now().withMonth(10).withDayOfMonth(30);
|
||||
LocalDateTime expected = LocalDateTime.of(last.getYear(), 11, 1, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -273,7 +265,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.now().withYear(2010).withMonth(12).withDayOfMonth(31);
|
||||
LocalDateTime expected = LocalDateTime.of(2011, 1, 1, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -306,7 +297,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.now().with(next(MONDAY));
|
||||
LocalDateTime expected = last.plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(TUESDAY);
|
||||
}
|
||||
@@ -318,7 +308,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.now().with(next(WEDNESDAY));
|
||||
LocalDateTime expected = last.plusDays(6).withHour(0).withMinute(0).withSecond(0).withNano(0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(TUESDAY);
|
||||
}
|
||||
@@ -330,7 +319,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.now().withMinute(4).withSecond(54);
|
||||
LocalDateTime expected = last.plusMinutes(1).withSecond(55).withNano(0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -345,7 +333,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.now().withHour(9).withSecond(54);
|
||||
LocalDateTime expected = last.plusHours(1).withMinute(0).withSecond(55).withNano(0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -360,7 +347,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.now().withHour(9).withMinute(4);
|
||||
LocalDateTime expected = last.plusHours(1).plusMinutes(1).withSecond(0).withNano(0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -376,7 +362,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.now().withDayOfMonth(2).withSecond(54);
|
||||
LocalDateTime expected = last.plusDays(1).withHour(0).withMinute(0).withSecond(55).withNano(0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -391,7 +376,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.now().withMonth(10).withDayOfMonth(2);
|
||||
LocalDateTime expected = LocalDateTime.of(last.getYear(), 11, 3, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -414,7 +398,6 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.now().withYear(2007).withMonth(2).withDayOfMonth(10);
|
||||
LocalDateTime expected = LocalDateTime.of(2008, 2, 29, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -430,14 +413,12 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.of(LocalDate.of(2009, 9, 26), LocalTime.now());
|
||||
LocalDateTime expected = last.plusDays(2).withHour(7).withMinute(0).withSecond(0).withNano(0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
// Next day is a week day so add one
|
||||
last = actual;
|
||||
expected = expected.plusDays(1);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -452,14 +433,12 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.of(LocalDate.of(2010, 12, 30), LocalTime.now());
|
||||
LocalDateTime expected = last.plusMonths(1).withHour(23).withMinute(30).withSecond(0).withSecond(0).withNano(0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
// Next trigger is 3 months later
|
||||
last = actual;
|
||||
expected = expected.plusMonths(3);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -506,13 +485,11 @@ class CronExpressionTests {
|
||||
LocalDateTime expected = LocalDateTime.of(last.getYear() + 1, 1, 1, 0, 0);
|
||||
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = expected.plusYears(1);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -536,13 +513,11 @@ class CronExpressionTests {
|
||||
LocalDateTime expected = LocalDateTime.of(last.getYear(), 11, 1, 0, 0);
|
||||
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = expected.plusMonths(1);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -559,13 +534,11 @@ class CronExpressionTests {
|
||||
LocalDateTime expected = last.with(next(SUNDAY)).withHour(0).withMinute(0).withSecond(0).withNano(0);
|
||||
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = expected.plusWeeks(1);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -582,13 +555,11 @@ class CronExpressionTests {
|
||||
LocalDateTime expected = last.plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
|
||||
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = expected.plusDays(1);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -612,13 +583,11 @@ class CronExpressionTests {
|
||||
LocalDateTime expected = last.plusHours(1).withMinute(0).withSecond(0).withNano(0);
|
||||
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = expected.plusHours(1);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -634,19 +603,16 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.of(LocalDate.of(2008, 1, 4), LocalTime.now());
|
||||
LocalDateTime expected = LocalDateTime.of(2008, 1, 31, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 2, 29, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 3, 31, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -662,19 +628,16 @@ class CronExpressionTests {
|
||||
LocalDateTime last = LocalDateTime.of(LocalDate.of(2008, 1, 4), LocalTime.now());
|
||||
LocalDateTime expected = LocalDateTime.of(2008, 1, 28, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 2, 26, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 3, 28, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
@@ -1079,62 +1042,4 @@ class CronExpressionTests {
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(WEDNESDAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void dayOfMonthListWithQuartz() {
|
||||
CronExpression expression = CronExpression.parse("0 0 0 1W,15,LW * ?");
|
||||
|
||||
LocalDateTime last = LocalDateTime.of(2019, 12, 30, 0, 0);
|
||||
LocalDateTime expected = LocalDateTime.of(2019, 12, 31, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 1, 1, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 1, 15, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 1, 31, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
}
|
||||
|
||||
@Test
|
||||
void dayOfWeekListWithQuartz() {
|
||||
CronExpression expression = CronExpression.parse("0 0 0 ? * THU#1,THU#3,THU#5");
|
||||
|
||||
LocalDateTime last = LocalDateTime.of(2019, 12, 31, 0, 0);
|
||||
LocalDateTime expected = LocalDateTime.of(2020, 1, 2, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(THURSDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 1, 16, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(THURSDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 1, 30, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(THURSDAY);
|
||||
}
|
||||
}
|
||||
|
||||
-3
@@ -25,8 +25,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link QuartzCronField}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
class QuartzCronFieldTests {
|
||||
@@ -97,7 +95,6 @@ class QuartzCronFieldTests {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("1#L"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("L#1"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("8#1"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("2#1,2#3,2#5"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
testbean.name=p3TestBean
|
||||
from.p3=p3Value
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -58,10 +58,10 @@ internal fun <T: Any> monoToDeferred(source: Mono<T>) =
|
||||
* @since 5.2
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun invokeSuspendingFunction(method: Method, target: Any, vararg args: Any?): Publisher<*> {
|
||||
fun invokeSuspendingFunction(method: Method, bean: Any, vararg args: Any?): Publisher<*> {
|
||||
val function = method.kotlinFunction!!
|
||||
val mono = mono(Dispatchers.Unconfined) {
|
||||
function.callSuspend(target, *args.sliceArray(0..(args.size-2))).let { if (it == Unit) null else it }
|
||||
function.callSuspend(bean, *args.sliceArray(0..(args.size-2))).let { if (it == Unit) null else it }
|
||||
}.onErrorMap(InvocationTargetException::class.java) { it.targetException }
|
||||
return if (function.returnType.classifier == Flow::class) {
|
||||
mono.flatMapMany { (it as Flow<Any>).asFlux() }
|
||||
|
||||
@@ -129,9 +129,9 @@ public abstract class AnnotationVisitor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an array value of the annotation. Note that arrays of primitive values (such as byte,
|
||||
* Visits an array value of the annotation. Note that arrays of primitive types (such as byte,
|
||||
* boolean, short, char, int, long, float or double) can be passed as value to {@link #visit
|
||||
* visit}. This is what {@link ClassReader} does for non empty arrays of primitive values.
|
||||
* visit}. This is what {@link ClassReader} does.
|
||||
*
|
||||
* @param name the value name.
|
||||
* @return a visitor to visit the actual array value elements, or {@literal null} if this visitor
|
||||
|
||||
@@ -100,10 +100,8 @@ public class ClassReader {
|
||||
@Deprecated
|
||||
// DontCheck(MemberName): can't be renamed (for backward binary compatibility).
|
||||
public final byte[] b;
|
||||
|
||||
/** The offset in bytes of the ClassFile's access_flags field. */
|
||||
public final int header;
|
||||
|
||||
/**
|
||||
* A byte array containing the JVMS ClassFile structure to be parsed. <i>The content of this array
|
||||
* must not be modified. This field is intended for {@link Attribute} sub classes, and is normally
|
||||
@@ -114,7 +112,6 @@ public class ClassReader {
|
||||
* ClassFile element offsets within this byte array.
|
||||
*/
|
||||
final byte[] classFileBuffer;
|
||||
|
||||
/**
|
||||
* The offset in bytes, in {@link #classFileBuffer}, of each cp_info entry of the ClassFile's
|
||||
* constant_pool array, <i>plus one</i>. In other words, the offset of constant pool entry i is
|
||||
@@ -122,19 +119,16 @@ public class ClassReader {
|
||||
* 1].
|
||||
*/
|
||||
private final int[] cpInfoOffsets;
|
||||
|
||||
/**
|
||||
* The String objects corresponding to the CONSTANT_Utf8 constant pool items. This cache avoids
|
||||
* multiple parsing of a given CONSTANT_Utf8 constant pool item.
|
||||
*/
|
||||
private final String[] constantUtf8Values;
|
||||
|
||||
/**
|
||||
* The ConstantDynamic objects corresponding to the CONSTANT_Dynamic constant pool items. This
|
||||
* cache avoids multiple parsing of a given CONSTANT_Dynamic constant pool item.
|
||||
*/
|
||||
private final ConstantDynamic[] constantDynamicValues;
|
||||
|
||||
/**
|
||||
* The start offsets in {@link #classFileBuffer} of each element of the bootstrap_methods array
|
||||
* (in the BootstrapMethods attribute).
|
||||
@@ -143,7 +137,6 @@ public class ClassReader {
|
||||
* 4.7.23</a>
|
||||
*/
|
||||
private final int[] bootstrapMethodOffsets;
|
||||
|
||||
/**
|
||||
* A conservative estimate of the maximum length of the strings contained in the constant pool of
|
||||
* the class.
|
||||
@@ -191,7 +184,7 @@ public class ClassReader {
|
||||
this.b = classFileBuffer;
|
||||
// Check the class' major_version. This field is after the magic and minor_version fields, which
|
||||
// use 4 and 2 bytes respectively.
|
||||
if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V17) {
|
||||
if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V16) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unsupported class file major version " + readShort(classFileOffset + 6));
|
||||
}
|
||||
@@ -506,9 +499,6 @@ public class ClassReader {
|
||||
} else if (Constants.SYNTHETIC.equals(attributeName)) {
|
||||
accessFlags |= Opcodes.ACC_SYNTHETIC;
|
||||
} else if (Constants.SOURCE_DEBUG_EXTENSION.equals(attributeName)) {
|
||||
if (attributeLength > classFileBuffer.length - currentAttributeOffset) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
sourceDebugExtension =
|
||||
readUtf(currentAttributeOffset, attributeLength, new char[attributeLength]);
|
||||
} else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) {
|
||||
@@ -1519,9 +1509,6 @@ public class ClassReader {
|
||||
final int maxLocals = readUnsignedShort(currentOffset + 2);
|
||||
final int codeLength = readInt(currentOffset + 4);
|
||||
currentOffset += 8;
|
||||
if (codeLength > classFileBuffer.length - currentOffset) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
// Read the bytecode 'code' array to create a label for each referenced instruction.
|
||||
final int bytecodeStartOffset = currentOffset;
|
||||
@@ -2978,7 +2965,7 @@ public class ClassReader {
|
||||
// Parse the array_value array.
|
||||
while (numElementValuePairs-- > 0) {
|
||||
currentOffset =
|
||||
readElementValue(annotationVisitor, currentOffset, /* elementName= */ null, charBuffer);
|
||||
readElementValue(annotationVisitor, currentOffset, /* elementName = */ null, charBuffer);
|
||||
}
|
||||
}
|
||||
if (annotationVisitor != null) {
|
||||
|
||||
@@ -132,7 +132,7 @@ public interface Opcodes {
|
||||
* <pre>
|
||||
* public class StuffVisitor {
|
||||
* @Deprecated public void visitOldStuff(int arg, ...) {
|
||||
* visitNewStuff(arg | SOURCE_DEPRECATED, ...);
|
||||
* visitNewStuf(arg | SOURCE_DEPRECATED, ...);
|
||||
* }
|
||||
* public void visitNewStuff(int argAndSource...) {
|
||||
* if ((argAndSource & SOURCE_DEPRECATED) == 0) {
|
||||
@@ -154,7 +154,7 @@ public interface Opcodes {
|
||||
* <p>and there are two cases:
|
||||
*
|
||||
* <ul>
|
||||
* <li>call visitOldStuff: in the call to super.visitOldStuff, the source is set to
|
||||
* <li>call visitOldSuff: in the call to super.visitOldStuff, the source is set to
|
||||
* SOURCE_DEPRECATED and visitNewStuff is called. Here 'do stuff' is run because the source
|
||||
* was previously set to SOURCE_DEPRECATED, and execution eventually returns to
|
||||
* UserStuffVisitor.visitOldStuff, where 'do user stuff' is run.
|
||||
@@ -281,7 +281,6 @@ public interface Opcodes {
|
||||
int V14 = 0 << 16 | 58;
|
||||
int V15 = 0 << 16 | 59;
|
||||
int V16 = 0 << 16 | 60;
|
||||
int V17 = 0 << 16 | 61;
|
||||
|
||||
/**
|
||||
* Version flag indicating that the class is using 'preview' features.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,24 +16,20 @@
|
||||
|
||||
package org.springframework.core;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Interface defining a generic contract for attaching and accessing metadata
|
||||
* to/from arbitrary objects.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Sam Brannen
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface AttributeAccessor {
|
||||
|
||||
/**
|
||||
* Set the attribute defined by {@code name} to the supplied {@code value}.
|
||||
* <p>If {@code value} is {@code null}, the attribute is {@link #removeAttribute removed}.
|
||||
* If {@code value} is {@code null}, the attribute is {@link #removeAttribute removed}.
|
||||
* <p>In general, users should take care to prevent overlaps with other
|
||||
* metadata attributes by using fully-qualified names, perhaps using
|
||||
* class or package names as prefix.
|
||||
@@ -44,48 +40,16 @@ public interface AttributeAccessor {
|
||||
|
||||
/**
|
||||
* Get the value of the attribute identified by {@code name}.
|
||||
* <p>Return {@code null} if the attribute doesn't exist.
|
||||
* Return {@code null} if the attribute doesn't exist.
|
||||
* @param name the unique attribute key
|
||||
* @return the current value of the attribute, if any
|
||||
*/
|
||||
@Nullable
|
||||
Object getAttribute(String name);
|
||||
|
||||
/**
|
||||
* Compute a new value for the attribute identified by {@code name} if
|
||||
* necessary and {@linkplain #setAttribute set} the new value in this
|
||||
* {@code AttributeAccessor}.
|
||||
* <p>If a value for the attribute identified by {@code name} already exists
|
||||
* in this {@code AttributeAccessor}, the existing value will be returned
|
||||
* without applying the supplied compute function.
|
||||
* <p>The default implementation of this method is not thread safe but can
|
||||
* overridden by concrete implementations of this interface.
|
||||
* @param <T> the type of the attribute value
|
||||
* @param name the unique attribute key
|
||||
* @param computeFunction a function that computes a new value for the attribute
|
||||
* name; the function must not return a {@code null} value
|
||||
* @return the existing value or newly computed value for the named attribute
|
||||
* @see #getAttribute(String)
|
||||
* @see #setAttribute(String, Object)
|
||||
* @since 5.3.3
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default <T> T computeAttribute(String name, Function<String, T> computeFunction) {
|
||||
Assert.notNull(name, "Name must not be null");
|
||||
Assert.notNull(computeFunction, "Compute function must not be null");
|
||||
Object value = getAttribute(name);
|
||||
if (value == null) {
|
||||
value = computeFunction.apply(name);
|
||||
Assert.state(value != null,
|
||||
() -> String.format("Compute function must not return null for attribute named '%s'", name));
|
||||
setAttribute(name, value);
|
||||
}
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the attribute identified by {@code name} and return its value.
|
||||
* <p>Return {@code null} if no attribute under {@code name} is found.
|
||||
* Return {@code null} if no attribute under {@code name} is found.
|
||||
* @param name the unique attribute key
|
||||
* @return the last value of the attribute, if any
|
||||
*/
|
||||
@@ -94,7 +58,7 @@ public interface AttributeAccessor {
|
||||
|
||||
/**
|
||||
* Return {@code true} if the attribute identified by {@code name} exists.
|
||||
* <p>Otherwise return {@code false}.
|
||||
* Otherwise return {@code false}.
|
||||
* @param name the unique attribute key
|
||||
*/
|
||||
boolean hasAttribute(String name);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -19,7 +19,6 @@ package org.springframework.core;
|
||||
import java.io.Serializable;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -33,7 +32,6 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@@ -61,17 +59,6 @@ public abstract class AttributeAccessorSupport implements AttributeAccessor, Ser
|
||||
return this.attributes.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T computeAttribute(String name, Function<String, T> computeFunction) {
|
||||
Assert.notNull(name, "Name must not be null");
|
||||
Assert.notNull(computeFunction, "Compute function must not be null");
|
||||
Object value = this.attributes.computeIfAbsent(name, computeFunction);
|
||||
Assert.state(value != null,
|
||||
() -> String.format("Compute function must not return null for attribute named '%s'", name));
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object removeAttribute(String name) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -225,11 +225,11 @@ public final class Conventions {
|
||||
if (!attributeName.contains("-")) {
|
||||
return attributeName;
|
||||
}
|
||||
char[] result = new char[attributeName.length() -1]; // not completely accurate but good guess
|
||||
char[] chars = attributeName.toCharArray();
|
||||
char[] result = new char[chars.length -1]; // not completely accurate but good guess
|
||||
int currPos = 0;
|
||||
boolean upperCaseNext = false;
|
||||
for (int i = 0; i < attributeName.length(); i++ ) {
|
||||
char c = attributeName.charAt(i);
|
||||
for (char c : chars) {
|
||||
if (c == '-') {
|
||||
upperCaseNext = true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -60,28 +60,7 @@ public class ReactiveAdapterRegistry {
|
||||
@Nullable
|
||||
private static volatile ReactiveAdapterRegistry sharedInstance;
|
||||
|
||||
private static final boolean reactorPresent;
|
||||
|
||||
private static final boolean rxjava1Present;
|
||||
|
||||
private static final boolean rxjava2Present;
|
||||
|
||||
private static final boolean rxjava3Present;
|
||||
|
||||
private static final boolean flowPublisherPresent;
|
||||
|
||||
private static final boolean kotlinCoroutinesPresent;
|
||||
|
||||
static {
|
||||
ClassLoader classLoader = ReactiveAdapterRegistry.class.getClassLoader();
|
||||
reactorPresent = ClassUtils.isPresent("reactor.core.publisher.Flux", classLoader);
|
||||
rxjava1Present = ClassUtils.isPresent("rx.Observable", classLoader) &&
|
||||
ClassUtils.isPresent("rx.RxReactiveStreams", classLoader);
|
||||
rxjava2Present = ClassUtils.isPresent("io.reactivex.Flowable", classLoader);
|
||||
rxjava3Present = ClassUtils.isPresent("io.reactivex.rxjava3.core.Flowable", classLoader);
|
||||
flowPublisherPresent = ClassUtils.isPresent("java.util.concurrent.Flow.Publisher", classLoader);
|
||||
kotlinCoroutinesPresent = ClassUtils.isPresent("kotlinx.coroutines.reactor.MonoKt", classLoader);
|
||||
}
|
||||
private final boolean reactorPresent;
|
||||
|
||||
private final List<ReactiveAdapter> adapters = new ArrayList<>();
|
||||
|
||||
@@ -91,34 +70,41 @@ public class ReactiveAdapterRegistry {
|
||||
* @see #getSharedInstance()
|
||||
*/
|
||||
public ReactiveAdapterRegistry() {
|
||||
ClassLoader classLoader = ReactiveAdapterRegistry.class.getClassLoader();
|
||||
|
||||
// Reactor
|
||||
if (reactorPresent) {
|
||||
boolean reactorRegistered = false;
|
||||
if (ClassUtils.isPresent("reactor.core.publisher.Flux", classLoader)) {
|
||||
new ReactorRegistrar().registerAdapters(this);
|
||||
reactorRegistered = true;
|
||||
}
|
||||
this.reactorPresent = reactorRegistered;
|
||||
|
||||
// RxJava1 (deprecated)
|
||||
if (rxjava1Present) {
|
||||
if (ClassUtils.isPresent("rx.Observable", classLoader) &&
|
||||
ClassUtils.isPresent("rx.RxReactiveStreams", classLoader)) {
|
||||
new RxJava1Registrar().registerAdapters(this);
|
||||
}
|
||||
|
||||
// RxJava2
|
||||
if (rxjava2Present) {
|
||||
if (ClassUtils.isPresent("io.reactivex.Flowable", classLoader)) {
|
||||
new RxJava2Registrar().registerAdapters(this);
|
||||
}
|
||||
|
||||
// RxJava3
|
||||
if (rxjava3Present) {
|
||||
if (ClassUtils.isPresent("io.reactivex.rxjava3.core.Flowable", classLoader)) {
|
||||
new RxJava3Registrar().registerAdapters(this);
|
||||
}
|
||||
|
||||
// Java 9+ Flow.Publisher
|
||||
if (flowPublisherPresent) {
|
||||
if (ClassUtils.isPresent("java.util.concurrent.Flow.Publisher", classLoader)) {
|
||||
new ReactorJdkFlowAdapterRegistrar().registerAdapter(this);
|
||||
}
|
||||
// If not present, do nothing for the time being...
|
||||
// We can fall back on "reactive-streams-flow-bridge" (once released)
|
||||
|
||||
// Kotlin Coroutines
|
||||
if (reactorPresent && kotlinCoroutinesPresent) {
|
||||
// Coroutines
|
||||
if (this.reactorPresent && ClassUtils.isPresent("kotlinx.coroutines.reactor.MonoKt", classLoader)) {
|
||||
new CoroutinesRegistrar().registerAdapters(this);
|
||||
}
|
||||
}
|
||||
@@ -139,7 +125,7 @@ public class ReactiveAdapterRegistry {
|
||||
public void registerReactiveType(ReactiveTypeDescriptor descriptor,
|
||||
Function<Object, Publisher<?>> toAdapter, Function<Publisher<?>, Object> fromAdapter) {
|
||||
|
||||
if (reactorPresent) {
|
||||
if (this.reactorPresent) {
|
||||
this.adapters.add(new ReactorAdapter(descriptor, toAdapter, fromAdapter));
|
||||
}
|
||||
else {
|
||||
@@ -278,12 +264,14 @@ public class ReactiveAdapterRegistry {
|
||||
registry.registerReactiveType(
|
||||
ReactiveTypeDescriptor.multiValue(io.reactivex.Observable.class, io.reactivex.Observable::empty),
|
||||
source -> ((io.reactivex.Observable<?>) source).toFlowable(io.reactivex.BackpressureStrategy.BUFFER),
|
||||
io.reactivex.Observable::fromPublisher
|
||||
source -> io.reactivex.Flowable.fromPublisher(source)
|
||||
.toObservable()
|
||||
);
|
||||
registry.registerReactiveType(
|
||||
ReactiveTypeDescriptor.singleRequiredValue(io.reactivex.Single.class),
|
||||
source -> ((io.reactivex.Single<?>) source).toFlowable(),
|
||||
io.reactivex.Single::fromPublisher
|
||||
source -> io.reactivex.Flowable.fromPublisher(source)
|
||||
.toObservable().singleElement().toSingle()
|
||||
);
|
||||
registry.registerReactiveType(
|
||||
ReactiveTypeDescriptor.singleOptionalValue(io.reactivex.Maybe.class, io.reactivex.Maybe::empty),
|
||||
@@ -294,7 +282,8 @@ public class ReactiveAdapterRegistry {
|
||||
registry.registerReactiveType(
|
||||
ReactiveTypeDescriptor.noValue(io.reactivex.Completable.class, io.reactivex.Completable::complete),
|
||||
source -> ((io.reactivex.Completable) source).toFlowable(),
|
||||
io.reactivex.Completable::fromPublisher
|
||||
source -> io.reactivex.Flowable.fromPublisher(source)
|
||||
.toObservable().ignoreElements()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -315,26 +304,30 @@ public class ReactiveAdapterRegistry {
|
||||
io.reactivex.rxjava3.core.Observable::empty),
|
||||
source -> ((io.reactivex.rxjava3.core.Observable<?>) source).toFlowable(
|
||||
io.reactivex.rxjava3.core.BackpressureStrategy.BUFFER),
|
||||
io.reactivex.rxjava3.core.Observable::fromPublisher
|
||||
source -> io.reactivex.rxjava3.core.Flowable.fromPublisher(source)
|
||||
.toObservable()
|
||||
);
|
||||
registry.registerReactiveType(
|
||||
ReactiveTypeDescriptor.singleRequiredValue(io.reactivex.rxjava3.core.Single.class),
|
||||
source -> ((io.reactivex.rxjava3.core.Single<?>) source).toFlowable(),
|
||||
io.reactivex.rxjava3.core.Single::fromPublisher
|
||||
source -> io.reactivex.rxjava3.core.Flowable.fromPublisher(source)
|
||||
.toObservable().singleElement().toSingle()
|
||||
);
|
||||
registry.registerReactiveType(
|
||||
ReactiveTypeDescriptor.singleOptionalValue(
|
||||
io.reactivex.rxjava3.core.Maybe.class,
|
||||
io.reactivex.rxjava3.core.Maybe::empty),
|
||||
source -> ((io.reactivex.rxjava3.core.Maybe<?>) source).toFlowable(),
|
||||
io.reactivex.rxjava3.core.Maybe::fromPublisher
|
||||
source -> io.reactivex.rxjava3.core.Flowable.fromPublisher(source)
|
||||
.toObservable().singleElement()
|
||||
);
|
||||
registry.registerReactiveType(
|
||||
ReactiveTypeDescriptor.noValue(
|
||||
io.reactivex.rxjava3.core.Completable.class,
|
||||
io.reactivex.rxjava3.core.Completable::complete),
|
||||
source -> ((io.reactivex.rxjava3.core.Completable) source).toFlowable(),
|
||||
io.reactivex.rxjava3.core.Completable::fromPublisher
|
||||
source -> io.reactivex.rxjava3.core.Flowable.fromPublisher(source)
|
||||
.toObservable().ignoreElements()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -47,6 +50,8 @@ public final class SpringProperties {
|
||||
|
||||
private static final String PROPERTIES_RESOURCE_LOCATION = "spring.properties";
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SpringProperties.class);
|
||||
|
||||
private static final Properties localProperties = new Properties();
|
||||
|
||||
|
||||
@@ -56,13 +61,16 @@ public final class SpringProperties {
|
||||
URL url = (cl != null ? cl.getResource(PROPERTIES_RESOURCE_LOCATION) :
|
||||
ClassLoader.getSystemResource(PROPERTIES_RESOURCE_LOCATION));
|
||||
if (url != null) {
|
||||
logger.debug("Found 'spring.properties' file in local classpath");
|
||||
try (InputStream is = url.openStream()) {
|
||||
localProperties.load(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
System.err.println("Could not load 'spring.properties' file from local classpath: " + ex);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Could not load 'spring.properties' file from local classpath: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +108,9 @@ public final class SpringProperties {
|
||||
value = System.getProperty(key);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
System.err.println("Could not retrieve system property '" + key + "': " + ex);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not retrieve system property '" + key + "': " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
|
||||
+17
-30
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -18,8 +18,8 @@ package org.springframework.core.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.IntFunction;
|
||||
@@ -31,11 +31,10 @@ import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* {@link Collector} implementations that provide various reduction operations for
|
||||
* Collector implementations that provide various reduction operations for
|
||||
* {@link MergedAnnotation} instances.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
* @since 5.2
|
||||
*/
|
||||
public abstract class MergedAnnotationCollectors {
|
||||
@@ -53,16 +52,13 @@ public abstract class MergedAnnotationCollectors {
|
||||
* Create a new {@link Collector} that accumulates merged annotations to a
|
||||
* {@link LinkedHashSet} containing {@linkplain MergedAnnotation#synthesize()
|
||||
* synthesized} versions.
|
||||
* <p>The collector returned by this method is effectively equivalent to
|
||||
* {@code Collectors.mapping(MergedAnnotation::synthesize, Collectors.toCollection(LinkedHashSet::new))}
|
||||
* but avoids the creation of a composite collector.
|
||||
* @param <A> the annotation type
|
||||
* @return a {@link Collector} which collects and synthesizes the
|
||||
* annotations into a {@link Set}
|
||||
*/
|
||||
public static <A extends Annotation> Collector<MergedAnnotation<A>, ?, Set<A>> toAnnotationSet() {
|
||||
return Collector.of(LinkedHashSet::new, (set, annotation) -> set.add(annotation.synthesize()),
|
||||
MergedAnnotationCollectors::combiner);
|
||||
return Collector.of(ArrayList<A>::new, (list, annotation) -> list.add(annotation.synthesize()),
|
||||
MergedAnnotationCollectors::addAll, LinkedHashSet::new);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,14 +90,14 @@ public abstract class MergedAnnotationCollectors {
|
||||
IntFunction<R[]> generator) {
|
||||
|
||||
return Collector.of(ArrayList::new, (list, annotation) -> list.add(annotation.synthesize()),
|
||||
MergedAnnotationCollectors::combiner, list -> list.toArray(generator.apply(list.size())));
|
||||
MergedAnnotationCollectors::addAll, list -> list.toArray(generator.apply(list.size())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Collector} that accumulates merged annotations to a
|
||||
* Create a new {@link Collector} that accumulates merged annotations to an
|
||||
* {@link MultiValueMap} with items {@linkplain MultiValueMap#add(Object, Object)
|
||||
* added} from each merged annotation
|
||||
* {@linkplain MergedAnnotation#asMap(Adapt...) as a map}.
|
||||
* {@link MergedAnnotation#asMap(Adapt...) as a map}.
|
||||
* @param <A> the annotation type
|
||||
* @param adaptations the adaptations that should be applied to the annotation values
|
||||
* @return a {@link Collector} which collects and synthesizes the
|
||||
@@ -115,13 +111,13 @@ public abstract class MergedAnnotationCollectors {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Collector} that accumulates merged annotations to a
|
||||
* Create a new {@link Collector} that accumulates merged annotations to an
|
||||
* {@link MultiValueMap} with items {@linkplain MultiValueMap#add(Object, Object)
|
||||
* added} from each merged annotation
|
||||
* {@linkplain MergedAnnotation#asMap(Adapt...) as a map}.
|
||||
* {@link MergedAnnotation#asMap(Adapt...) as a map}.
|
||||
* @param <A> the annotation type
|
||||
* @param finisher the finisher function for the new {@link MultiValueMap}
|
||||
* @param adaptations the adaptations that should be applied to the annotation values
|
||||
* @param finisher the finisher function for the new {@link MultiValueMap}
|
||||
* @return a {@link Collector} which collects and synthesizes the
|
||||
* annotations into a {@link LinkedMultiValueMap}
|
||||
* @see #toMultiValueMap(MergedAnnotation.Adapt...)
|
||||
@@ -134,7 +130,7 @@ public abstract class MergedAnnotationCollectors {
|
||||
IDENTITY_FINISH_CHARACTERISTICS : NO_CHARACTERISTICS);
|
||||
return Collector.of(LinkedMultiValueMap::new,
|
||||
(map, annotation) -> annotation.asMap(adaptations).forEach(map::add),
|
||||
MergedAnnotationCollectors::combiner, finisher, characteristics);
|
||||
MergedAnnotationCollectors::merge, finisher, characteristics);
|
||||
}
|
||||
|
||||
|
||||
@@ -142,22 +138,13 @@ public abstract class MergedAnnotationCollectors {
|
||||
return instance == candidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Collector#combiner() Combiner} for collections.
|
||||
* <p>This method is only invoked if the {@link java.util.stream.Stream} is
|
||||
* processed in {@linkplain java.util.stream.Stream#parallel() parallel}.
|
||||
*/
|
||||
private static <E, C extends Collection<E>> C combiner(C collection, C additions) {
|
||||
collection.addAll(additions);
|
||||
return collection;
|
||||
private static <E, L extends List<E>> L addAll(L list, L additions) {
|
||||
list.addAll(additions);
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Collector#combiner() Combiner} for multi-value maps.
|
||||
* <p>This method is only invoked if the {@link java.util.stream.Stream} is
|
||||
* processed in {@linkplain java.util.stream.Stream#parallel() parallel}.
|
||||
*/
|
||||
private static <K, V> MultiValueMap<K, V> combiner(MultiValueMap<K, V> map, MultiValueMap<K, V> additions) {
|
||||
private static <K, V> MultiValueMap<K, V> merge(MultiValueMap<K, V> map,
|
||||
MultiValueMap<K, V> additions) {
|
||||
map.addAll(additions);
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@@ -150,22 +148,4 @@ public abstract class Hints {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the hints contain a {@link #LOG_PREFIX_HINT} and the given logger has
|
||||
* DEBUG level enabled, apply the log prefix as a hint to the given buffer
|
||||
* via {@link DataBufferUtils#touch(DataBuffer, Object)}.
|
||||
* @param buffer the buffer to touch
|
||||
* @param hints the hints map to check for a log prefix
|
||||
* @param logger the logger whose level to check
|
||||
* @since 5.3.2
|
||||
*/
|
||||
public static void touchDataBuffer(DataBuffer buffer, @Nullable Map<String, Object> hints, Log logger) {
|
||||
if (logger.isDebugEnabled() && hints != null) {
|
||||
Object logPrefix = hints.get(LOG_PREFIX_HINT);
|
||||
if (logPrefix != null) {
|
||||
DataBufferUtils.touch(buffer, logPrefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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,9 +130,6 @@ public class ResourceRegionEncoder extends AbstractEncoder<ResourceRegion> {
|
||||
}
|
||||
|
||||
Flux<DataBuffer> in = DataBufferUtils.read(resource, position, bufferFactory, this.bufferSize);
|
||||
if (logger.isDebugEnabled()) {
|
||||
in = in.doOnNext(buffer -> Hints.touchDataBuffer(buffer, hints, logger));
|
||||
}
|
||||
return DataBufferUtils.takeUntilByteCount(in, count);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -118,7 +118,7 @@ public final class Property {
|
||||
}
|
||||
|
||||
|
||||
// Package private
|
||||
// package private
|
||||
|
||||
MethodParameter getMethodParameter() {
|
||||
return this.methodParameter;
|
||||
@@ -132,7 +132,7 @@ public final class Property {
|
||||
}
|
||||
|
||||
|
||||
// Internal helpers
|
||||
// internal helpers
|
||||
|
||||
private String resolveName() {
|
||||
if (this.readMethod != null) {
|
||||
@@ -142,13 +142,10 @@ public final class Property {
|
||||
}
|
||||
else {
|
||||
index = this.readMethod.getName().indexOf("is");
|
||||
if (index != -1) {
|
||||
index += 2;
|
||||
}
|
||||
else {
|
||||
// Record-style plain accessor method, e.g. name()
|
||||
index = 0;
|
||||
if (index == -1) {
|
||||
throw new IllegalArgumentException("Not a getter method");
|
||||
}
|
||||
index += 2;
|
||||
}
|
||||
return StringUtils.uncapitalize(this.readMethod.getName().substring(index));
|
||||
}
|
||||
|
||||
+8
-7
@@ -17,17 +17,17 @@
|
||||
package org.springframework.core.convert.support;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import org.springframework.core.DecoratingProxy;
|
||||
import org.springframework.core.ResolvableType;
|
||||
@@ -500,9 +500,9 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
*/
|
||||
private static class Converters {
|
||||
|
||||
private final Set<GenericConverter> globalConverters = new CopyOnWriteArraySet<>();
|
||||
private final Set<GenericConverter> globalConverters = new LinkedHashSet<>();
|
||||
|
||||
private final Map<ConvertiblePair, ConvertersForPair> converters = new ConcurrentHashMap<>(256);
|
||||
private final Map<ConvertiblePair, ConvertersForPair> converters = new LinkedHashMap<>(36);
|
||||
|
||||
public void add(GenericConverter converter) {
|
||||
Set<ConvertiblePair> convertibleTypes = converter.getConvertibleTypes();
|
||||
@@ -513,7 +513,8 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
}
|
||||
else {
|
||||
for (ConvertiblePair convertiblePair : convertibleTypes) {
|
||||
getMatchableConverters(convertiblePair).add(converter);
|
||||
ConvertersForPair convertersForPair = getMatchableConverters(convertiblePair);
|
||||
convertersForPair.add(converter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -651,7 +652,7 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
*/
|
||||
private static class ConvertersForPair {
|
||||
|
||||
private final Deque<GenericConverter> converters = new ConcurrentLinkedDeque<>();
|
||||
private final Deque<GenericConverter> converters = new ArrayDeque<>(1);
|
||||
|
||||
public void add(GenericConverter converter) {
|
||||
this.converters.addFirst(converter);
|
||||
|
||||
@@ -487,24 +487,6 @@ public abstract class DataBufferUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate the given hint with the data buffer if it is a pooled buffer
|
||||
* and supports leak tracking.
|
||||
* @param dataBuffer the data buffer to attach the hint to
|
||||
* @param hint the hint to attach
|
||||
* @return the input buffer
|
||||
* @since 5.3.2
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends DataBuffer> T touch(T dataBuffer, Object hint) {
|
||||
if (dataBuffer instanceof PooledDataBuffer) {
|
||||
return (T) ((PooledDataBuffer) dataBuffer).touch(hint);
|
||||
}
|
||||
else {
|
||||
return dataBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the given data buffer, if it is a {@link PooledDataBuffer} and
|
||||
* has been {@linkplain PooledDataBuffer#isAllocated() allocated}.
|
||||
|
||||
+6
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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,8 +54,11 @@ public class LimitedDataBufferList extends ArrayList<DataBuffer> {
|
||||
|
||||
@Override
|
||||
public boolean add(DataBuffer buffer) {
|
||||
updateCount(buffer.readableByteCount());
|
||||
return super.add(buffer);
|
||||
boolean result = super.add(buffer);
|
||||
if (result) {
|
||||
updateCount(buffer.readableByteCount());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -315,12 +315,6 @@ public class NettyDataBuffer implements PooledDataBuffer {
|
||||
return new NettyDataBuffer(this.byteBuf.retain(), this.dataBufferFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PooledDataBuffer touch(Object hint) {
|
||||
this.byteBuf.touch(hint);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean release() {
|
||||
return this.byteBuf.release();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2018 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,13 +38,6 @@ public interface PooledDataBuffer extends DataBuffer {
|
||||
*/
|
||||
PooledDataBuffer retain();
|
||||
|
||||
/**
|
||||
* Associate the given hint with the data buffer for debugging purposes.
|
||||
* @return this buffer
|
||||
* @since 5.3.2
|
||||
*/
|
||||
PooledDataBuffer touch(Object hint);
|
||||
|
||||
/**
|
||||
* Decrease the reference count for this buffer by one,
|
||||
* and deallocate it once the count reaches zero.
|
||||
|
||||
-3
@@ -432,9 +432,6 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
// Possibly "c:" drive prefix on Windows, to be upper-cased for proper duplicate detection
|
||||
filePath = StringUtils.capitalize(filePath);
|
||||
}
|
||||
// # can appear in directories/filenames, java.net.URL should not treat it as a fragment
|
||||
filePath = StringUtils.replace(filePath, "#", "%23");
|
||||
// Build URL that points to the root of the jar file
|
||||
UrlResource jarResource = new UrlResource(ResourceUtils.JAR_URL_PREFIX +
|
||||
ResourceUtils.FILE_URL_PREFIX + filePath + ResourceUtils.JAR_URL_SEPARATOR);
|
||||
// Potentially overlapping with URLClassLoader.getURLs() result above!
|
||||
|
||||
+13
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -18,11 +18,10 @@ package org.springframework.core.io.support;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -130,7 +129,7 @@ public class ResourceArrayPropertyEditor extends PropertyEditorSupport {
|
||||
public void setValue(Object value) throws IllegalArgumentException {
|
||||
if (value instanceof Collection || (value instanceof Object[] && !(value instanceof Resource[]))) {
|
||||
Collection<?> input = (value instanceof Collection ? (Collection<?>) value : Arrays.asList((Object[]) value));
|
||||
Set<Resource> merged = new LinkedHashSet<>();
|
||||
List<Resource> merged = new ArrayList<>();
|
||||
for (Object element : input) {
|
||||
if (element instanceof String) {
|
||||
// A location pattern: resolve it into a Resource array.
|
||||
@@ -138,7 +137,11 @@ public class ResourceArrayPropertyEditor extends PropertyEditorSupport {
|
||||
String pattern = resolvePath((String) element).trim();
|
||||
try {
|
||||
Resource[] resources = this.resourcePatternResolver.getResources(pattern);
|
||||
Collections.addAll(merged, resources);
|
||||
for (Resource resource : resources) {
|
||||
if (!merged.contains(resource)) {
|
||||
merged.add(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// ignore - might be an unresolved placeholder or non-existing base directory
|
||||
@@ -149,7 +152,10 @@ public class ResourceArrayPropertyEditor extends PropertyEditorSupport {
|
||||
}
|
||||
else if (element instanceof Resource) {
|
||||
// A Resource object: add it to the result.
|
||||
merged.add((Resource) element);
|
||||
Resource resource = (Resource) element;
|
||||
if (!merged.contains(resource)) {
|
||||
merged.add(resource);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Cannot convert element [" + element + "] to [" +
|
||||
|
||||
@@ -644,7 +644,7 @@ public class AntPathMatcher implements PathMatcher {
|
||||
|
||||
private static final Pattern GLOB_PATTERN = Pattern.compile("\\?|\\*|\\{((?:\\{[^/]+?}|[^/{}]|\\\\[{}])+?)}");
|
||||
|
||||
private static final String DEFAULT_VARIABLE_PATTERN = "((?s).*)";
|
||||
private static final String DEFAULT_VARIABLE_PATTERN = "(.*)";
|
||||
|
||||
private final String rawPattern;
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.BitSet;
|
||||
@@ -106,7 +104,7 @@ public class MimeType implements Comparable<MimeType>, Serializable {
|
||||
private final Map<String, String> parameters;
|
||||
|
||||
@Nullable
|
||||
private transient Charset resolvedCharset;
|
||||
private Charset resolvedCharset;
|
||||
|
||||
@Nullable
|
||||
private volatile String toStringValue;
|
||||
@@ -186,9 +184,9 @@ public class MimeType implements Comparable<MimeType>, Serializable {
|
||||
this.subtype = subtype.toLowerCase(Locale.ENGLISH);
|
||||
if (!CollectionUtils.isEmpty(parameters)) {
|
||||
Map<String, String> map = new LinkedCaseInsensitiveMap<>(parameters.size(), Locale.ENGLISH);
|
||||
parameters.forEach((parameter, value) -> {
|
||||
checkParameters(parameter, value);
|
||||
map.put(parameter, value);
|
||||
parameters.forEach((attribute, value) -> {
|
||||
checkParameters(attribute, value);
|
||||
map.put(attribute, value);
|
||||
});
|
||||
this.parameters = Collections.unmodifiableMap(map);
|
||||
}
|
||||
@@ -226,11 +224,11 @@ public class MimeType implements Comparable<MimeType>, Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkParameters(String parameter, String value) {
|
||||
Assert.hasLength(parameter, "'parameter' must not be empty");
|
||||
protected void checkParameters(String attribute, String value) {
|
||||
Assert.hasLength(attribute, "'attribute' must not be empty");
|
||||
Assert.hasLength(value, "'value' must not be empty");
|
||||
checkToken(parameter);
|
||||
if (PARAM_CHARSET.equals(parameter)) {
|
||||
checkToken(attribute);
|
||||
if (PARAM_CHARSET.equals(attribute)) {
|
||||
if (this.resolvedCharset == null) {
|
||||
this.resolvedCharset = Charset.forName(unquote(value));
|
||||
}
|
||||
@@ -593,17 +591,6 @@ public class MimeType implements Comparable<MimeType>, Serializable {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
// Rely on default serialization, just initialize state after deserialization.
|
||||
ois.defaultReadObject();
|
||||
|
||||
// Initialize transient fields.
|
||||
String charsetName = getParameter(PARAM_CHARSET);
|
||||
if (charsetName != null) {
|
||||
this.resolvedCharset = Charset.forName(unquote(charsetName));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse the given String value into a {@code MimeType} object,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -824,19 +824,6 @@ public abstract class ReflectionUtils {
|
||||
* @param method the method to check
|
||||
*/
|
||||
boolean matches(Method method);
|
||||
|
||||
/**
|
||||
* Create a composite filter based on this filter <em>and</em> the provided filter.
|
||||
* <p>If this filter does not match, the next filter will not be applied.
|
||||
* @param next the next {@code MethodFilter}
|
||||
* @return a composite {@code MethodFilter}
|
||||
* @throws IllegalArgumentException if the MethodFilter argument is {@code null}
|
||||
* @since 5.3.2
|
||||
*/
|
||||
default MethodFilter and(MethodFilter next) {
|
||||
Assert.notNull(next, "Next MethodFilter must not be null");
|
||||
return method -> matches(method) && next.matches(method);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -865,19 +852,6 @@ public abstract class ReflectionUtils {
|
||||
* @param field the field to check
|
||||
*/
|
||||
boolean matches(Field field);
|
||||
|
||||
/**
|
||||
* Create a composite filter based on this filter <em>and</em> the provided filter.
|
||||
* <p>If this filter does not match, the next filter will not be applied.
|
||||
* @param next the next {@code FieldFilter}
|
||||
* @return a composite {@code FieldFilter}
|
||||
* @throws IllegalArgumentException if the FieldFilter argument is {@code null}
|
||||
* @since 5.3.2
|
||||
*/
|
||||
default FieldFilter and(FieldFilter next) {
|
||||
Assert.notNull(next, "Next FieldFilter must not be null");
|
||||
return field -> matches(field) && next.matches(field);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -161,8 +161,9 @@ class XMLEventStreamWriter implements XMLStreamWriter {
|
||||
public void writeEndElement() throws XMLStreamException {
|
||||
closeEmptyElementIfNecessary();
|
||||
int last = this.endElements.size() - 1;
|
||||
EndElement lastEndElement = this.endElements.remove(last);
|
||||
EndElement lastEndElement = this.endElements.get(last);
|
||||
this.eventWriter.add(lastEndElement);
|
||||
this.endElements.remove(last);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+10
-32
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -17,61 +17,39 @@
|
||||
package org.springframework.core;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AttributeAccessorSupport}.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Sam Brannen
|
||||
* @since 2.0
|
||||
*/
|
||||
class AttributeAccessorSupportTests {
|
||||
|
||||
private static final String NAME = "name";
|
||||
private static final String NAME = "foo";
|
||||
|
||||
private static final String VALUE = "value";
|
||||
|
||||
private final AttributeAccessor attributeAccessor = new SimpleAttributeAccessorSupport();
|
||||
private static final String VALUE = "bar";
|
||||
|
||||
private AttributeAccessor attributeAccessor = new SimpleAttributeAccessorSupport();
|
||||
|
||||
@Test
|
||||
void setAndGet() {
|
||||
void setAndGet() throws Exception {
|
||||
this.attributeAccessor.setAttribute(NAME, VALUE);
|
||||
assertThat(this.attributeAccessor.getAttribute(NAME)).isEqualTo(VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void setAndHas() {
|
||||
void setAndHas() throws Exception {
|
||||
assertThat(this.attributeAccessor.hasAttribute(NAME)).isFalse();
|
||||
this.attributeAccessor.setAttribute(NAME, VALUE);
|
||||
assertThat(this.attributeAccessor.hasAttribute(NAME)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void computeAttribute() {
|
||||
AtomicInteger atomicInteger = new AtomicInteger();
|
||||
Function<String, String> computeFunction = name -> "computed-" + atomicInteger.incrementAndGet();
|
||||
|
||||
assertThat(this.attributeAccessor.hasAttribute(NAME)).isFalse();
|
||||
this.attributeAccessor.computeAttribute(NAME, computeFunction);
|
||||
assertThat(this.attributeAccessor.getAttribute(NAME)).isEqualTo("computed-1");
|
||||
this.attributeAccessor.computeAttribute(NAME, computeFunction);
|
||||
assertThat(this.attributeAccessor.getAttribute(NAME)).isEqualTo("computed-1");
|
||||
|
||||
this.attributeAccessor.removeAttribute(NAME);
|
||||
assertThat(this.attributeAccessor.hasAttribute(NAME)).isFalse();
|
||||
this.attributeAccessor.computeAttribute(NAME, computeFunction);
|
||||
assertThat(this.attributeAccessor.getAttribute(NAME)).isEqualTo("computed-2");
|
||||
}
|
||||
|
||||
@Test
|
||||
void remove() {
|
||||
void remove() throws Exception {
|
||||
assertThat(this.attributeAccessor.hasAttribute(NAME)).isFalse();
|
||||
this.attributeAccessor.setAttribute(NAME, VALUE);
|
||||
assertThat(this.attributeAccessor.removeAttribute(NAME)).isEqualTo(VALUE);
|
||||
@@ -79,13 +57,13 @@ class AttributeAccessorSupportTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void attributeNames() {
|
||||
void attributeNames() throws Exception {
|
||||
this.attributeAccessor.setAttribute(NAME, VALUE);
|
||||
this.attributeAccessor.setAttribute("abc", "123");
|
||||
String[] attributeNames = this.attributeAccessor.attributeNames();
|
||||
Arrays.sort(attributeNames);
|
||||
assertThat(Arrays.binarySearch(attributeNames, "abc")).isEqualTo(0);
|
||||
assertThat(Arrays.binarySearch(attributeNames, NAME)).isEqualTo(1);
|
||||
assertThat(Arrays.binarySearch(attributeNames, NAME) > -1).isTrue();
|
||||
assertThat(Arrays.binarySearch(attributeNames, "abc") > -1).isTrue();
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
|
||||
+1
-2
@@ -367,9 +367,8 @@ class ReactiveAdapterRegistryTests {
|
||||
private static class ExtendedFlux<T> extends Flux<T> {
|
||||
|
||||
@Override
|
||||
public void subscribe(CoreSubscriber<? super T> actual) {
|
||||
public void subscribe(CoreSubscriber actual) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-18
@@ -35,8 +35,6 @@ import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.reactivestreams.Subscription;
|
||||
import reactor.core.publisher.BaseSubscriber;
|
||||
@@ -836,22 +834,6 @@ class DataBufferUtilsTests extends AbstractDataBufferAllocatingTests {
|
||||
.verifyError(DataBufferLimitException.class);
|
||||
}
|
||||
|
||||
@Test // gh-26060
|
||||
void joinWithLimitDoesNotOverRelease() {
|
||||
NettyDataBufferFactory bufferFactory = new NettyDataBufferFactory(PooledByteBufAllocator.DEFAULT);
|
||||
byte[] bytes = "foo-bar-baz".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
NettyDataBuffer buffer = bufferFactory.allocateBuffer(bytes.length);
|
||||
buffer.getNativeBuffer().retain(); // should be at 2 now
|
||||
buffer.write(bytes);
|
||||
|
||||
Mono<DataBuffer> result = DataBufferUtils.join(Flux.just(buffer), 8);
|
||||
|
||||
StepVerifier.create(result).verifyError(DataBufferLimitException.class);
|
||||
assertThat(buffer.getNativeBuffer().refCnt()).isEqualTo(1);
|
||||
buffer.release();
|
||||
}
|
||||
|
||||
@ParameterizedDataBufferAllocatingTest
|
||||
void joinErrors(String displayName, DataBufferFactory bufferFactory) {
|
||||
super.bufferFactory = bufferFactory;
|
||||
|
||||
+3
-7
@@ -17,11 +17,9 @@ package org.springframework.core.io.buffer;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link LimitedDataBufferList}.
|
||||
* @author Rossen Stoyanchev
|
||||
@@ -31,10 +29,8 @@ public class LimitedDataBufferListTests {
|
||||
|
||||
@Test
|
||||
void limitEnforced() {
|
||||
LimitedDataBufferList list = new LimitedDataBufferList(5);
|
||||
|
||||
assertThatThrownBy(() -> list.add(toDataBuffer("123456"))).isInstanceOf(DataBufferLimitException.class);
|
||||
assertThat(list).isEmpty();
|
||||
Assertions.assertThatThrownBy(() -> new LimitedDataBufferList(5).add(toDataBuffer("123456")))
|
||||
.isInstanceOf(DataBufferLimitException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -130,7 +130,6 @@ class AntPathMatcherTests {
|
||||
assertThat(pathMatcher.match("", "")).isTrue();
|
||||
|
||||
assertThat(pathMatcher.match("/{bla}.*", "/testing.html")).isTrue();
|
||||
assertThat(pathMatcher.match("/{bla}", "//x\ny")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.testfixture.io.SerializationTestUtils;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -268,13 +267,13 @@ class MimeTypeTests {
|
||||
assertThat(mimeType.getParameter("attr")).isEqualTo("'v>alue'");
|
||||
}
|
||||
|
||||
@Test // SPR-16630
|
||||
@Test // SPR-16630
|
||||
void parseMimeTypeWithSpacesAroundEquals() {
|
||||
MimeType mimeType = MimeTypeUtils.parseMimeType("multipart/x-mixed-replace;boundary = --myboundary");
|
||||
assertThat(mimeType.getParameter("boundary")).isEqualTo("--myboundary");
|
||||
}
|
||||
|
||||
@Test // SPR-16630
|
||||
@Test // SPR-16630
|
||||
void parseMimeTypeWithSpacesAroundEqualsAndQuotedValue() {
|
||||
MimeType mimeType = MimeTypeUtils.parseMimeType("text/plain; foo = \" bar \" ");
|
||||
assertThat(mimeType.getParameter("foo")).isEqualTo("\" bar \"");
|
||||
@@ -304,14 +303,14 @@ class MimeTypeTests {
|
||||
assertThat(mimeTypes.size()).as("Invalid amount of mime types").isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test // gh-23241
|
||||
@Test // gh-23241
|
||||
void parseMimeTypesWithTrailingComma() {
|
||||
List<MimeType> mimeTypes = MimeTypeUtils.parseMimeTypes("text/plain, text/html,");
|
||||
assertThat(mimeTypes).as("No mime types returned").isNotNull();
|
||||
assertThat(mimeTypes.size()).as("Incorrect number of mime types").isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test // SPR-17459
|
||||
@Test // SPR-17459
|
||||
void parseMimeTypesWithQuotedParameters() {
|
||||
testWithQuotedParameters("foo/bar;param=\",\"");
|
||||
testWithQuotedParameters("foo/bar;param=\"s,a,\"");
|
||||
@@ -333,7 +332,7 @@ class MimeTypeTests {
|
||||
assertThat(type.getSubtypeSuffix()).isEqualTo("json");
|
||||
}
|
||||
|
||||
@Test // gh-25350
|
||||
@Test // gh-25350
|
||||
void wildcardSubtypeCompatibleWithSuffix() {
|
||||
MimeType applicationStar = new MimeType("application", "*");
|
||||
MimeType applicationVndJson = new MimeType("application", "vnd.something+json");
|
||||
@@ -343,9 +342,8 @@ class MimeTypeTests {
|
||||
private void testWithQuotedParameters(String... mimeTypes) {
|
||||
String s = String.join(",", mimeTypes);
|
||||
List<MimeType> actual = MimeTypeUtils.parseMimeTypes(s);
|
||||
|
||||
assertThat(actual.size()).isEqualTo(mimeTypes.length);
|
||||
for (int i = 0; i < mimeTypes.length; i++) {
|
||||
for (int i=0; i < mimeTypes.length; i++) {
|
||||
assertThat(actual.get(i).toString()).isEqualTo(mimeTypes[i]);
|
||||
}
|
||||
}
|
||||
@@ -372,7 +370,6 @@ class MimeTypeTests {
|
||||
|
||||
List<MimeType> result = new ArrayList<>(expected);
|
||||
Random rnd = new Random();
|
||||
|
||||
// shuffle & sort 10 times
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Collections.shuffle(result, rnd);
|
||||
@@ -402,7 +399,11 @@ class MimeTypeTests {
|
||||
assertThat(m2.compareTo(m1) != 0).as("Invalid comparison result").isTrue();
|
||||
}
|
||||
|
||||
@Test // SPR-13157
|
||||
/**
|
||||
* SPR-13157
|
||||
* @since 4.2
|
||||
*/
|
||||
@Test
|
||||
void equalsIsCaseInsensitiveForCharsets() {
|
||||
MimeType m1 = new MimeType("text", "plain", singletonMap("charset", "UTF-8"));
|
||||
MimeType m2 = new MimeType("text", "plain", singletonMap("charset", "utf-8"));
|
||||
@@ -412,12 +413,4 @@ class MimeTypeTests {
|
||||
assertThat(m2.compareTo(m1)).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test // gh-26127
|
||||
void serialize() throws Exception {
|
||||
MimeType original = new MimeType("text", "plain", StandardCharsets.UTF_8);
|
||||
MimeType deserialized = SerializationTestUtils.serializeAndDeserialize(original);
|
||||
assertThat(deserialized).isEqualTo(original);
|
||||
assertThat(original).isEqualTo(deserialized);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -186,7 +186,12 @@ class ReflectionUtilsTests {
|
||||
@Test
|
||||
void doWithProtectedMethods() {
|
||||
ListSavingMethodCallback mc = new ListSavingMethodCallback();
|
||||
ReflectionUtils.doWithMethods(TestObject.class, mc, method -> Modifier.isProtected(method.getModifiers()));
|
||||
ReflectionUtils.doWithMethods(TestObject.class, mc, new ReflectionUtils.MethodFilter() {
|
||||
@Override
|
||||
public boolean matches(Method m) {
|
||||
return Modifier.isProtected(m.getModifiers());
|
||||
}
|
||||
});
|
||||
assertThat(mc.getMethodNames().isEmpty()).isFalse();
|
||||
assertThat(mc.getMethodNames().contains("clone")).as("Must find protected method on Object").isTrue();
|
||||
assertThat(mc.getMethodNames().contains("finalize")).as("Must find protected method on Object").isTrue();
|
||||
|
||||
+9
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.core.testfixture.io.buffer;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.DataBufferWrapper;
|
||||
import org.springframework.core.io.buffer.PooledDataBuffer;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -68,19 +67,19 @@ class LeakAwareDataBuffer extends DataBufferWrapper implements PooledDataBuffer
|
||||
|
||||
@Override
|
||||
public PooledDataBuffer retain() {
|
||||
DataBufferUtils.retain(dataBuffer());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PooledDataBuffer touch(Object hint) {
|
||||
DataBufferUtils.touch(dataBuffer(), hint);
|
||||
DataBuffer delegate = dataBuffer();
|
||||
if (delegate instanceof PooledDataBuffer) {
|
||||
((PooledDataBuffer) delegate).retain();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean release() {
|
||||
DataBufferUtils.release(dataBuffer());
|
||||
DataBuffer delegate = dataBuffer();
|
||||
if (delegate instanceof PooledDataBuffer) {
|
||||
((PooledDataBuffer) delegate).release();
|
||||
}
|
||||
return isAllocated();
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2018 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,10 @@ public abstract class AstUtils {
|
||||
}
|
||||
else {
|
||||
if (targetType != null) {
|
||||
int pos = 0;
|
||||
for (Class<?> clazz : targets) {
|
||||
if (clazz == targetType) { // put exact matches on the front to be tried first?
|
||||
specificAccessors.add(resolver);
|
||||
specificAccessors.add(pos++, resolver);
|
||||
}
|
||||
else if (clazz.isAssignableFrom(targetType)) { // put supertype matches at the end of the
|
||||
// specificAccessor list
|
||||
|
||||
+31
-56
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -63,36 +63,34 @@ import org.springframework.util.StringUtils;
|
||||
* <p>Individual expressions can be compiled by calling {@code SpelCompiler.compile(expression)}.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
*/
|
||||
public final class SpelCompiler implements Opcodes {
|
||||
|
||||
private static final int CLASSES_DEFINED_LIMIT = 100;
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SpelCompiler.class);
|
||||
|
||||
private static final int CLASSES_DEFINED_LIMIT = 100;
|
||||
|
||||
// A compiler is created for each classloader, it manages a child class loader of that
|
||||
// classloader and the child is used to load the compiled expressions.
|
||||
private static final Map<ClassLoader, SpelCompiler> compilers = new ConcurrentReferenceHashMap<>();
|
||||
|
||||
|
||||
// The child ClassLoader used to load the compiled expression classes
|
||||
private volatile ChildClassLoader childClassLoader;
|
||||
private ChildClassLoader ccl;
|
||||
|
||||
// Counter suffix for generated classes within this SpelCompiler instance
|
||||
private final AtomicInteger suffixId = new AtomicInteger(1);
|
||||
|
||||
|
||||
private SpelCompiler(@Nullable ClassLoader classloader) {
|
||||
this.childClassLoader = new ChildClassLoader(classloader);
|
||||
this.ccl = new ChildClassLoader(classloader);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attempt compilation of the supplied expression. A check is made to see
|
||||
* if it is compilable before compilation proceeds. The check involves
|
||||
* visiting all the nodes in the expression AST and ensuring enough state
|
||||
* visiting all the nodes in the expression Ast and ensuring enough state
|
||||
* is known about them that bytecode can be generated for them.
|
||||
* @param expression the expression to compile
|
||||
* @return an instance of the class implementing the compiled expression,
|
||||
@@ -127,7 +125,7 @@ public final class SpelCompiler implements Opcodes {
|
||||
|
||||
/**
|
||||
* Generate the class that encapsulates the compiled expression and define it.
|
||||
* The generated class will be a subtype of CompiledExpression.
|
||||
* The generated class will be a subtype of CompiledExpression.
|
||||
* @param expressionToCompile the expression to be compiled
|
||||
* @return the expression call, or {@code null} if the decision was to opt out of
|
||||
* compilation during code generation
|
||||
@@ -137,7 +135,7 @@ public final class SpelCompiler implements Opcodes {
|
||||
// Create class outline 'spel/ExNNN extends org.springframework.expression.spel.CompiledExpression'
|
||||
String className = "spel/Ex" + getNextSuffix();
|
||||
ClassWriter cw = new ExpressionClassWriter();
|
||||
cw.visit(V1_8, ACC_PUBLIC, className, null, "org/springframework/expression/spel/CompiledExpression", null);
|
||||
cw.visit(V1_5, ACC_PUBLIC, className, null, "org/springframework/expression/spel/CompiledExpression", null);
|
||||
|
||||
// Create default constructor
|
||||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
|
||||
@@ -152,7 +150,7 @@ public final class SpelCompiler implements Opcodes {
|
||||
// Create getValue() method
|
||||
mv = cw.visitMethod(ACC_PUBLIC, "getValue",
|
||||
"(Ljava/lang/Object;Lorg/springframework/expression/EvaluationContext;)Ljava/lang/Object;", null,
|
||||
new String[] {"org/springframework/expression/EvaluationException"});
|
||||
new String[ ]{"org/springframework/expression/EvaluationException"});
|
||||
mv.visitCode();
|
||||
|
||||
CodeFlow cf = new CodeFlow(className, cw);
|
||||
@@ -189,7 +187,7 @@ public final class SpelCompiler implements Opcodes {
|
||||
|
||||
/**
|
||||
* Load a compiled expression class. Makes sure the classloaders aren't used too much
|
||||
* because they anchor compiled classes in memory and prevent GC. If you have expressions
|
||||
* because they anchor compiled classes in memory and prevent GC. If you have expressions
|
||||
* continually recompiling over time then by replacing the classloader periodically
|
||||
* at least some of the older variants can be garbage collected.
|
||||
* @param name the name of the class
|
||||
@@ -198,25 +196,12 @@ public final class SpelCompiler implements Opcodes {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<? extends CompiledExpression> loadClass(String name, byte[] bytes) {
|
||||
ChildClassLoader ccl = this.childClassLoader;
|
||||
if (ccl.getClassesDefinedCount() >= CLASSES_DEFINED_LIMIT) {
|
||||
synchronized (this) {
|
||||
ChildClassLoader currentCcl = this.childClassLoader;
|
||||
if (ccl == currentCcl) {
|
||||
// Still the same ClassLoader that needs to be replaced...
|
||||
ccl = new ChildClassLoader(ccl.getParent());
|
||||
this.childClassLoader = ccl;
|
||||
}
|
||||
else {
|
||||
// Already replaced by some other thread, let's pick it up.
|
||||
ccl = currentCcl;
|
||||
}
|
||||
}
|
||||
if (this.ccl.getClassesDefinedCount() > CLASSES_DEFINED_LIMIT) {
|
||||
this.ccl = new ChildClassLoader(this.ccl.getParent());
|
||||
}
|
||||
return (Class<? extends CompiledExpression>) ccl.defineClass(name, bytes);
|
||||
return (Class<? extends CompiledExpression>) this.ccl.defineClass(name, bytes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Factory method for compiler instances. The returned SpelCompiler will
|
||||
* attach a class loader as the child of the given class loader and this
|
||||
@@ -226,28 +211,21 @@ public final class SpelCompiler implements Opcodes {
|
||||
*/
|
||||
public static SpelCompiler getCompiler(@Nullable ClassLoader classLoader) {
|
||||
ClassLoader clToUse = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
|
||||
// Quick check for existing compiler without lock contention
|
||||
SpelCompiler compiler = compilers.get(clToUse);
|
||||
if (compiler == null) {
|
||||
// Full lock now since we're creating a child ClassLoader
|
||||
synchronized (compilers) {
|
||||
compiler = compilers.get(clToUse);
|
||||
if (compiler == null) {
|
||||
compiler = new SpelCompiler(clToUse);
|
||||
compilers.put(clToUse, compiler);
|
||||
}
|
||||
synchronized (compilers) {
|
||||
SpelCompiler compiler = compilers.get(clToUse);
|
||||
if (compiler == null) {
|
||||
compiler = new SpelCompiler(clToUse);
|
||||
compilers.put(clToUse, compiler);
|
||||
}
|
||||
return compiler;
|
||||
}
|
||||
return compiler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request that an attempt is made to compile the specified expression.
|
||||
* It may fail if components of the expression are not suitable for compilation
|
||||
* or the data types involved are not suitable for compilation. Used for testing.
|
||||
* @param expression the expression to compile
|
||||
* @return {@code true} if the expression was successfully compiled,
|
||||
* {@code false} otherwise
|
||||
* Request that an attempt is made to compile the specified expression. It may fail if
|
||||
* components of the expression are not suitable for compilation or the data types
|
||||
* involved are not suitable for compilation. Used for testing.
|
||||
* @return true if the expression was successfully compiled
|
||||
*/
|
||||
public static boolean compile(Expression expression) {
|
||||
return (expression instanceof SpelExpression && ((SpelExpression) expression).compileExpression());
|
||||
@@ -272,27 +250,24 @@ public final class SpelCompiler implements Opcodes {
|
||||
|
||||
private static final URL[] NO_URLS = new URL[0];
|
||||
|
||||
private final AtomicInteger classesDefinedCount = new AtomicInteger(0);
|
||||
private int classesDefinedCount = 0;
|
||||
|
||||
public ChildClassLoader(@Nullable ClassLoader classLoader) {
|
||||
super(NO_URLS, classLoader);
|
||||
}
|
||||
|
||||
public Class<?> defineClass(String name, byte[] bytes) {
|
||||
Class<?> clazz = super.defineClass(name, bytes, 0, bytes.length);
|
||||
this.classesDefinedCount.incrementAndGet();
|
||||
return clazz;
|
||||
int getClassesDefinedCount() {
|
||||
return this.classesDefinedCount;
|
||||
}
|
||||
|
||||
public int getClassesDefinedCount() {
|
||||
return this.classesDefinedCount.get();
|
||||
public Class<?> defineClass(String name, byte[] bytes) {
|
||||
Class<?> clazz = super.defineClass(name, bytes, 0, bytes.length);
|
||||
this.classesDefinedCount++;
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An ASM ClassWriter extension bound to the SpelCompiler's ClassLoader.
|
||||
*/
|
||||
private class ExpressionClassWriter extends ClassWriter {
|
||||
|
||||
public ExpressionClassWriter() {
|
||||
@@ -301,7 +276,7 @@ public final class SpelCompiler implements Opcodes {
|
||||
|
||||
@Override
|
||||
protected ClassLoader getClassLoader() {
|
||||
return childClassLoader;
|
||||
return ccl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-14
@@ -47,7 +47,7 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A powerful {@link PropertyAccessor} that uses reflection to access properties
|
||||
* for reading and possibly also for writing on a target instance.
|
||||
* for reading and possibly also for writing.
|
||||
*
|
||||
* <p>A property can be referenced through a public getter method (when being read)
|
||||
* or a public setter method (when being written), and also as a public field.
|
||||
@@ -98,8 +98,8 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new property accessor for reading and possibly also writing.
|
||||
* @param allowWrite whether to allow write operations on a target instance
|
||||
* Create a new property accessor for reading and possibly writing.
|
||||
* @param allowWrite whether to also allow for write operations
|
||||
* @since 4.3.15
|
||||
* @see #canWrite
|
||||
*/
|
||||
@@ -395,11 +395,6 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
if (method == null) {
|
||||
method = findMethodForProperty(getPropertyMethodSuffixes(propertyName),
|
||||
"is", clazz, mustBeStatic, 0, BOOLEAN_TYPES);
|
||||
if (method == null) {
|
||||
// Record-style plain accessor method, e.g. name()
|
||||
method = findMethodForProperty(new String[] {propertyName},
|
||||
"", clazz, mustBeStatic, 0, ANY_TYPES);
|
||||
}
|
||||
}
|
||||
return method;
|
||||
}
|
||||
@@ -628,8 +623,8 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PropertyCacheKey [clazz=" + this.clazz.getName() + ", property=" + this.property +
|
||||
", targetIsClass=" + this.targetIsClass + "]";
|
||||
return "CacheKey [clazz=" + this.clazz.getName() + ", property=" + this.property + ", " +
|
||||
this.property + ", targetIsClass=" + this.targetIsClass + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -688,11 +683,12 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
return true;
|
||||
}
|
||||
getterName = "is" + StringUtils.capitalize(name);
|
||||
if (getterName.equals(method.getName())) {
|
||||
return true;
|
||||
}
|
||||
return getterName.equals(method.getName());
|
||||
}
|
||||
else {
|
||||
Field field = (Field) this.member;
|
||||
return field.getName().equals(name);
|
||||
}
|
||||
return this.member.getName().equals(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -36,7 +36,6 @@ import org.springframework.expression.spel.support.SimpleEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.testresources.Inventor;
|
||||
import org.springframework.expression.spel.testresources.Person;
|
||||
import org.springframework.expression.spel.testresources.RecordPerson;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
@@ -192,20 +191,6 @@ public class PropertyAccessTests extends AbstractExpressionTests {
|
||||
parser.parseExpression("name='p3'").getValue(context, target));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyReadOnlyWithRecordStyle() {
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||
|
||||
Expression expr = parser.parseExpression("name");
|
||||
RecordPerson target1 = new RecordPerson("p1");
|
||||
assertThat(expr.getValue(context, target1)).isEqualTo("p1");
|
||||
RecordPerson target2 = new RecordPerson("p2");
|
||||
assertThat(expr.getValue(context, target2)).isEqualTo("p2");
|
||||
|
||||
assertThatExceptionOfType(SpelEvaluationException.class).isThrownBy(() ->
|
||||
parser.parseExpression("name='p3'").getValue(context, target2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyReadWrite() {
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
|
||||
|
||||
+25
-19
@@ -4180,13 +4180,6 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
||||
assertThat(expression.getValue(tc)).isEqualTo("value4");
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(tc)).isEqualTo("value4");
|
||||
|
||||
// record-style accessor
|
||||
expression = parser.parseExpression("strawberry");
|
||||
assertCantCompile(expression);
|
||||
assertThat(expression.getValue(tc)).isEqualTo("value5");
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(tc)).isEqualTo("value5");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -4560,9 +4553,23 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
||||
Object v = expression.getValue(ctx,holder);
|
||||
assertThat(v).isEqualTo("abc");
|
||||
|
||||
// // time it interpreted
|
||||
// long stime = System.currentTimeMillis();
|
||||
// for (int i = 0; i < 100000; i++) {
|
||||
// v = expression.getValue(ctx,holder);
|
||||
// }
|
||||
// System.out.println((System.currentTimeMillis() - stime));
|
||||
|
||||
assertCanCompile(expression);
|
||||
v = expression.getValue(ctx,holder);
|
||||
assertThat(v).isEqualTo("abc");
|
||||
|
||||
// // time it compiled
|
||||
// stime = System.currentTimeMillis();
|
||||
// for (int i = 0; i < 100000; i++) {
|
||||
// v = expression.getValue(ctx,holder);
|
||||
// }
|
||||
// System.out.println((System.currentTimeMillis() - stime));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -4978,12 +4985,13 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
||||
assertThat(fast.compileExpression()).isTrue();
|
||||
r.setValue2(null);
|
||||
// try the numbers 0,1,2,null
|
||||
for (int i = 0; i < 4; i++) {
|
||||
r.setValue(i < 3 ? i : null);
|
||||
for (int i=0;i<4;i++) {
|
||||
r.setValue(i<3?i:null);
|
||||
boolean slowResult = (Boolean)slow.getValue(ctx);
|
||||
boolean fastResult = (Boolean)fast.getValue(ctx);
|
||||
assertThat(fastResult).as("Differing results: expression=" + expressionText +
|
||||
" value=" + r.getValue() + " slow=" + slowResult + " fast="+fastResult).isEqualTo(slowResult);
|
||||
// System.out.println("Trying "+expressionText+" with value="+r.getValue()+" result is "+slowResult);
|
||||
assertThat(fastResult).as(" Differing results: expression="+expressionText+
|
||||
" value="+r.getValue()+" slow="+slowResult+" fast="+fastResult).isEqualTo(slowResult);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4994,12 +5002,13 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
||||
assertThat(fast.compileExpression()).isTrue();
|
||||
Reg r = (Reg)ctx.getRootObject().getValue();
|
||||
// try the numbers 0,1,2,null
|
||||
for (int i = 0; i < 4; i++) {
|
||||
r.setValue(i < 3 ? i : null);
|
||||
for (int i=0;i<4;i++) {
|
||||
r.setValue(i<3?i:null);
|
||||
boolean slowResult = (Boolean)slow.getValue(ctx);
|
||||
boolean fastResult = (Boolean)fast.getValue(ctx);
|
||||
assertThat(fastResult).as("Differing results: expression=" + expressionText +
|
||||
" value=" + r.getValue() + " slow=" + slowResult + " fast="+fastResult).isEqualTo(slowResult);
|
||||
// System.out.println("Trying "+expressionText+" with value="+r.getValue()+" result is "+slowResult);
|
||||
assertThat(fastResult).as(" Differing results: expression="+expressionText+
|
||||
" value="+r.getValue()+" slow="+slowResult+" fast="+fastResult).isEqualTo(slowResult);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5830,6 +5839,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
||||
|
||||
public String orange = "value1";
|
||||
public static String apple = "value2";
|
||||
|
||||
public long peach = 34L;
|
||||
|
||||
public String getBanana() {
|
||||
@@ -5839,10 +5849,6 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
||||
public static String getPlum() {
|
||||
return "value4";
|
||||
}
|
||||
|
||||
public String strawberry() {
|
||||
return "value5";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
@@ -76,6 +76,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
*/
|
||||
public class SpelReproTests extends AbstractExpressionTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void NPE_SPR5661() {
|
||||
evaluate("joinThreeStrings('a',null,'c')", "anullc", String.class);
|
||||
|
||||
+36
-34
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -36,10 +36,10 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
* @author Andy Clement
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
class SpelParserTests {
|
||||
public class SpelParserTests {
|
||||
|
||||
@Test
|
||||
void theMostBasic() {
|
||||
public void theMostBasic() {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
SpelExpression expr = parser.parseRaw("2");
|
||||
assertThat(expr).isNotNull();
|
||||
@@ -50,7 +50,7 @@ class SpelParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void valueType() {
|
||||
public void valueType() {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
EvaluationContext ctx = new StandardEvaluationContext();
|
||||
Class<?> c = parser.parseRaw("2").getValueType();
|
||||
@@ -66,7 +66,7 @@ class SpelParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void whitespace() {
|
||||
public void whitespace() {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
SpelExpression expr = parser.parseRaw("2 + 3");
|
||||
assertThat(expr.getValue()).isEqualTo(5);
|
||||
@@ -79,7 +79,7 @@ class SpelParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void arithmeticPlus1() {
|
||||
public void arithmeticPlus1() {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
SpelExpression expr = parser.parseRaw("2+2");
|
||||
assertThat(expr).isNotNull();
|
||||
@@ -88,65 +88,66 @@ class SpelParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void arithmeticPlus2() {
|
||||
public void arithmeticPlus2() {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
SpelExpression expr = parser.parseRaw("37+41");
|
||||
assertThat(expr.getValue()).isEqualTo(78);
|
||||
}
|
||||
|
||||
@Test
|
||||
void arithmeticMultiply1() {
|
||||
public void arithmeticMultiply1() {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
SpelExpression expr = parser.parseRaw("2*3");
|
||||
assertThat(expr).isNotNull();
|
||||
assertThat(expr.getAST()).isNotNull();
|
||||
// printAst(expr.getAST(),0);
|
||||
assertThat(expr.getValue()).isEqualTo(6);
|
||||
}
|
||||
|
||||
@Test
|
||||
void arithmeticPrecedence1() {
|
||||
public void arithmeticPrecedence1() {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
SpelExpression expr = parser.parseRaw("2*3+5");
|
||||
assertThat(expr.getValue()).isEqualTo(11);
|
||||
}
|
||||
|
||||
@Test
|
||||
void generalExpressions() {
|
||||
public void generalExpressions() {
|
||||
assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
parser.parseRaw("new String");
|
||||
})
|
||||
.satisfies(parseExceptionRequirements(SpelMessage.MISSING_CONSTRUCTOR_ARGS, 10));
|
||||
.satisfies(ex -> parseExceptionRequirements(SpelMessage.MISSING_CONSTRUCTOR_ARGS, 10));
|
||||
|
||||
assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
parser.parseRaw("new String(3,");
|
||||
})
|
||||
.satisfies(parseExceptionRequirements(SpelMessage.RUN_OUT_OF_ARGUMENTS, 10));
|
||||
.satisfies(ex -> parseExceptionRequirements(SpelMessage.RUN_OUT_OF_ARGUMENTS, 10));
|
||||
|
||||
assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
parser.parseRaw("new String(3");
|
||||
})
|
||||
.satisfies(parseExceptionRequirements(SpelMessage.RUN_OUT_OF_ARGUMENTS, 10));
|
||||
.satisfies(ex -> parseExceptionRequirements(SpelMessage.RUN_OUT_OF_ARGUMENTS, 10));
|
||||
|
||||
assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
parser.parseRaw("new String(");
|
||||
})
|
||||
.satisfies(parseExceptionRequirements(SpelMessage.RUN_OUT_OF_ARGUMENTS, 10));
|
||||
.satisfies(ex -> parseExceptionRequirements(SpelMessage.RUN_OUT_OF_ARGUMENTS, 10));
|
||||
|
||||
assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
parser.parseRaw("\"abc");
|
||||
})
|
||||
.satisfies(parseExceptionRequirements(SpelMessage.NON_TERMINATING_DOUBLE_QUOTED_STRING, 0));
|
||||
.satisfies(ex -> parseExceptionRequirements(SpelMessage.NON_TERMINATING_DOUBLE_QUOTED_STRING, 0));
|
||||
|
||||
assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
parser.parseRaw("'abc");
|
||||
})
|
||||
.satisfies(parseExceptionRequirements(SpelMessage.NON_TERMINATING_QUOTED_STRING, 0));
|
||||
.satisfies(ex -> parseExceptionRequirements(SpelMessage.NON_TERMINATING_QUOTED_STRING, 0));
|
||||
|
||||
}
|
||||
|
||||
@@ -160,38 +161,38 @@ class SpelParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void arithmeticPrecedence2() {
|
||||
public void arithmeticPrecedence2() {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
SpelExpression expr = parser.parseRaw("2+3*5");
|
||||
assertThat(expr.getValue()).isEqualTo(17);
|
||||
}
|
||||
|
||||
@Test
|
||||
void arithmeticPrecedence3() {
|
||||
public void arithmeticPrecedence3() {
|
||||
SpelExpression expr = new SpelExpressionParser().parseRaw("3+10/2");
|
||||
assertThat(expr.getValue()).isEqualTo(8);
|
||||
}
|
||||
|
||||
@Test
|
||||
void arithmeticPrecedence4() {
|
||||
public void arithmeticPrecedence4() {
|
||||
SpelExpression expr = new SpelExpressionParser().parseRaw("10/2+3");
|
||||
assertThat(expr.getValue()).isEqualTo(8);
|
||||
}
|
||||
|
||||
@Test
|
||||
void arithmeticPrecedence5() {
|
||||
public void arithmeticPrecedence5() {
|
||||
SpelExpression expr = new SpelExpressionParser().parseRaw("(4+10)/2");
|
||||
assertThat(expr.getValue()).isEqualTo(7);
|
||||
}
|
||||
|
||||
@Test
|
||||
void arithmeticPrecedence6() {
|
||||
public void arithmeticPrecedence6() {
|
||||
SpelExpression expr = new SpelExpressionParser().parseRaw("(3+2)*2");
|
||||
assertThat(expr.getValue()).isEqualTo(10);
|
||||
}
|
||||
|
||||
@Test
|
||||
void booleanOperators() {
|
||||
public void booleanOperators() {
|
||||
SpelExpression expr = new SpelExpressionParser().parseRaw("true");
|
||||
assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.TRUE);
|
||||
expr = new SpelExpressionParser().parseRaw("false");
|
||||
@@ -209,7 +210,7 @@ class SpelParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void booleanOperators_symbolic_spr9614() {
|
||||
public void booleanOperators_symbolic_spr9614() {
|
||||
SpelExpression expr = new SpelExpressionParser().parseRaw("true");
|
||||
assertThat(expr.getValue(Boolean.class)).isEqualTo(Boolean.TRUE);
|
||||
expr = new SpelExpressionParser().parseRaw("false");
|
||||
@@ -227,7 +228,7 @@ class SpelParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void stringLiterals() {
|
||||
public void stringLiterals() {
|
||||
SpelExpression expr = new SpelExpressionParser().parseRaw("'howdy'");
|
||||
assertThat(expr.getValue()).isEqualTo("howdy");
|
||||
expr = new SpelExpressionParser().parseRaw("'hello '' world'");
|
||||
@@ -235,13 +236,13 @@ class SpelParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void stringLiterals2() {
|
||||
public void stringLiterals2() {
|
||||
SpelExpression expr = new SpelExpressionParser().parseRaw("'howdy'.substring(0,2)");
|
||||
assertThat(expr.getValue()).isEqualTo("ho");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStringLiterals_DoubleQuotes_spr9620() {
|
||||
public void testStringLiterals_DoubleQuotes_spr9620() {
|
||||
SpelExpression expr = new SpelExpressionParser().parseRaw("\"double quote: \"\".\"");
|
||||
assertThat(expr.getValue()).isEqualTo("double quote: \".");
|
||||
expr = new SpelExpressionParser().parseRaw("\"hello \"\" world\"");
|
||||
@@ -249,7 +250,7 @@ class SpelParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStringLiterals_DoubleQuotes_spr9620_2() {
|
||||
public void testStringLiterals_DoubleQuotes_spr9620_2() {
|
||||
assertThatExceptionOfType(SpelParseException.class).isThrownBy(() ->
|
||||
new SpelExpressionParser().parseRaw("\"double quote: \\\"\\\".\""))
|
||||
.satisfies(ex -> {
|
||||
@@ -259,7 +260,7 @@ class SpelParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void positionalInformation() {
|
||||
public void positionalInformation() {
|
||||
SpelExpression expr = new SpelExpressionParser().parseRaw("true and true or false");
|
||||
SpelNode rootAst = expr.getAST();
|
||||
OpOr operatorOr = (OpOr) rootAst;
|
||||
@@ -288,7 +289,7 @@ class SpelParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void tokenKind() {
|
||||
public void tokenKind() {
|
||||
TokenKind tk = TokenKind.NOT;
|
||||
assertThat(tk.hasPayload()).isFalse();
|
||||
assertThat(tk.toString()).isEqualTo("NOT(!)");
|
||||
@@ -303,7 +304,7 @@ class SpelParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void token() {
|
||||
public void token() {
|
||||
Token token = new Token(TokenKind.NOT, 0, 3);
|
||||
assertThat(token.kind).isEqualTo(TokenKind.NOT);
|
||||
assertThat(token.startPos).isEqualTo(0);
|
||||
@@ -318,7 +319,7 @@ class SpelParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void exceptions() {
|
||||
public void exceptions() {
|
||||
ExpressionException exprEx = new ExpressionException("test");
|
||||
assertThat(exprEx.getSimpleMessage()).isEqualTo("test");
|
||||
assertThat(exprEx.toDetailedString()).isEqualTo("test");
|
||||
@@ -336,13 +337,13 @@ class SpelParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseMethodsOnNumbers() {
|
||||
public void parseMethodsOnNumbers() {
|
||||
checkNumber("3.14.toString()", "3.14", String.class);
|
||||
checkNumber("3.toString()", "3", String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void numerics() {
|
||||
public void numerics() {
|
||||
checkNumber("2", 2, Integer.class);
|
||||
checkNumber("22", 22, Integer.class);
|
||||
checkNumber("+22", 22, Integer.class);
|
||||
@@ -384,7 +385,8 @@ class SpelParserTests {
|
||||
|
||||
private void checkNumberError(String expression, SpelMessage expectedMessage) {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> parser.parseRaw(expression))
|
||||
assertThatExceptionOfType(SpelParseException.class).isThrownBy(() ->
|
||||
parser.parseRaw(expression))
|
||||
.satisfies(ex -> assertThat(ex.getMessageCode()).isEqualTo(expectedMessage));
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,10 +16,9 @@
|
||||
|
||||
package org.springframework.expression.spel.testresources;
|
||||
|
||||
///CLOVER:OFF
|
||||
public class Person {
|
||||
|
||||
private String privateName;
|
||||
|
||||
Company company;
|
||||
|
||||
public Person(String name) {
|
||||
@@ -42,5 +41,4 @@ public class Person {
|
||||
public Company getCompany() {
|
||||
return company;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user