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 | |
|---|---|---|---|
| 0ddc62e87f |
@@ -1,10 +0,0 @@
|
||||
name: "Validate Gradle Wrapper"
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
validation:
|
||||
name: "Validation"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
@@ -23,7 +23,6 @@ buildSrc/build
|
||||
/spring-*/build
|
||||
/spring-core/kotlin-coroutines/build
|
||||
/framework-bom/build
|
||||
/framework-docs/build
|
||||
/integration-tests/build
|
||||
/src/asciidoc/build
|
||||
target/
|
||||
@@ -42,5 +41,3 @@ out
|
||||
test-output
|
||||
atlassian-ide-plugin.xml
|
||||
.gradletasknamecache
|
||||
|
||||
cached-antora-playbook.yml
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
#### Discuss
|
||||
|
||||
If you have a question, check Stack Overflow using
|
||||
[this list of tags](https://stackoverflow.com/questions/tagged/spring+or+spring-mvc+or+spring-aop+or+spring-jdbc+or+spring-transactions+or+spring-annotations+or+spring-jms+or+spring-el+or+spring-test+or+spring+or+spring-remoting+or+spring-orm+or+spring-jmx+or+spring-cache+or+spring-webflux?tab=Newest).
|
||||
[this list of tags](https://spring.io/questions), organized by Spring project.
|
||||
Find an existing discussion, or start a new one if necessary.
|
||||
|
||||
If you believe there is an issue, search through
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# <img src="src/docs/asciidoc/images/spring-framework.png" width="80" height="80"> Spring Framework [](https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-5.2.x?groups=Build")
|
||||
# <img src="src/docs/asciidoc/images/spring-framework.png" width="80" height="80"> Spring Framework [](https://build.spring.io/browse/SPR)
|
||||
|
||||
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".
|
||||
|
||||
|
||||
+1
-1
@@ -8,4 +8,4 @@ wiki page.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please see https://spring.io/security-policy.
|
||||
Please see https://pivotal.io/security.
|
||||
|
||||
+68
-61
@@ -1,18 +1,26 @@
|
||||
plugins {
|
||||
id 'io.spring.dependency-management' version '1.0.9.RELEASE' apply false
|
||||
id 'io.spring.ge.conventions' version '0.0.7'
|
||||
id 'io.spring.nohttp' version '0.0.5.RELEASE'
|
||||
id "io.freefair.aspectj" version '4.1.6' apply false
|
||||
id 'org.jetbrains.dokka' version '0.10.1' apply false
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.3.72' apply false
|
||||
id 'io.spring.dependency-management' version '1.0.8.RELEASE' apply false
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.3.61' apply false
|
||||
id 'org.jetbrains.dokka' version '0.9.18' apply false
|
||||
id 'org.asciidoctor.jvm.convert' version '2.4.0'
|
||||
id 'org.asciidoctor.jvm.pdf' version '2.4.0'
|
||||
id "com.github.ben-manes.versions" version '0.28.0'
|
||||
id 'com.gradle.build-scan' version '3.2'
|
||||
id 'de.undercouch.download' version '4.1.1'
|
||||
id 'io.spring.nohttp' version '0.0.4.RELEASE'
|
||||
id 'de.undercouch.download' version '4.0.0'
|
||||
id 'com.gradle.build-scan' version '3.1.1'
|
||||
id "com.jfrog.artifactory" version '4.11.0' apply false
|
||||
id "io.freefair.aspectj" version "4.1.1" apply false
|
||||
id "com.github.ben-manes.versions" version "0.24.0"
|
||||
}
|
||||
|
||||
apply from: "$rootDir/gradle/build-scan-user-data.gradle"
|
||||
buildScan {
|
||||
captureTaskInputFiles = true
|
||||
obfuscation {
|
||||
ipAddresses { addresses -> addresses.collect { address -> '0.0.0.0'} }
|
||||
}
|
||||
publishAlwaysIf(System.getenv('GRADLE_ENTERPRISE_URL') != null)
|
||||
server = 'https://ge.spring.io'
|
||||
}
|
||||
|
||||
ext {
|
||||
moduleProjects = subprojects.findAll { it.name.startsWith("spring-") }
|
||||
javaProjects = subprojects - project(":framework-bom")
|
||||
@@ -26,31 +34,32 @@ configure(allprojects) { project ->
|
||||
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom "com.fasterxml.jackson:jackson-bom:2.10.5"
|
||||
mavenBom "io.netty:netty-bom:4.1.51.Final"
|
||||
mavenBom "io.projectreactor:reactor-bom:Dysprosium-SR25"
|
||||
mavenBom "io.rsocket:rsocket-bom:1.0.4"
|
||||
mavenBom "org.eclipse.jetty:jetty-bom:9.4.31.v20200723"
|
||||
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.3.72"
|
||||
mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.3.5"
|
||||
mavenBom "org.junit:junit-bom:5.6.3"
|
||||
mavenBom "com.fasterxml.jackson:jackson-bom:2.10.2"
|
||||
mavenBom "io.netty:netty-bom:4.1.44.Final"
|
||||
mavenBom "io.projectreactor:reactor-bom:Dysprosium-SR3"
|
||||
mavenBom "io.rsocket:rsocket-bom:1.0.0-RC5"
|
||||
mavenBom "org.eclipse.jetty:jetty-bom:9.4.25.v20191220"
|
||||
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.3.61"
|
||||
mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.3.2"
|
||||
mavenBom "org.junit:junit-bom:5.5.2"
|
||||
}
|
||||
dependencies {
|
||||
dependencySet(group: 'org.apache.logging.log4j', version: '2.17.2') {
|
||||
dependencySet(group: 'org.apache.logging.log4j', version: '2.13.0') {
|
||||
entry 'log4j-api'
|
||||
entry 'log4j-core'
|
||||
entry 'log4j-jul'
|
||||
entry 'log4j-slf4j-impl'
|
||||
entry 'log4j-jul'
|
||||
}
|
||||
dependency "org.slf4j:slf4j-api:1.7.32"
|
||||
dependency "org.slf4j:slf4j-api:1.7.30"
|
||||
|
||||
dependency "com.google.code.findbugs:jsr305:3.0.2"
|
||||
|
||||
dependencySet(group: 'org.aspectj', version: '1.9.7') {
|
||||
dependencySet(group: 'org.aspectj', version: '1.9.5') {
|
||||
entry 'aspectjrt'
|
||||
entry 'aspectjtools'
|
||||
entry 'aspectjweaver'
|
||||
}
|
||||
dependencySet(group: 'org.codehaus.groovy', version: '2.5.15') {
|
||||
dependencySet(group: 'org.codehaus.groovy', version: '2.5.8') {
|
||||
entry 'groovy'
|
||||
entry 'groovy-jsr223'
|
||||
entry 'groovy-templates'
|
||||
@@ -60,38 +69,37 @@ 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.21"
|
||||
dependency "io.projectreactor.tools:blockhound:1.0.6.RELEASE"
|
||||
dependency "io.reactivex.rxjava2:rxjava:2.2.17"
|
||||
|
||||
dependency "com.caucho:hessian:4.0.63"
|
||||
dependency "com.caucho:hessian:4.0.62"
|
||||
dependency "com.fasterxml:aalto-xml:1.2.2"
|
||||
dependency("com.fasterxml.woodstox:woodstox-core:6.2.3") {
|
||||
dependency("com.fasterxml.woodstox:woodstox-core:6.0.2") {
|
||||
exclude group: "stax", name: "stax-api"
|
||||
}
|
||||
dependency "com.google.code.gson:gson:2.8.6"
|
||||
dependency "com.google.protobuf:protobuf-java-util:3.11.4"
|
||||
dependency "com.google.protobuf:protobuf-java-util:3.11.1"
|
||||
dependency "com.googlecode.protobuf-java-format:protobuf-java-format:1.4"
|
||||
dependency("com.thoughtworks.xstream:xstream:1.4.11.1") {
|
||||
exclude group: "xpp3", name: "xpp3_min"
|
||||
exclude group: "xmlpull", name: "xmlpull"
|
||||
}
|
||||
dependency "org.apache.johnzon:johnzon-jsonb:1.2.10"
|
||||
dependency "org.apache.johnzon:johnzon-jsonb:1.2.2"
|
||||
dependency("org.codehaus.jettison:jettison:1.3.8") {
|
||||
exclude group: "stax", name: "stax-api"
|
||||
}
|
||||
dependencySet(group: 'org.jibx', version: '1.3.3') {
|
||||
dependencySet(group: 'org.jibx', version: '1.3.1') {
|
||||
entry 'jibx-bind'
|
||||
entry 'jibx-run'
|
||||
}
|
||||
dependency "org.ogce:xpp3:1.1.6"
|
||||
dependency "org.yaml:snakeyaml:1.27"
|
||||
dependency "org.yaml:snakeyaml:1.25"
|
||||
|
||||
dependency "com.h2database:h2:1.4.200"
|
||||
dependency "com.github.ben-manes.caffeine:caffeine:2.8.8"
|
||||
dependency "com.github.librepdf:openpdf:1.3.25"
|
||||
dependency "com.github.ben-manes.caffeine:caffeine:2.8.0"
|
||||
dependency "com.github.librepdf:openpdf:1.3.11"
|
||||
dependency "com.rometools:rome:1.12.2"
|
||||
dependency "commons-io:commons-io:2.5"
|
||||
dependency "io.vavr:vavr:0.10.3"
|
||||
dependency "io.vavr:vavr:0.10.0"
|
||||
dependency "net.sf.jopt-simple:jopt-simple:5.0.4"
|
||||
dependencySet(group: 'org.apache.activemq', version: '5.8.0') {
|
||||
entry 'activemq-broker'
|
||||
@@ -101,37 +109,37 @@ configure(allprojects) { project ->
|
||||
entry 'activemq-stomp'
|
||||
}
|
||||
dependency "org.apache.bcel:bcel:6.0"
|
||||
dependency "org.apache.commons:commons-pool2:2.8.1"
|
||||
dependency "org.apache.commons:commons-pool2:2.7.0"
|
||||
dependencySet(group: 'org.apache.derby', version: '10.14.2.0') {
|
||||
entry 'derby'
|
||||
entry 'derbyclient'
|
||||
}
|
||||
dependency "org.apache.poi:poi-ooxml:4.1.2"
|
||||
dependency "org.apache-extras.beanshell:bsh:2.0b6"
|
||||
dependency "org.freemarker:freemarker:2.3.30"
|
||||
dependency "org.hsqldb:hsqldb:2.5.1"
|
||||
dependency "org.apache.poi:poi-ooxml:4.1.1"
|
||||
dependency "org.beanshell:bsh:2.0b5"
|
||||
dependency "org.freemarker:freemarker:2.3.29"
|
||||
dependency "org.hsqldb:hsqldb:2.5.0"
|
||||
dependency "org.quartz-scheduler:quartz:2.3.2"
|
||||
dependency "org.codehaus.fabric3.api:commonj:1.1.0"
|
||||
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.28.Final"
|
||||
dependency "org.hibernate:hibernate-validator:6.1.7.Final"
|
||||
dependency "org.webjars:webjars-locator-core:0.46"
|
||||
dependency "org.hibernate:hibernate-core:5.4.10.Final"
|
||||
dependency "org.hibernate:hibernate-validator:6.1.0.Final"
|
||||
dependency "org.webjars:webjars-locator-core:0.43"
|
||||
dependency "org.webjars:underscorejs:1.8.3"
|
||||
|
||||
dependencySet(group: 'org.apache.tomcat', version: '9.0.37') {
|
||||
dependencySet(group: 'org.apache.tomcat', version: '9.0.30') {
|
||||
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.37') {
|
||||
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.30') {
|
||||
entry 'tomcat-embed-core'
|
||||
entry 'tomcat-embed-websocket'
|
||||
}
|
||||
dependencySet(group: 'io.undertow', version: '2.0.32.Final') {
|
||||
dependencySet(group: 'io.undertow', version: '2.0.29.Final') {
|
||||
entry 'undertow-core'
|
||||
entry('undertow-websockets-jsr') {
|
||||
exclude group: "org.jboss.spec.javax.websocket", name: "jboss-websocket-api_1.1_spec"
|
||||
@@ -142,19 +150,19 @@ configure(allprojects) { project ->
|
||||
}
|
||||
}
|
||||
|
||||
dependencySet(group: 'com.squareup.okhttp3', version: '3.14.9') {
|
||||
dependencySet(group: 'com.squareup.okhttp3', version: '3.14.6') {
|
||||
entry 'okhttp'
|
||||
entry 'mockwebserver'
|
||||
}
|
||||
dependency("org.apache.httpcomponents:httpclient:4.5.13") {
|
||||
dependency("org.apache.httpcomponents:httpclient:4.5.10") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.apache.httpcomponents:httpasyncclient:4.1.4") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency "org.eclipse.jetty:jetty-reactive-httpclient:1.1.4"
|
||||
dependency "org.eclipse.jetty:jetty-reactive-httpclient:1.1.1"
|
||||
|
||||
dependency "org.jruby:jruby:9.2.11.1"
|
||||
dependency "org.jruby:jruby:9.2.9.0"
|
||||
dependency "org.python:jython-standalone:2.7.1"
|
||||
dependency "org.mozilla:rhino:1.7.11"
|
||||
|
||||
@@ -179,25 +187,25 @@ configure(allprojects) { project ->
|
||||
dependency "org.testng:testng:6.14.3"
|
||||
dependency "org.hamcrest:hamcrest:2.1"
|
||||
dependency "org.awaitility:awaitility:3.1.6"
|
||||
dependency "org.assertj:assertj-core:3.18.1"
|
||||
dependency "org.assertj:assertj-core:3.14.0"
|
||||
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.3.3') {
|
||||
dependencySet(group: 'org.mockito', version: '3.2.0') {
|
||||
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.9.3"
|
||||
|
||||
dependency("net.sourceforge.htmlunit:htmlunit:2.43.0") {
|
||||
dependency("net.sourceforge.htmlunit:htmlunit:2.36.0") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.seleniumhq.selenium:htmlunit-driver:2.43.1") {
|
||||
dependency("org.seleniumhq.selenium:htmlunit-driver:2.36.0") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.seleniumhq.selenium:selenium-java:3.141.59") {
|
||||
@@ -223,9 +231,9 @@ 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.10"
|
||||
dependency "org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.7"
|
||||
dependency "com.jamonapi:jamon:2.81"
|
||||
dependency "joda-time:joda-time:2.10.5"
|
||||
dependency "org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.5"
|
||||
dependency "org.javamoney:moneta:1.3"
|
||||
|
||||
dependency "com.sun.activation:javax.activation:1.2.0"
|
||||
@@ -296,7 +304,6 @@ configure([rootProject] + javaProjects) { project ->
|
||||
apply plugin: "java-test-fixtures"
|
||||
apply plugin: "checkstyle"
|
||||
apply plugin: 'org.springframework.build.compile'
|
||||
apply from: "${rootDir}/gradle/custom-java-home.gradle"
|
||||
apply from: "${rootDir}/gradle/ide.gradle"
|
||||
|
||||
pluginManager.withPlugin("kotlin") {
|
||||
@@ -325,7 +332,7 @@ configure([rootProject] + javaProjects) { project ->
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
toolVersion = "8.38"
|
||||
toolVersion = "8.28"
|
||||
configDir = rootProject.file("src/checkstyle")
|
||||
}
|
||||
|
||||
@@ -366,7 +373,7 @@ configure([rootProject] + javaProjects) { project ->
|
||||
"https://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.10/",
|
||||
"https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/",
|
||||
"https://junit.org/junit4/javadoc/4.12/",
|
||||
"https://junit.org/junit5/docs/5.6.3/api/"
|
||||
"https://junit.org/junit5/docs/5.5.2/api/"
|
||||
] as String[]
|
||||
}
|
||||
|
||||
@@ -386,7 +393,7 @@ configure(rootProject) {
|
||||
|
||||
nohttp {
|
||||
source.exclude "**/test-output/**"
|
||||
allowlistFile = project.file("src/nohttp/allowlist.lines")
|
||||
whitelistFile = project.file("src/nohttp/whitelist.lines")
|
||||
def rootPath = file(rootDir).toPath()
|
||||
def projectDirs = allprojects.collect { it.projectDir } + "${rootDir}/buildSrc"
|
||||
projectDirs.forEach { dir ->
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ They are declared in the `build.gradle` file in this folder.
|
||||
|
||||
### Compiler conventions
|
||||
|
||||
The `org.springframework.build.compile` plugin applies the Java compiler conventions to the build.
|
||||
The `org.springframework.build.compile` plubin applies the Java compiler conventions to the build.
|
||||
By default, the build compiles sources with Java `1.8` source and target compatibility.
|
||||
You can test a different source compatibility version on the CLI with a project property like:
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
implementation "me.champeau.gradle:japicmp-gradle-plugin:0.2.8"
|
||||
implementation "com.google.guava:guava:28.2-jre" // required by japicmp-gradle-plugin
|
||||
implementation "com.google.guava:guava:18.0" // required by japicmp-gradle-plugin
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
|
||||
+9
-13
@@ -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.
|
||||
@@ -33,7 +33,6 @@ import org.gradle.api.tasks.compile.JavaCompile;
|
||||
* with a dedicated property on the CLI: {@code "./gradlew test -PjavaSourceVersion=11"}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public class CompilerConventionsPlugin implements Plugin<Project> {
|
||||
|
||||
@@ -41,13 +40,13 @@ public class CompilerConventionsPlugin implements Plugin<Project> {
|
||||
* The project property that can be used to switch the Java source
|
||||
* compatibility version for building source and test classes.
|
||||
*/
|
||||
public static final String JAVA_SOURCE_VERSION_PROPERTY = "javaSourceVersion";
|
||||
public static String JAVA_SOURCE_VERSION_PROPERTY = "javaSourceVersion";
|
||||
|
||||
public static final JavaVersion DEFAULT_COMPILER_VERSION = JavaVersion.VERSION_1_8;
|
||||
public static JavaVersion DEFAULT_COMPILER_VERSION = JavaVersion.VERSION_1_8;
|
||||
|
||||
private static final List<String> COMPILER_ARGS;
|
||||
private static List<String> COMPILER_ARGS;
|
||||
|
||||
private static final List<String> TEST_COMPILER_ARGS;
|
||||
private static List<String> TEST_COMPILER_ARGS;
|
||||
|
||||
static {
|
||||
List<String> commonCompilerArgs = Arrays.asList(
|
||||
@@ -73,8 +72,7 @@ public class CompilerConventionsPlugin implements Plugin<Project> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the common Java compiler options for main sources, test fixture sources, and
|
||||
* test sources.
|
||||
* Applies the common Java compiler options for sources and test sources.
|
||||
* @param project the current project
|
||||
*/
|
||||
private void applyJavaCompileConventions(Project project) {
|
||||
@@ -89,18 +87,16 @@ public class CompilerConventionsPlugin implements Plugin<Project> {
|
||||
java.setTargetCompatibility(DEFAULT_COMPILER_VERSION);
|
||||
|
||||
project.getTasks().withType(JavaCompile.class)
|
||||
.matching(compileTask -> compileTask.getName().equals(JavaPlugin.COMPILE_JAVA_TASK_NAME))
|
||||
.matching(javaCompile -> javaCompile.getName().equals(JavaPlugin.COMPILE_JAVA_TASK_NAME))
|
||||
.forEach(compileTask -> {
|
||||
compileTask.getOptions().setCompilerArgs(COMPILER_ARGS);
|
||||
compileTask.getOptions().setEncoding("UTF-8");
|
||||
});
|
||||
project.getTasks().withType(JavaCompile.class)
|
||||
.matching(compileTask -> compileTask.getName().equals(JavaPlugin.COMPILE_TEST_JAVA_TASK_NAME)
|
||||
|| compileTask.getName().equals("compileTestFixturesJava"))
|
||||
.matching(javaCompile -> javaCompile.getName().equals(JavaPlugin.COMPILE_TEST_JAVA_TASK_NAME))
|
||||
.forEach(compileTask -> {
|
||||
compileTask.getOptions().setCompilerArgs(TEST_COMPILER_ARGS);
|
||||
compileTask.getOptions().setEncoding("UTF-8");
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
== Spring Framework Concourse pipeline
|
||||
|
||||
The Spring Framework uses https://concourse-ci.org/[Concourse] for its CI build and other automated tasks.
|
||||
The Spring team has a dedicated Concourse instance available at https://ci.spring.io with a build pipeline
|
||||
for https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-5.2.x[Spring Framework 5.2.x].
|
||||
|
||||
=== Setting up your development environment
|
||||
|
||||
If you're part of the Spring Framework project on GitHub, you can get access to CI management features.
|
||||
First, you need to go to https://ci.spring.io and install the client CLI for your platform (see bottom right of the screen).
|
||||
|
||||
You can then login with the instance using:
|
||||
|
||||
[source]
|
||||
----
|
||||
$ fly -t spring login -n spring-framework -c https://ci.spring.io
|
||||
----
|
||||
|
||||
Once logged in, you should get something like:
|
||||
|
||||
[source]
|
||||
----
|
||||
$ fly ts
|
||||
name url team expiry
|
||||
spring https://ci.spring.io spring-framework Wed, 25 Mar 2020 17:45:26 UTC
|
||||
----
|
||||
|
||||
=== Pipeline configuration and structure
|
||||
|
||||
The build pipelines are described in `pipeline.yml` file.
|
||||
|
||||
This file is listing Concourse resources, i.e. build inputs and outputs such as container images, artifact repositories, source repositories, notification services, etc.
|
||||
|
||||
It also describes jobs (a job is a sequence of inputs, tasks and outputs); jobs are organized by groups.
|
||||
|
||||
The `pipeline.yml` definition contains `((parameters))` which are loaded from the `parameters.yml` file or from our https://docs.cloudfoundry.org/credhub/[credhub instance].
|
||||
|
||||
You'll find in this folder the following resources:
|
||||
|
||||
* `pipeline.yml` the build pipeline
|
||||
* `parameters.yml` the build parameters used for the pipeline
|
||||
* `images/` holds the container images definitions used in this pipeline
|
||||
* `scripts/` holds the build scripts that ship within the CI container images
|
||||
* `tasks` contains the task definitions used in the main `pipeline.yml`
|
||||
|
||||
=== Updating the build pipeline
|
||||
|
||||
Updating files on the repository is not enough to update the build pipeline, as changes need to be applied.
|
||||
|
||||
The pipeline can be deployed using the following command:
|
||||
|
||||
[source]
|
||||
----
|
||||
$ fly -t spring set-pipeline -p spring-framework-5.2.x -c ci/pipeline.yml -l ci/parameters.yml
|
||||
----
|
||||
|
||||
NOTE: This assumes that you have credhub integration configured with the appropriate secrets.
|
||||
@@ -1,17 +0,0 @@
|
||||
changelog:
|
||||
repository: spring-projects/spring-framework
|
||||
sections:
|
||||
- title: ":star: New Features"
|
||||
labels:
|
||||
- "type: enhancement"
|
||||
- title: ":lady_beetle: Bug Fixes"
|
||||
labels:
|
||||
- "type: bug"
|
||||
- "type: regression"
|
||||
- title: ":notebook_with_decorative_cover: Documentation"
|
||||
labels:
|
||||
- "type: documentation"
|
||||
- title: ":hammer: Dependency Upgrades"
|
||||
sort: "title"
|
||||
labels:
|
||||
- "type: dependency-upgrade"
|
||||
@@ -1,10 +0,0 @@
|
||||
logging:
|
||||
level:
|
||||
io.spring.concourse: DEBUG
|
||||
spring:
|
||||
main:
|
||||
banner-mode: off
|
||||
sonatype:
|
||||
exclude:
|
||||
- 'build-info\.json'
|
||||
- '.*\.zip'
|
||||
@@ -1,21 +0,0 @@
|
||||
== CI Images
|
||||
|
||||
These images are used by CI to run the actual builds.
|
||||
|
||||
To build the image locally run the following from this directory:
|
||||
|
||||
----
|
||||
$ docker build --no-cache -f <image-folder>/Dockerfile .
|
||||
----
|
||||
|
||||
For example
|
||||
|
||||
----
|
||||
$ docker build --no-cache -f spring-framework-ci-image/Dockerfile .
|
||||
----
|
||||
|
||||
To test run:
|
||||
|
||||
----
|
||||
$ docker run -it --entrypoint /bin/bash <SHA>
|
||||
----
|
||||
@@ -1,8 +0,0 @@
|
||||
FROM ubuntu:focal-20220302
|
||||
|
||||
ADD setup.sh /setup.sh
|
||||
ADD get-jdk-url.sh /get-jdk-url.sh
|
||||
RUN ./setup.sh java11
|
||||
|
||||
ENV JAVA_HOME /opt/openjdk
|
||||
ENV PATH $JAVA_HOME/bin:$PATH
|
||||
@@ -1,8 +0,0 @@
|
||||
FROM ubuntu:jammy-20230624
|
||||
|
||||
ADD setup.sh /setup.sh
|
||||
ADD get-jdk-url.sh /get-jdk-url.sh
|
||||
RUN ./setup.sh java8
|
||||
|
||||
ENV JAVA_HOME /opt/openjdk
|
||||
ENV PATH $JAVA_HOME/bin:$PATH
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
java8)
|
||||
echo "https://github.com/bell-sw/Liberica/releases/download/8u372+7/bellsoft-jdk8u372+7-linux-amd64.tar.gz"
|
||||
;;
|
||||
java11)
|
||||
echo "https://github.com/bell-sw/Liberica/releases/download/11.0.19%2B7/bellsoft-jdk11.0.19+7-linux-amd64.tar.gz"
|
||||
;;
|
||||
*)
|
||||
echo $"Unknown java version"
|
||||
exit 1
|
||||
esac
|
||||
@@ -1,35 +0,0 @@
|
||||
#!/bin/bash
|
||||
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
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
curl https://raw.githubusercontent.com/spring-io/concourse-java-scripts/v0.0.4/concourse-java.sh > /opt/concourse-java.sh
|
||||
|
||||
curl --output /opt/concourse-release-scripts.jar https://repo.spring.io/release/io/spring/concourse/releasescripts/concourse-release-scripts/0.3.2/concourse-release-scripts-0.3.2.jar
|
||||
|
||||
###########################################################
|
||||
# JAVA
|
||||
###########################################################
|
||||
JDK_URL=$( ./get-jdk-url.sh $1 )
|
||||
|
||||
mkdir -p /opt/openjdk
|
||||
cd /opt/openjdk
|
||||
curl -L ${JDK_URL} | tar zx --strip-components=1
|
||||
test -f /opt/openjdk/bin/java
|
||||
test -f /opt/openjdk/bin/javac
|
||||
|
||||
###########################################################
|
||||
# GRADLE ENTERPRISE
|
||||
###########################################################
|
||||
cd /
|
||||
mkdir ~/.gradle
|
||||
echo 'systemProp.user.name=concourse' > ~/.gradle/gradle.properties
|
||||
@@ -1,13 +0,0 @@
|
||||
email-server: "smtp.svc.pivotal.io"
|
||||
email-from: "ci@spring.io"
|
||||
email-to: ["spring-framework-dev@pivotal.io"]
|
||||
github-repo: "https://github.com/spring-projects/spring-framework.git"
|
||||
github-repo-name: "spring-projects/spring-framework"
|
||||
docker-hub-organization: "springci"
|
||||
artifactory-server: "https://repo.spring.io"
|
||||
branch: "5.2.x"
|
||||
milestone: "5.2.x"
|
||||
build-name: "spring-framework"
|
||||
pipeline-name: "spring-framework"
|
||||
concourse-url: "https://ci.spring.io"
|
||||
task-timeout: 1h00m
|
||||
-399
@@ -1,399 +0,0 @@
|
||||
anchors:
|
||||
git-repo-resource-source: &git-repo-resource-source
|
||||
uri: ((github-repo))
|
||||
username: ((github-username))
|
||||
password: ((github-ci-release-token))
|
||||
branch: ((branch))
|
||||
gradle-enterprise-task-params: &gradle-enterprise-task-params
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ((gradle_enterprise_secret_access_key))
|
||||
GRADLE_ENTERPRISE_CACHE_USERNAME: ((gradle_enterprise_cache_user.username))
|
||||
GRADLE_ENTERPRISE_CACHE_PASSWORD: ((gradle_enterprise_cache_user.password))
|
||||
sonatype-task-params: &sonatype-task-params
|
||||
SONATYPE_USERNAME: ((sonatype-username))
|
||||
SONATYPE_PASSWORD: ((sonatype-password))
|
||||
SONATYPE_URL: ((sonatype-url))
|
||||
SONATYPE_STAGING_PROFILE_ID: ((sonatype-staging-profile-id))
|
||||
artifactory-task-params: &artifactory-task-params
|
||||
ARTIFACTORY_SERVER: ((artifactory-server))
|
||||
ARTIFACTORY_USERNAME: ((artifactory-username))
|
||||
ARTIFACTORY_PASSWORD: ((artifactory-password))
|
||||
build-project-task-params: &build-project-task-params
|
||||
privileged: true
|
||||
timeout: ((task-timeout))
|
||||
params:
|
||||
BRANCH: ((branch))
|
||||
<<: *gradle-enterprise-task-params
|
||||
docker-resource-source: &docker-resource-source
|
||||
username: ((docker-hub-username))
|
||||
password: ((docker-hub-password))
|
||||
slack-fail-params: &slack-fail-params
|
||||
text: >
|
||||
:concourse-failed: <https://ci.spring.io/teams/${BUILD_TEAM_NAME}/pipelines/${BUILD_PIPELINE_NAME}/jobs/${BUILD_JOB_NAME}/builds/${BUILD_NAME}|${BUILD_PIPELINE_NAME} ${BUILD_JOB_NAME} failed!>
|
||||
[$TEXT_FILE_CONTENT]
|
||||
text_file: git-repo/build/build-scan-uri.txt
|
||||
silent: true
|
||||
icon_emoji: ":concourse:"
|
||||
username: concourse-ci
|
||||
changelog-task-params: &changelog-task-params
|
||||
name: generated-changelog/tag
|
||||
tag: generated-changelog/tag
|
||||
body: generated-changelog/changelog.md
|
||||
github-task-params: &github-task-params
|
||||
GITHUB_USERNAME: ((github-username))
|
||||
GITHUB_TOKEN: ((github-ci-release-token))
|
||||
|
||||
resource_types:
|
||||
- name: registry-image
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: concourse/registry-image-resource
|
||||
tag: 1.7.1
|
||||
- name: artifactory-resource
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: springio/artifactory-resource
|
||||
tag: 0.0.17
|
||||
- name: github-release
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: concourse/github-release-resource
|
||||
tag: 1.5.5
|
||||
- name: github-status-resource
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: dpb587/github-status-resource
|
||||
tag: master
|
||||
- name: slack-notification
|
||||
type: registry-image
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: cfcommunity/slack-notification-resource
|
||||
tag: latest
|
||||
resources:
|
||||
- name: git-repo
|
||||
type: git
|
||||
icon: github
|
||||
source:
|
||||
<<: *git-repo-resource-source
|
||||
- name: every-morning
|
||||
type: time
|
||||
icon: alarm
|
||||
source:
|
||||
start: 8:00 AM
|
||||
stop: 9:00 AM
|
||||
location: Europe/Vienna
|
||||
- name: ci-images-git-repo
|
||||
type: git
|
||||
icon: github
|
||||
source:
|
||||
uri: ((github-repo))
|
||||
branch: ((branch))
|
||||
paths: ["ci/images/*"]
|
||||
- name: ci-image
|
||||
type: docker-image
|
||||
icon: docker
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: ((docker-hub-organization))/spring-framework-ci
|
||||
tag: ((milestone))
|
||||
- name: ci-image-jdk11
|
||||
type: docker-image
|
||||
icon: docker
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: ((docker-hub-organization))/spring-framework-ci-jdk11
|
||||
tag: ((milestone))
|
||||
- name: artifactory-repo
|
||||
type: artifactory-resource
|
||||
icon: package-variant
|
||||
source:
|
||||
uri: ((artifactory-server))
|
||||
username: ((artifactory-username))
|
||||
password: ((artifactory-password))
|
||||
build_name: ((build-name))
|
||||
- name: repo-status-build
|
||||
type: github-status-resource
|
||||
icon: eye-check-outline
|
||||
source:
|
||||
repository: ((github-repo-name))
|
||||
access_token: ((github-ci-status-token))
|
||||
branch: ((branch))
|
||||
context: build
|
||||
- name: repo-status-jdk11-build
|
||||
type: github-status-resource
|
||||
icon: eye-check-outline
|
||||
source:
|
||||
repository: ((github-repo-name))
|
||||
access_token: ((github-ci-status-token))
|
||||
branch: ((branch))
|
||||
context: jdk11-build
|
||||
- name: slack-alert
|
||||
type: slack-notification
|
||||
icon: slack
|
||||
source:
|
||||
url: ((slack-webhook-url))
|
||||
- name: github-pre-release
|
||||
type: github-release
|
||||
icon: briefcase-download-outline
|
||||
source:
|
||||
owner: spring-projects
|
||||
repository: spring-framework
|
||||
access_token: ((github-ci-release-token))
|
||||
pre_release: true
|
||||
release: false
|
||||
- name: github-release
|
||||
type: github-release
|
||||
icon: briefcase-download
|
||||
source:
|
||||
owner: spring-projects
|
||||
repository: spring-framework
|
||||
access_token: ((github-ci-release-token))
|
||||
pre_release: false
|
||||
jobs:
|
||||
- name: build-ci-images
|
||||
plan:
|
||||
- get: ci-images-git-repo
|
||||
trigger: true
|
||||
- in_parallel:
|
||||
- put: ci-image
|
||||
params:
|
||||
build: ci-images-git-repo/ci/images
|
||||
dockerfile: ci-images-git-repo/ci/images/ci-image/Dockerfile
|
||||
- put: ci-image-jdk11
|
||||
params:
|
||||
build: ci-images-git-repo/ci/images
|
||||
dockerfile: ci-images-git-repo/ci/images/ci-image-jdk11/Dockerfile
|
||||
- name: build
|
||||
serial: true
|
||||
public: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
trigger: true
|
||||
- put: repo-status-build
|
||||
params: { state: "pending", commit: "git-repo" }
|
||||
- do:
|
||||
- task: build-project
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/build-project.yml
|
||||
<<: *build-project-task-params
|
||||
on_failure:
|
||||
do:
|
||||
- put: repo-status-build
|
||||
params: { state: "failure", commit: "git-repo" }
|
||||
- put: slack-alert
|
||||
params:
|
||||
<<: *slack-fail-params
|
||||
- put: repo-status-build
|
||||
params: { state: "success", commit: "git-repo" }
|
||||
- put: artifactory-repo
|
||||
params: &artifactory-params
|
||||
signing_key: ((signing-key))
|
||||
signing_passphrase: ((signing-passphrase))
|
||||
repo: libs-snapshot-local
|
||||
folder: distribution-repository
|
||||
build_uri: "https://ci.spring.io/teams/${BUILD_TEAM_NAME}/pipelines/${BUILD_PIPELINE_NAME}/jobs/${BUILD_JOB_NAME}/builds/${BUILD_NAME}"
|
||||
build_number: "${BUILD_PIPELINE_NAME}-${BUILD_JOB_NAME}-${BUILD_NAME}"
|
||||
disable_checksum_uploads: true
|
||||
threads: 8
|
||||
artifact_set:
|
||||
- include:
|
||||
- "/**/spring-*.zip"
|
||||
properties:
|
||||
"zip.name": "spring-framework"
|
||||
"zip.displayname": "Spring Framework"
|
||||
"zip.deployed": "false"
|
||||
- include:
|
||||
- "/**/spring-*-docs.zip"
|
||||
properties:
|
||||
"zip.type": "docs"
|
||||
- include:
|
||||
- "/**/spring-*-dist.zip"
|
||||
properties:
|
||||
"zip.type": "dist"
|
||||
- include:
|
||||
- "/**/spring-*-schema.zip"
|
||||
properties:
|
||||
"zip.type": "schema"
|
||||
get_params:
|
||||
threads: 8
|
||||
- name: jdk11-build
|
||||
serial: true
|
||||
public: true
|
||||
plan:
|
||||
- get: ci-image-jdk11
|
||||
- get: git-repo
|
||||
- get: every-morning
|
||||
trigger: true
|
||||
- put: repo-status-jdk11-build
|
||||
params: { state: "pending", commit: "git-repo" }
|
||||
- do:
|
||||
- task: check-project
|
||||
image: ci-image-jdk11
|
||||
file: git-repo/ci/tasks/check-project.yml
|
||||
<<: *build-project-task-params
|
||||
on_failure:
|
||||
do:
|
||||
- put: repo-status-jdk11-build
|
||||
params: { state: "failure", commit: "git-repo" }
|
||||
- put: slack-alert
|
||||
params:
|
||||
<<: *slack-fail-params
|
||||
- put: repo-status-jdk11-build
|
||||
params: { state: "success", commit: "git-repo" }
|
||||
- name: stage-milestone
|
||||
serial: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
trigger: false
|
||||
- task: stage
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/stage-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: M
|
||||
<<: *gradle-enterprise-task-params
|
||||
- put: artifactory-repo
|
||||
params:
|
||||
<<: *artifactory-params
|
||||
repo: libs-staging-local
|
||||
- put: git-repo
|
||||
params:
|
||||
repository: stage-git-repo
|
||||
- name: promote-milestone
|
||||
serial: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
trigger: false
|
||||
- get: artifactory-repo
|
||||
trigger: false
|
||||
passed: [stage-milestone]
|
||||
params:
|
||||
download_artifacts: false
|
||||
save_build_info: true
|
||||
- task: promote
|
||||
file: git-repo/ci/tasks/promote-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: M
|
||||
<<: *artifactory-task-params
|
||||
- task: generate-changelog
|
||||
file: git-repo/ci/tasks/generate-changelog.yml
|
||||
params:
|
||||
RELEASE_TYPE: M
|
||||
<<: *github-task-params
|
||||
- put: github-pre-release
|
||||
params:
|
||||
<<: *changelog-task-params
|
||||
- name: stage-rc
|
||||
serial: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
trigger: false
|
||||
- task: stage
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/stage-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: RC
|
||||
<<: *gradle-enterprise-task-params
|
||||
- put: artifactory-repo
|
||||
params:
|
||||
<<: *artifactory-params
|
||||
repo: libs-staging-local
|
||||
- put: git-repo
|
||||
params:
|
||||
repository: stage-git-repo
|
||||
- name: promote-rc
|
||||
serial: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
trigger: false
|
||||
- get: artifactory-repo
|
||||
trigger: false
|
||||
passed: [stage-rc]
|
||||
params:
|
||||
download_artifacts: false
|
||||
save_build_info: true
|
||||
- task: promote
|
||||
file: git-repo/ci/tasks/promote-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: RC
|
||||
<<: *artifactory-task-params
|
||||
- task: generate-changelog
|
||||
file: git-repo/ci/tasks/generate-changelog.yml
|
||||
params:
|
||||
RELEASE_TYPE: RC
|
||||
<<: *github-task-params
|
||||
- put: github-pre-release
|
||||
params:
|
||||
<<: *changelog-task-params
|
||||
- name: stage-release
|
||||
serial: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
trigger: false
|
||||
- task: stage
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/stage-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: RELEASE
|
||||
<<: *gradle-enterprise-task-params
|
||||
- put: artifactory-repo
|
||||
params:
|
||||
<<: *artifactory-params
|
||||
repo: libs-staging-local
|
||||
- put: git-repo
|
||||
params:
|
||||
repository: stage-git-repo
|
||||
- name: promote-release
|
||||
serial: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
trigger: false
|
||||
- get: artifactory-repo
|
||||
trigger: false
|
||||
passed: [stage-release]
|
||||
params:
|
||||
download_artifacts: true
|
||||
save_build_info: true
|
||||
- task: promote
|
||||
file: git-repo/ci/tasks/promote-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: RELEASE
|
||||
<<: *artifactory-task-params
|
||||
<<: *sonatype-task-params
|
||||
- name: create-github-release
|
||||
serial: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
- get: artifactory-repo
|
||||
trigger: true
|
||||
passed: [promote-release]
|
||||
params:
|
||||
download_artifacts: false
|
||||
save_build_info: true
|
||||
- task: generate-changelog
|
||||
file: git-repo/ci/tasks/generate-changelog.yml
|
||||
params:
|
||||
RELEASE_TYPE: RELEASE
|
||||
<<: *github-task-params
|
||||
- put: github-release
|
||||
params:
|
||||
<<: *changelog-task-params
|
||||
|
||||
groups:
|
||||
- name: "builds"
|
||||
jobs: ["build", "jdk11-build"]
|
||||
- name: "releases"
|
||||
jobs: ["stage-milestone", "stage-rc", "stage-release", "promote-milestone", "promote-rc", "promote-release", "create-github-release"]
|
||||
- name: "ci-images"
|
||||
jobs: ["build-ci-images"]
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source $(dirname $0)/common.sh
|
||||
repository=$(pwd)/distribution-repository
|
||||
|
||||
pushd git-repo > /dev/null
|
||||
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false --no-daemon --max-workers=4 -PdeploymentRepository=${repository} build publishAllPublicationsToDeploymentRepository
|
||||
popd > /dev/null
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source $(dirname $0)/common.sh
|
||||
|
||||
pushd git-repo > /dev/null
|
||||
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false --no-daemon --max-workers=4 check
|
||||
popd > /dev/null
|
||||
@@ -1,2 +0,0 @@
|
||||
source /opt/concourse-java.sh
|
||||
setup_symlinks
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
CONFIG_DIR=git-repo/ci/config
|
||||
version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
|
||||
|
||||
milestone=${version}
|
||||
if [[ $RELEASE_TYPE = "RELEASE" ]]; then
|
||||
milestone=${version%.RELEASE}
|
||||
fi
|
||||
|
||||
java -jar /github-changelog-generator.jar \
|
||||
--spring.config.location=${CONFIG_DIR}/changelog-generator.yml \
|
||||
${milestone} generated-changelog/changelog.md
|
||||
|
||||
echo ${version} > generated-changelog/version
|
||||
echo v${version} > generated-changelog/tag
|
||||
@@ -1,18 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
source $(dirname $0)/common.sh
|
||||
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 /concourse-release-scripts.jar \
|
||||
--spring.config.location=${CONFIG_DIR}/release-scripts.yml \
|
||||
publishToCentral $RELEASE_TYPE $BUILD_INFO_LOCATION artifactory-repo || { exit 1; }
|
||||
|
||||
java -jar /concourse-release-scripts.jar \
|
||||
--spring.config.location=${CONFIG_DIR}/release-scripts.yml \
|
||||
promote $RELEASE_TYPE $BUILD_INFO_LOCATION || { exit 1; }
|
||||
|
||||
echo "Promotion complete"
|
||||
echo $version > version/version
|
||||
@@ -1,50 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source $(dirname $0)/common.sh
|
||||
repository=$(pwd)/distribution-repository
|
||||
|
||||
pushd git-repo > /dev/null
|
||||
git fetch --tags --all > /dev/null
|
||||
popd > /dev/null
|
||||
|
||||
git clone git-repo stage-git-repo > /dev/null
|
||||
|
||||
pushd stage-git-repo > /dev/null
|
||||
|
||||
snapshotVersion=$( awk -F '=' '$1 == "version" { print $2 }' gradle.properties )
|
||||
if [[ $RELEASE_TYPE = "M" ]]; then
|
||||
stageVersion=$( get_next_milestone_release $snapshotVersion)
|
||||
nextVersion=$snapshotVersion
|
||||
elif [[ $RELEASE_TYPE = "RC" ]]; then
|
||||
stageVersion=$( get_next_rc_release $snapshotVersion)
|
||||
nextVersion=$snapshotVersion
|
||||
elif [[ $RELEASE_TYPE = "RELEASE" ]]; then
|
||||
stageVersion=$( get_next_release $snapshotVersion "RELEASE")
|
||||
nextVersion=$( bump_version_number $snapshotVersion)
|
||||
else
|
||||
echo "Unknown release type $RELEASE_TYPE" >&2; exit 1;
|
||||
fi
|
||||
|
||||
echo "Staging $stageVersion (next version will be $nextVersion)"
|
||||
sed -i "s/version=$snapshotVersion/version=$stageVersion/" gradle.properties
|
||||
|
||||
git config user.name "Spring Builds" > /dev/null
|
||||
git config user.email "spring-builds@users.noreply.github.com" > /dev/null
|
||||
git add gradle.properties > /dev/null
|
||||
git commit -m"Release v$stageVersion" > /dev/null
|
||||
git tag -a "v$stageVersion" -m"Release v$stageVersion" > /dev/null
|
||||
|
||||
./gradlew --no-daemon --max-workers=4 -PdeploymentRepository=${repository} build publishAllPublicationsToDeploymentRepository
|
||||
|
||||
git reset --hard HEAD^ > /dev/null
|
||||
if [[ $nextVersion != $snapshotVersion ]]; then
|
||||
echo "Setting next development version (v$nextVersion)"
|
||||
sed -i "s/version=$snapshotVersion/version=$nextVersion/" gradle.properties
|
||||
git add gradle.properties > /dev/null
|
||||
git commit -m"Next development version (v$nextVersion)" > /dev/null
|
||||
fi;
|
||||
|
||||
echo "Staging Complete"
|
||||
|
||||
popd > /dev/null
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
export BUILD_INFO_LOCATION=$(pwd)/artifactory-repo/build-info.json
|
||||
version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
|
||||
java -jar /opt/concourse-release-scripts.jar syncToCentral "RELEASE" $BUILD_INFO_LOCATION || { exit 1; }
|
||||
|
||||
echo "Sync complete"
|
||||
echo $version > version/version
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
platform: linux
|
||||
inputs:
|
||||
- name: git-repo
|
||||
outputs:
|
||||
- name: distribution-repository
|
||||
- name: git-repo
|
||||
caches:
|
||||
- path: gradle
|
||||
params:
|
||||
BRANCH:
|
||||
CI: true
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY:
|
||||
GRADLE_ENTERPRISE_CACHE_USERNAME:
|
||||
GRADLE_ENTERPRISE_CACHE_PASSWORD:
|
||||
GRADLE_ENTERPRISE_URL: https://ge.spring.io
|
||||
run:
|
||||
path: bash
|
||||
args:
|
||||
- -ec
|
||||
- |
|
||||
${PWD}/git-repo/ci/scripts/build-project.sh
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
platform: linux
|
||||
inputs:
|
||||
- name: git-repo
|
||||
outputs:
|
||||
- name: distribution-repository
|
||||
- name: git-repo
|
||||
caches:
|
||||
- path: gradle
|
||||
params:
|
||||
BRANCH:
|
||||
CI: true
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY:
|
||||
GRADLE_ENTERPRISE_CACHE_USERNAME:
|
||||
GRADLE_ENTERPRISE_CACHE_PASSWORD:
|
||||
GRADLE_ENTERPRISE_URL: https://ge.spring.io
|
||||
run:
|
||||
path: bash
|
||||
args:
|
||||
- -ec
|
||||
- |
|
||||
${PWD}/git-repo/ci/scripts/check-project.sh
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: springio/github-changelog-generator
|
||||
tag: '0.0.8'
|
||||
username: ((docker-hub-username))
|
||||
password: ((docker-hub-password))
|
||||
inputs:
|
||||
- name: git-repo
|
||||
- name: artifactory-repo
|
||||
outputs:
|
||||
- name: generated-changelog
|
||||
params:
|
||||
GITHUB_ORGANIZATION:
|
||||
GITHUB_REPO:
|
||||
GITHUB_USERNAME:
|
||||
GITHUB_TOKEN:
|
||||
RELEASE_TYPE:
|
||||
run:
|
||||
path: git-repo/ci/scripts/generate-changelog.sh
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: springio/concourse-release-scripts
|
||||
tag: '0.3.4'
|
||||
username: ((docker-hub-username))
|
||||
password: ((docker-hub-password))
|
||||
inputs:
|
||||
- name: git-repo
|
||||
- name: artifactory-repo
|
||||
outputs:
|
||||
- name: version
|
||||
params:
|
||||
RELEASE_TYPE:
|
||||
ARTIFACTORY_SERVER:
|
||||
ARTIFACTORY_USERNAME:
|
||||
ARTIFACTORY_PASSWORD:
|
||||
SONATYPE_USER:
|
||||
SONATYPE_PASSWORD:
|
||||
SONATYPE_URL:
|
||||
SONATYPE_STAGING_PROFILE_ID:
|
||||
run:
|
||||
path: git-repo/ci/scripts/promote-version.sh
|
||||
@@ -1,17 +0,0 @@
|
||||
---
|
||||
platform: linux
|
||||
inputs:
|
||||
- name: git-repo
|
||||
outputs:
|
||||
- name: stage-git-repo
|
||||
- name: distribution-repository
|
||||
params:
|
||||
RELEASE_TYPE:
|
||||
CI: true
|
||||
GRADLE_ENTERPRISE_CACHE_USERNAME:
|
||||
GRADLE_ENTERPRISE_CACHE_PASSWORD:
|
||||
GRADLE_ENTERPRISE_URL: https://ge.spring.io
|
||||
caches:
|
||||
- path: gradle
|
||||
run:
|
||||
path: git-repo/ci/scripts/stage-version.sh
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
version=5.2.26.BUILD-SNAPSHOT
|
||||
version=5.2.3.RELEASE
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
org.gradle.caching=true
|
||||
org.gradle.parallel=true
|
||||
|
||||
@@ -1,16 +1,90 @@
|
||||
addCustomJavaHomeMetadata()
|
||||
addCustomJavaSourceVersionMetadata()
|
||||
tagOs()
|
||||
tagIde()
|
||||
tagCiOrLocal()
|
||||
addCiMetadata()
|
||||
addGitMetadata()
|
||||
addTestTaskMetadata()
|
||||
|
||||
void addCustomJavaHomeMetadata() {
|
||||
def customJavaHome = System.getProperty("customJavaHome")
|
||||
if (customJavaHome) {
|
||||
buildScan.value "Custom JAVA_HOME", customJavaHome
|
||||
void tagOs() {
|
||||
buildScan.tag System.getProperty('os.name')
|
||||
}
|
||||
|
||||
void tagIde() {
|
||||
if (System.getProperty('idea.version')) {
|
||||
buildScan.tag 'IntelliJ IDEA'
|
||||
} else if (System.getProperty('eclipse.buildId')) {
|
||||
buildScan.tag 'Eclipse'
|
||||
}
|
||||
}
|
||||
|
||||
void addCustomJavaSourceVersionMetadata() {
|
||||
def customJavaSourceVersion = System.getProperty("customJavaSourceVersion")
|
||||
if (customJavaSourceVersion) {
|
||||
buildScan.value "Custom Java Source Version", customJavaSourceVersion
|
||||
void tagCiOrLocal() {
|
||||
buildScan.tag(isCi() ? 'CI' : 'LOCAL')
|
||||
}
|
||||
|
||||
void addGitMetadata() {
|
||||
buildScan.background {
|
||||
def gitCommitId = execAndGetStdout('git', 'rev-parse', '--short=8', '--verify', 'HEAD')
|
||||
def gitBranchName = execAndGetStdout('git', 'rev-parse', '--abbrev-ref', 'HEAD')
|
||||
def gitStatus = execAndGetStdout('git', 'status', '--porcelain')
|
||||
|
||||
if(gitCommitId) {
|
||||
def commitIdLabel = 'Git Commit ID'
|
||||
value commitIdLabel, gitCommitId
|
||||
link 'Git commit build scans', customValueSearchUrl([(commitIdLabel): gitCommitId])
|
||||
}
|
||||
if (gitBranchName) {
|
||||
tag gitBranchName
|
||||
value 'Git branch', gitBranchName
|
||||
}
|
||||
if (gitStatus) {
|
||||
tag 'dirty'
|
||||
value 'Git status', gitStatus
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addCiMetadata() {
|
||||
def ciBuild = 'CI BUILD'
|
||||
if (isBamboo()) {
|
||||
buildScan.link ciBuild, System.getenv('bamboo_resultsUrl')
|
||||
}
|
||||
}
|
||||
|
||||
void addTestTaskMetadata() {
|
||||
allprojects {
|
||||
tasks.withType(Test) { test ->
|
||||
doFirst {
|
||||
buildScan.value "Test#maxParallelForks[${test.path}]", test.maxParallelForks.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isCi() {
|
||||
isBamboo()
|
||||
}
|
||||
|
||||
boolean isBamboo() {
|
||||
System.getenv('bamboo_resultsUrl')
|
||||
}
|
||||
|
||||
String execAndGetStdout(String... args) {
|
||||
def stdout = new ByteArrayOutputStream()
|
||||
exec {
|
||||
commandLine(args)
|
||||
standardOutput = stdout
|
||||
}
|
||||
return stdout.toString().trim()
|
||||
}
|
||||
|
||||
String customValueSearchUrl(Map<String, String> search) {
|
||||
def query = search.collect { name, value ->
|
||||
"search.names=${encodeURL(name)}&search.values=${encodeURL(value)}"
|
||||
}.join('&')
|
||||
|
||||
"$buildScan.server/scans?$query"
|
||||
}
|
||||
|
||||
String encodeURL(String url) {
|
||||
URLEncoder.encode(url, 'UTF-8')
|
||||
}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// This script adds support for the following two JVM system properties
|
||||
// that control the build for alternative JDKs (i.e., a JDK other than
|
||||
// the one used to launch the Gradle process).
|
||||
//
|
||||
// - customJavaHome: absolute path to the alternate JDK installation to
|
||||
// use to compile Java code and execute tests. This system property
|
||||
// is also used in spring-oxm.gradle to determine whether JiBX is
|
||||
// supported.
|
||||
//
|
||||
// - customJavaSourceVersion: Java version supplied to the `--release`
|
||||
// command line flag to control the Java source and target
|
||||
// compatibility version. Supported versions include 9 or higher.
|
||||
// Do not set this system property if Java 8 should be used.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// ./gradlew -DcustomJavaHome=/Library/Java/JavaVirtualMachines/jdk-14.jdk/Contents/Home test
|
||||
//
|
||||
// ./gradlew --no-build-cache -DcustomJavaHome=/Library/Java/JavaVirtualMachines/jdk-14.jdk/Contents/Home test
|
||||
//
|
||||
// ./gradlew -DcustomJavaHome=/Library/Java/JavaVirtualMachines/jdk-14.jdk/Contents/Home -DcustomJavaSourceVersion=14 test
|
||||
//
|
||||
//
|
||||
// Credits: inspired by work from Marc Philipp and Stephane Nicoll
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
// import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile
|
||||
|
||||
def customJavaHome = System.getProperty("customJavaHome")
|
||||
|
||||
if (customJavaHome) {
|
||||
def customJavaHomeDir = new File(customJavaHome)
|
||||
def customJavaSourceVersion = System.getProperty("customJavaSourceVersion")
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
logger.info("Java home for " + it.name + " task in " + project.name + ": " + customJavaHomeDir)
|
||||
options.forkOptions.javaHome = customJavaHomeDir
|
||||
inputs.property("customJavaHome", customJavaHome)
|
||||
if (customJavaSourceVersion) {
|
||||
options.compilerArgs += [ "--release", customJavaSourceVersion]
|
||||
inputs.property("customJavaSourceVersion", customJavaSourceVersion)
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(GroovyCompile) {
|
||||
logger.info("Java home for " + it.name + " task in " + project.name + ": " + customJavaHomeDir)
|
||||
options.forkOptions.javaHome = customJavaHomeDir
|
||||
inputs.property("customJavaHome", customJavaHome)
|
||||
if (customJavaSourceVersion) {
|
||||
options.compilerArgs += [ "--release", customJavaSourceVersion]
|
||||
inputs.property("customJavaSourceVersion", customJavaSourceVersion)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
tasks.withType(KotlinJvmCompile) {
|
||||
logger.info("Java home for " + it.name + " task in " + project.name + ": " + customJavaHome)
|
||||
kotlinOptions.jdkHome = customJavaHomeDir
|
||||
inputs.property("customJavaHome", customJavaHome)
|
||||
}
|
||||
*/
|
||||
|
||||
tasks.withType(Test) {
|
||||
def javaExecutable = customJavaHome + "/bin/java"
|
||||
if (OperatingSystem.current().isWindows()) {
|
||||
javaExecutable += ".exe"
|
||||
}
|
||||
logger.info("Java executable for " + it.name + " task in " + project.name + ": " + javaExecutable)
|
||||
executable = javaExecutable
|
||||
inputs.property("customJavaHome", customJavaHome)
|
||||
if (customJavaSourceVersion) {
|
||||
inputs.property("customJavaSourceVersion", customJavaSourceVersion)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+53
-83
@@ -3,16 +3,7 @@ configurations {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
asciidoctorExt("io.spring.asciidoctor:spring-asciidoctor-extensions-block-switch:0.6.1")
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url "https://repo.spring.io/release"
|
||||
mavenContent {
|
||||
includeGroup "io.spring.asciidoctor"
|
||||
}
|
||||
}
|
||||
asciidoctorExt("io.spring.asciidoctor:spring-asciidoctor-extensions:0.2.0.RELEASE")
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,50 +56,41 @@ dokka {
|
||||
dependsOn {
|
||||
tasks.getByName("api")
|
||||
}
|
||||
|
||||
doFirst {
|
||||
configuration {
|
||||
classpath = moduleProjects.collect { project -> project.jar.outputs.files.getFiles() }.flatten()
|
||||
classpath += files(moduleProjects.collect { it.sourceSets.main.compileClasspath })
|
||||
|
||||
moduleProjects.findAll {
|
||||
it.pluginManager.hasPlugin("kotlin")
|
||||
}.each { project ->
|
||||
def kotlinDirs = project.sourceSets.main.kotlin.srcDirs.collect()
|
||||
kotlinDirs -= project.sourceSets.main.java.srcDirs
|
||||
kotlinDirs.each { dir ->
|
||||
if (dir.exists()) {
|
||||
sourceRoot {
|
||||
path = dir.path
|
||||
}
|
||||
}
|
||||
classpath = moduleProjects.collect { project -> project.jar.outputs.files.getFiles() }.flatten()
|
||||
classpath += files(moduleProjects.collect { it.sourceSets.main.compileClasspath })
|
||||
sourceDirs = files(moduleProjects
|
||||
.findAll {
|
||||
it.pluginManager.hasPlugin("kotlin")
|
||||
}
|
||||
}
|
||||
}
|
||||
.collect { project ->
|
||||
def kotlinDirs = project.sourceSets.main.kotlin.srcDirs.collect()
|
||||
kotlinDirs -= project.sourceSets.main.java.srcDirs
|
||||
})
|
||||
}
|
||||
|
||||
moduleName = "spring-framework"
|
||||
outputFormat = "html"
|
||||
outputDirectory = "$buildDir/docs/kdoc"
|
||||
|
||||
configuration {
|
||||
moduleName = "spring-framework"
|
||||
|
||||
externalDocumentationLink {
|
||||
url = new URL("https://docs.spring.io/spring-framework/docs/$version/javadoc-api/")
|
||||
packageListUrl = new File(buildDir, "docs/javadoc/package-list").toURI().toURL()
|
||||
}
|
||||
externalDocumentationLink {
|
||||
url = new URL("https://projectreactor.io/docs/core/release/api/")
|
||||
}
|
||||
externalDocumentationLink {
|
||||
url = new URL("https://www.reactive-streams.org/reactive-streams-1.0.1-javadoc/")
|
||||
}
|
||||
externalDocumentationLink {
|
||||
url = new URL("https://docs.spring.io/spring-framework/docs/$version/javadoc-api/")
|
||||
packageListUrl = new File(buildDir, "docs/javadoc/package-list").toURI().toURL()
|
||||
}
|
||||
externalDocumentationLink {
|
||||
url = new URL("https://projectreactor.io/docs/core/release/api/")
|
||||
}
|
||||
externalDocumentationLink {
|
||||
url = new URL("https://www.reactive-streams.org/reactive-streams-1.0.1-javadoc/")
|
||||
}
|
||||
externalDocumentationLink {
|
||||
url = new URL("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/")
|
||||
}
|
||||
}
|
||||
|
||||
task downloadResources(type: Download) {
|
||||
src "https://repo.spring.io/artifactory/snapshot/io/spring/docresources/" +
|
||||
"spring-doc-resources/0.2.6-SNAPSHOT/spring-doc-resources-0.2.6-20210308.231804-2.zip"
|
||||
def version = "0.1.3.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")
|
||||
onlyIfModified true
|
||||
useETag "all"
|
||||
@@ -125,7 +107,29 @@ asciidoctorj {
|
||||
version '1.5.0-beta.8'
|
||||
}
|
||||
}
|
||||
fatalWarnings ".*"
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce the Spring Framework Reference documentation
|
||||
* from "src/docs/asciidoc" into "build/asciidoc/html5"
|
||||
*/
|
||||
asciidoctor {
|
||||
baseDirFollowsSourceDir()
|
||||
configurations 'asciidoctorExt'
|
||||
sources {
|
||||
include '*.adoc'
|
||||
}
|
||||
outputDir "$buildDir/docs/ref-docs/"
|
||||
resources {
|
||||
from(sourceDir) {
|
||||
include 'images/*', 'css/**', 'js/**'
|
||||
}
|
||||
from extractDocResources
|
||||
}
|
||||
logDocuments = true
|
||||
outputOptions {
|
||||
backends = ["html5", "pdf"]
|
||||
}
|
||||
options doctype: 'book', eruby: 'erubis'
|
||||
attributes([
|
||||
icons: 'font',
|
||||
@@ -137,51 +141,17 @@ asciidoctorj {
|
||||
sectnums: '',
|
||||
'source-highlighter': 'highlight.js',
|
||||
highlightjsdir: 'js/highlight',
|
||||
'highlightjs-theme': 'github', // 'googlecode',
|
||||
'highlightjs-theme': 'github',
|
||||
stylesdir: 'css/',
|
||||
stylesheet: 'stylesheet.css',
|
||||
'spring-version': project.version
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the Spring Framework Reference documentation from "src/docs/asciidoc"
|
||||
* in "build/docs/ref-docs/html5".
|
||||
*/
|
||||
asciidoctor {
|
||||
baseDirFollowsSourceDir()
|
||||
configurations 'asciidoctorExt'
|
||||
sources {
|
||||
include '*.adoc'
|
||||
}
|
||||
outputDir "$buildDir/docs/ref-docs/html5"
|
||||
logDocuments = true
|
||||
resources {
|
||||
from(sourceDir) {
|
||||
include 'images/*', 'css/**', 'js/**'
|
||||
}
|
||||
from extractDocResources
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the Spring Framework Reference documentation from "src/docs/asciidoc"
|
||||
* in "build/docs/ref-docs/pdf".
|
||||
*/
|
||||
asciidoctorPdf {
|
||||
baseDirFollowsSourceDir()
|
||||
configurations 'asciidoctorExt'
|
||||
sources {
|
||||
include '*.adoc'
|
||||
}
|
||||
outputDir "$buildDir/docs/ref-docs/pdf"
|
||||
logDocuments = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip all docs (API and reference) into a single archive
|
||||
*/
|
||||
task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'asciidoctorPdf', 'dokka']) {
|
||||
task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'dokka']) {
|
||||
group = "Distribution"
|
||||
description = "Builds -${archiveClassifier} archive containing api and reference " +
|
||||
"for deployment at https://docs.spring.io/spring-framework/docs."
|
||||
@@ -194,10 +164,10 @@ task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'asciidoctorPdf', 'dok
|
||||
from (api) {
|
||||
into "javadoc-api"
|
||||
}
|
||||
from ("$asciidoctor.outputDir") {
|
||||
from ("$asciidoctor.outputDir/html5") {
|
||||
into "spring-framework-reference"
|
||||
}
|
||||
from ("$asciidoctorPdf.outputDir") {
|
||||
from ("$asciidoctor.outputDir/pdf") {
|
||||
into "spring-framework-reference/pdf"
|
||||
}
|
||||
from (dokka) {
|
||||
|
||||
+2
-1
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
apply plugin: "maven-publish"
|
||||
apply plugin: 'com.jfrog.artifactory'
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
@@ -49,16 +50,6 @@ publishing {
|
||||
}
|
||||
}
|
||||
|
||||
configureDeploymentRepository(project)
|
||||
|
||||
void configureDeploymentRepository(Project project) {
|
||||
project.plugins.withType(MavenPublishPlugin.class).all {
|
||||
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
|
||||
if (project.hasProperty("deploymentRepository")) {
|
||||
publishing.repositories.maven {
|
||||
it.url = project.property("deploymentRepository")
|
||||
it.name = "deployment"
|
||||
}
|
||||
}
|
||||
}
|
||||
artifactoryPublish {
|
||||
publications(publishing.publications.mavenJava)
|
||||
}
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Integration tests for advice invocation order for advice configured via the
|
||||
* AOP namespace.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.2.7
|
||||
* @see org.springframework.aop.framework.autoproxy.AspectJAutoProxyAdviceOrderIntegrationTests
|
||||
*/
|
||||
class AopNamespaceHandlerAdviceOrderIntegrationTests {
|
||||
|
||||
@Nested
|
||||
@SpringJUnitConfig(locations = "AopNamespaceHandlerAdviceOrderIntegrationTests-afterFirst.xml")
|
||||
@DirtiesContext
|
||||
class AfterAdviceFirstTests {
|
||||
|
||||
@Test
|
||||
void afterAdviceIsInvokedFirst(@Autowired Echo echo, @Autowired InvocationTrackingAspect aspect) throws Exception {
|
||||
assertThat(aspect.invocations).isEmpty();
|
||||
assertThat(echo.echo(42)).isEqualTo(42);
|
||||
assertThat(aspect.invocations).containsExactly("around - start", "before", "around - end", "after", "after returning");
|
||||
|
||||
aspect.invocations.clear();
|
||||
assertThatExceptionOfType(Exception.class).isThrownBy(() -> echo.echo(new Exception()));
|
||||
assertThat(aspect.invocations).containsExactly("around - start", "before", "around - end", "after", "after throwing");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@SpringJUnitConfig(locations = "AopNamespaceHandlerAdviceOrderIntegrationTests-afterLast.xml")
|
||||
@DirtiesContext
|
||||
class AfterAdviceLastTests {
|
||||
|
||||
@Test
|
||||
void afterAdviceIsInvokedLast(@Autowired Echo echo, @Autowired InvocationTrackingAspect aspect) throws Exception {
|
||||
assertThat(aspect.invocations).isEmpty();
|
||||
assertThat(echo.echo(42)).isEqualTo(42);
|
||||
assertThat(aspect.invocations).containsExactly("around - start", "before", "around - end", "after returning", "after");
|
||||
|
||||
aspect.invocations.clear();
|
||||
assertThatExceptionOfType(Exception.class).isThrownBy(() -> echo.echo(new Exception()));
|
||||
assertThat(aspect.invocations).containsExactly("around - start", "before", "around - end", "after throwing", "after");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class Echo {
|
||||
|
||||
Object echo(Object obj) throws Exception {
|
||||
if (obj instanceof Exception) {
|
||||
throw (Exception) obj;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
static class InvocationTrackingAspect {
|
||||
|
||||
List<String> invocations = new ArrayList<>();
|
||||
|
||||
Object around(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
invocations.add("around - start");
|
||||
try {
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
finally {
|
||||
invocations.add("around - end");
|
||||
}
|
||||
}
|
||||
|
||||
void before() {
|
||||
invocations.add("before");
|
||||
}
|
||||
|
||||
void afterReturning() {
|
||||
invocations.add("after returning");
|
||||
}
|
||||
|
||||
void afterThrowing() {
|
||||
invocations.add("after throwing");
|
||||
}
|
||||
|
||||
void after() {
|
||||
invocations.add("after");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-233
@@ -1,233 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.framework.autoproxy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.After;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.AfterThrowing;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Integration tests for advice invocation order for advice configured via
|
||||
* AspectJ auto-proxy support.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.2.7
|
||||
* @see org.springframework.aop.config.AopNamespaceHandlerAdviceOrderIntegrationTests
|
||||
*/
|
||||
class AspectJAutoProxyAdviceOrderIntegrationTests {
|
||||
|
||||
/**
|
||||
* {@link After @After} advice declared as first <em>after</em> method in source code.
|
||||
*/
|
||||
@Nested
|
||||
@SpringJUnitConfig(AfterAdviceFirstConfig.class)
|
||||
@DirtiesContext
|
||||
class AfterAdviceFirstTests {
|
||||
|
||||
@Test
|
||||
void afterAdviceIsInvokedLast(@Autowired Echo echo, @Autowired AfterAdviceFirstAspect aspect) throws Exception {
|
||||
assertThat(aspect.invocations).isEmpty();
|
||||
assertThat(echo.echo(42)).isEqualTo(42);
|
||||
assertThat(aspect.invocations).containsExactly("around - start", "before", "after returning", "after", "around - end");
|
||||
|
||||
aspect.invocations.clear();
|
||||
assertThatExceptionOfType(Exception.class).isThrownBy(
|
||||
() -> echo.echo(new Exception()));
|
||||
assertThat(aspect.invocations).containsExactly("around - start", "before", "after throwing", "after", "around - end");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This test class uses {@link AfterAdviceLastAspect} which declares its
|
||||
* {@link After @After} advice as the last <em>after advice type</em> method
|
||||
* in its source code.
|
||||
*
|
||||
* <p>On Java versions prior to JDK 7, we would have expected the {@code @After}
|
||||
* advice method to be invoked before {@code @AfterThrowing} and
|
||||
* {@code @AfterReturning} advice methods due to the AspectJ precedence
|
||||
* rules implemented in
|
||||
* {@link org.springframework.aop.aspectj.autoproxy.AspectJPrecedenceComparator}.
|
||||
*/
|
||||
@Nested
|
||||
@SpringJUnitConfig(AfterAdviceLastConfig.class)
|
||||
@DirtiesContext
|
||||
class AfterAdviceLastTests {
|
||||
|
||||
@Test
|
||||
void afterAdviceIsInvokedLast(@Autowired Echo echo, @Autowired AfterAdviceLastAspect aspect) throws Exception {
|
||||
assertThat(aspect.invocations).isEmpty();
|
||||
assertThat(echo.echo(42)).isEqualTo(42);
|
||||
assertThat(aspect.invocations).containsExactly("around - start", "before", "after returning", "after", "around - end");
|
||||
|
||||
aspect.invocations.clear();
|
||||
assertThatExceptionOfType(Exception.class).isThrownBy(
|
||||
() -> echo.echo(new Exception()));
|
||||
assertThat(aspect.invocations).containsExactly("around - start", "before", "after throwing", "after", "around - end");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableAspectJAutoProxy(proxyTargetClass = true)
|
||||
static class AfterAdviceFirstConfig {
|
||||
|
||||
@Bean
|
||||
AfterAdviceFirstAspect echoAspect() {
|
||||
return new AfterAdviceFirstAspect();
|
||||
}
|
||||
|
||||
@Bean
|
||||
Echo echo() {
|
||||
return new Echo();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAspectJAutoProxy(proxyTargetClass = true)
|
||||
static class AfterAdviceLastConfig {
|
||||
|
||||
@Bean
|
||||
AfterAdviceLastAspect echoAspect() {
|
||||
return new AfterAdviceLastAspect();
|
||||
}
|
||||
|
||||
@Bean
|
||||
Echo echo() {
|
||||
return new Echo();
|
||||
}
|
||||
}
|
||||
|
||||
static class Echo {
|
||||
|
||||
Object echo(Object obj) throws Exception {
|
||||
if (obj instanceof Exception) {
|
||||
throw (Exception) obj;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link After @After} advice declared as first <em>after</em> method in source code.
|
||||
*/
|
||||
@Aspect
|
||||
static class AfterAdviceFirstAspect {
|
||||
|
||||
List<String> invocations = new ArrayList<>();
|
||||
|
||||
@Pointcut("execution(* echo(*))")
|
||||
void echo() {
|
||||
}
|
||||
|
||||
@After("echo()")
|
||||
void after() {
|
||||
invocations.add("after");
|
||||
}
|
||||
|
||||
@AfterReturning("echo()")
|
||||
void afterReturning() {
|
||||
invocations.add("after returning");
|
||||
}
|
||||
|
||||
@AfterThrowing("echo()")
|
||||
void afterThrowing() {
|
||||
invocations.add("after throwing");
|
||||
}
|
||||
|
||||
@Before("echo()")
|
||||
void before() {
|
||||
invocations.add("before");
|
||||
}
|
||||
|
||||
@Around("echo()")
|
||||
Object around(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
invocations.add("around - start");
|
||||
try {
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
finally {
|
||||
invocations.add("around - end");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link After @After} advice declared as last <em>after</em> method in source code.
|
||||
*/
|
||||
@Aspect
|
||||
static class AfterAdviceLastAspect {
|
||||
|
||||
List<String> invocations = new ArrayList<>();
|
||||
|
||||
@Pointcut("execution(* echo(*))")
|
||||
void echo() {
|
||||
}
|
||||
|
||||
@Around("echo()")
|
||||
Object around(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
invocations.add("around - start");
|
||||
try {
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
finally {
|
||||
invocations.add("around - end");
|
||||
}
|
||||
}
|
||||
|
||||
@Before("echo()")
|
||||
void before() {
|
||||
invocations.add("before");
|
||||
}
|
||||
|
||||
@AfterReturning("echo()")
|
||||
void afterReturning() {
|
||||
invocations.add("after returning");
|
||||
}
|
||||
|
||||
@AfterThrowing("echo()")
|
||||
void afterThrowing() {
|
||||
invocations.add("after throwing");
|
||||
}
|
||||
|
||||
@After("echo()")
|
||||
void after() {
|
||||
invocations.add("after");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
|
||||
|
||||
<bean id="echo" class="org.springframework.aop.config.AopNamespaceHandlerAdviceOrderIntegrationTests$Echo"/>
|
||||
|
||||
<bean id="invocationTrackingAspect" class="org.springframework.aop.config.AopNamespaceHandlerAdviceOrderIntegrationTests$InvocationTrackingAspect" />
|
||||
|
||||
<aop:config>
|
||||
<aop:aspect id="echoAdvice" ref="invocationTrackingAspect">
|
||||
<aop:pointcut id="echoMethod" expression="execution(* echo(*))" />
|
||||
<aop:around method="around" pointcut-ref="echoMethod" />
|
||||
<aop:before method="before" pointcut-ref="echoMethod" />
|
||||
<aop:after method="after" pointcut-ref="echoMethod" />
|
||||
<aop:after-throwing method="afterThrowing" pointcut-ref="echoMethod" />
|
||||
<aop:after-returning method="afterReturning" pointcut-ref="echoMethod" />
|
||||
</aop:aspect>
|
||||
</aop:config>
|
||||
|
||||
</beans>
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
|
||||
|
||||
<bean id="echo" class="org.springframework.aop.config.AopNamespaceHandlerAdviceOrderIntegrationTests$Echo"/>
|
||||
|
||||
<bean id="invocationTrackingAspect" class="org.springframework.aop.config.AopNamespaceHandlerAdviceOrderIntegrationTests$InvocationTrackingAspect" />
|
||||
|
||||
<aop:config>
|
||||
<aop:aspect id="echoAdvice" ref="invocationTrackingAspect">
|
||||
<aop:pointcut id="echoMethod" expression="execution(* echo(*))" />
|
||||
<aop:around method="around" pointcut-ref="echoMethod" />
|
||||
<aop:before method="before" pointcut-ref="echoMethod" />
|
||||
<aop:after-throwing method="afterThrowing" pointcut-ref="echoMethod" />
|
||||
<aop:after-returning method="afterReturning" pointcut-ref="echoMethod" />
|
||||
<aop:after method="after" pointcut-ref="echoMethod" />
|
||||
</aop:aspect>
|
||||
</aop:config>
|
||||
|
||||
</beans>
|
||||
+2
-2
@@ -10,8 +10,8 @@ include "spring-aop"
|
||||
include "spring-aspects"
|
||||
include "spring-beans"
|
||||
include "spring-context"
|
||||
include "spring-context-indexer"
|
||||
include "spring-context-support"
|
||||
include "spring-context-indexer"
|
||||
include "spring-core"
|
||||
include "kotlin-coroutines"
|
||||
project(':kotlin-coroutines').projectDir = file('spring-core/kotlin-coroutines')
|
||||
@@ -26,8 +26,8 @@ include "spring-oxm"
|
||||
include "spring-test"
|
||||
include "spring-tx"
|
||||
include "spring-web"
|
||||
include "spring-webflux"
|
||||
include "spring-webmvc"
|
||||
include "spring-webflux"
|
||||
include "spring-websocket"
|
||||
include "framework-bom"
|
||||
include "integration-tests"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,7 +23,7 @@ import java.lang.reflect.AccessibleObject;
|
||||
* terminology).
|
||||
*
|
||||
* <p>A runtime joinpoint is an <i>event</i> that occurs on a static
|
||||
* joinpoint (i.e. a location in a program). For instance, an
|
||||
* joinpoint (i.e. a location in a the program). For instance, an
|
||||
* invocation is the runtime joinpoint on a method (static joinpoint).
|
||||
* The static part of a given joinpoint can be generically retrieved
|
||||
* using the {@link #getStaticPart()} method.
|
||||
|
||||
@@ -33,9 +33,9 @@ public interface AfterReturningAdvice extends AfterAdvice {
|
||||
/**
|
||||
* Callback after a given method successfully returned.
|
||||
* @param returnValue the value returned by the method, if any
|
||||
* @param method the method being invoked
|
||||
* @param args the arguments to the method
|
||||
* @param target the target of the method invocation. May be {@code null}.
|
||||
* @param method method being invoked
|
||||
* @param args arguments to the method
|
||||
* @param target target of the method invocation. May be {@code null}.
|
||||
* @throws Throwable if this object wishes to abort the call.
|
||||
* Any exception thrown will be returned to the caller if it's
|
||||
* allowed by the method signature. Otherwise the exception
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,7 +26,7 @@ import org.aopalliance.aop.Advice;
|
||||
* <p>Introductions are often <b>mixins</b>, enabling the building of composite
|
||||
* objects that can achieve many of the goals of multiple inheritance in Java.
|
||||
*
|
||||
* <p>Compared to {@link IntroductionInfo}, this interface allows an advice to
|
||||
* <p>Compared to {qlink IntroductionInfo}, this interface allows an advice to
|
||||
* implement a range of interfaces that is not necessarily known in advance.
|
||||
* Thus an {@link IntroductionAdvisor} can be used to specify which interfaces
|
||||
* will be exposed in an advised object.
|
||||
|
||||
@@ -32,9 +32,9 @@ public interface MethodBeforeAdvice extends BeforeAdvice {
|
||||
|
||||
/**
|
||||
* Callback before a given method is invoked.
|
||||
* @param method the method being invoked
|
||||
* @param args the arguments to the method
|
||||
* @param target the target of the method invocation. May be {@code null}.
|
||||
* @param method method being invoked
|
||||
* @param args arguments to the method
|
||||
* @param target target of the method invocation. May be {@code null}.
|
||||
* @throws Throwable if this object wishes to abort the call.
|
||||
* Any exception thrown will be returned to the caller if it's
|
||||
* allowed by the method signature. Otherwise the exception
|
||||
|
||||
+2
-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.
|
||||
@@ -648,7 +648,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
}
|
||||
|
||||
if (tokens[currentIndex].endsWith(")")) {
|
||||
sb.append(tokens[currentIndex], 0, tokens[currentIndex].length() - 1);
|
||||
sb.append(tokens[currentIndex].substring(0, tokens[currentIndex].length() - 1));
|
||||
return new PointcutBody(numTokensConsumed, sb.toString().trim());
|
||||
}
|
||||
|
||||
|
||||
+4
-6
@@ -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.
|
||||
@@ -219,12 +219,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
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -103,11 +103,10 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
@Override
|
||||
public void validate(Class<?> aspectClass) throws AopConfigException {
|
||||
// If the parent has the annotation and isn't abstract it's an error
|
||||
Class<?> superclass = aspectClass.getSuperclass();
|
||||
if (superclass.getAnnotation(Aspect.class) != null &&
|
||||
!Modifier.isAbstract(superclass.getModifiers())) {
|
||||
if (aspectClass.getSuperclass().getAnnotation(Aspect.class) != null &&
|
||||
!Modifier.isAbstract(aspectClass.getSuperclass().getModifiers())) {
|
||||
throw new AopConfigException("[" + aspectClass.getName() + "] cannot extend concrete aspect [" +
|
||||
superclass.getName() + "]");
|
||||
aspectClass.getSuperclass().getName() + "]");
|
||||
}
|
||||
|
||||
AjType<?> ajType = AjTypeSystem.getAjType(aspectClass);
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
|
||||
* introspect to create AJType metadata using the type returned for the
|
||||
* given bean name from the BeanFactory.
|
||||
* @param beanFactory the BeanFactory to obtain instance(s) from
|
||||
* @param name the name of the bean
|
||||
* @param name name of the bean
|
||||
*/
|
||||
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name) {
|
||||
this(beanFactory, name, null);
|
||||
|
||||
+2
-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.
|
||||
@@ -97,7 +97,7 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
}
|
||||
// We must be careful not to instantiate beans eagerly as in this case they
|
||||
// would be cached by the Spring container but would not have been weaved.
|
||||
Class<?> beanType = this.beanFactory.getType(beanName, false);
|
||||
Class<?> beanType = this.beanFactory.getType(beanName);
|
||||
if (beanType == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
+8
-23
@@ -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.
|
||||
@@ -56,15 +56,14 @@ import org.springframework.util.comparator.InstanceComparator;
|
||||
|
||||
/**
|
||||
* Factory that can create Spring AOP Advisors given AspectJ classes from
|
||||
* classes honoring AspectJ's annotation syntax, using reflection to invoke the
|
||||
* corresponding advice methods.
|
||||
* classes honoring the AspectJ 5 annotation syntax, using reflection to
|
||||
* invoke the corresponding advice methods.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
* @author Ramnivas Laddad
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@@ -73,17 +72,13 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
private static final Comparator<Method> METHOD_COMPARATOR;
|
||||
|
||||
static {
|
||||
// Note: although @After is ordered before @AfterReturning and @AfterThrowing,
|
||||
// an @After advice method will actually be invoked after @AfterReturning and
|
||||
// @AfterThrowing methods due to the fact that AspectJAfterAdvice.invoke(MethodInvocation)
|
||||
// invokes proceed() in a `try` block and only invokes the @After advice method
|
||||
// in a corresponding `finally` block.
|
||||
Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
|
||||
new InstanceComparator<>(
|
||||
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
|
||||
(Converter<Method, Annotation>) method -> {
|
||||
AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
|
||||
return (ann != null ? ann.getAnnotation() : null);
|
||||
AspectJAnnotation<?> annotation =
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
|
||||
return (annotation != null ? annotation.getAnnotation() : null);
|
||||
});
|
||||
Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
|
||||
METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
|
||||
@@ -128,15 +123,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
|
||||
List<Advisor> advisors = new ArrayList<>();
|
||||
for (Method method : getAdvisorMethods(aspectClass)) {
|
||||
// Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect
|
||||
// to getAdvisor(...) to represent the "current position" in the declared methods list.
|
||||
// However, since Java 7 the "current position" is not valid since the JDK no longer
|
||||
// returns declared methods in the order in which they are declared in the source code.
|
||||
// Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods
|
||||
// discovered via reflection in order to support reliable advice ordering across JVM launches.
|
||||
// Specifically, a value of 0 aligns with the default value used in
|
||||
// AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).
|
||||
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
|
||||
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
|
||||
if (advisor != null) {
|
||||
advisors.add(advisor);
|
||||
}
|
||||
@@ -167,9 +154,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
methods.add(method);
|
||||
}
|
||||
}, ReflectionUtils.USER_DECLARED_METHODS);
|
||||
if (methods.size() > 1) {
|
||||
methods.sort(METHOD_COMPARATOR);
|
||||
}
|
||||
methods.sort(METHOD_COMPARATOR);
|
||||
return methods;
|
||||
}
|
||||
|
||||
|
||||
+20
-22
@@ -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.
|
||||
@@ -50,27 +50,27 @@ public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProx
|
||||
|
||||
|
||||
/**
|
||||
* Sort the supplied {@link Advisor} instances according to AspectJ precedence.
|
||||
* <p>If two pieces of advice come from the same aspect, they will have the same
|
||||
* order. Advice from the same aspect is then further ordered according to the
|
||||
* Sort the rest by AspectJ precedence. If two pieces of advice have
|
||||
* come from the same aspect they will have the same order.
|
||||
* Advice from the same aspect is then further ordered according to the
|
||||
* following rules:
|
||||
* <ul>
|
||||
* <li>If either of the pair is <em>after</em> advice, then the advice declared
|
||||
* last gets highest precedence (i.e., runs last).</li>
|
||||
* <li>Otherwise the advice declared first gets highest precedence (i.e., runs
|
||||
* first).</li>
|
||||
* <li>if either of the pair is after advice, then the advice declared
|
||||
* last gets highest precedence (runs last)</li>
|
||||
* <li>otherwise the advice declared first gets highest precedence (runs first)</li>
|
||||
* </ul>
|
||||
* <p><b>Important:</b> Advisors are sorted in precedence order, from highest
|
||||
* precedence to lowest. "On the way in" to a join point, the highest precedence
|
||||
* advisor should run first. "On the way out" of a join point, the highest
|
||||
* precedence advisor should run last.
|
||||
* advisor should run first. "On the way out" of a join point, the highest precedence
|
||||
* advisor should run last.
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
|
||||
List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
|
||||
for (Advisor advisor : advisors) {
|
||||
for (Advisor element : advisors) {
|
||||
partiallyComparableAdvisors.add(
|
||||
new PartiallyComparableAdvisorHolder(advisor, DEFAULT_PRECEDENCE_COMPARATOR));
|
||||
new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
|
||||
}
|
||||
List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
|
||||
if (sorted != null) {
|
||||
@@ -86,8 +86,8 @@ public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProx
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an {@link ExposeInvocationInterceptor} to the beginning of the advice chain.
|
||||
* <p>This additional advice is needed when using AspectJ pointcut expressions
|
||||
* Adds an {@link ExposeInvocationInterceptor} to the beginning of the advice chain.
|
||||
* These additional advices are needed when using AspectJ expression pointcuts
|
||||
* and when using AspectJ-style advice.
|
||||
*/
|
||||
@Override
|
||||
@@ -110,7 +110,7 @@ public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProx
|
||||
|
||||
|
||||
/**
|
||||
* Implements AspectJ's {@link PartialComparable} interface for defining partial orderings.
|
||||
* Implements AspectJ PartialComparable interface for defining partial orderings.
|
||||
*/
|
||||
private static class PartiallyComparableAdvisorHolder implements PartialComparable {
|
||||
|
||||
@@ -140,19 +140,17 @@ public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProx
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Advice advice = this.advisor.getAdvice();
|
||||
StringBuilder sb = new StringBuilder(ClassUtils.getShortName(advice.getClass()));
|
||||
boolean appended = false;
|
||||
sb.append(ClassUtils.getShortName(advice.getClass()));
|
||||
sb.append(": ");
|
||||
if (this.advisor instanceof Ordered) {
|
||||
sb.append(": order = ").append(((Ordered) this.advisor).getOrder());
|
||||
appended = true;
|
||||
sb.append("order ").append(((Ordered) this.advisor).getOrder()).append(", ");
|
||||
}
|
||||
if (advice instanceof AbstractAspectJAdvice) {
|
||||
sb.append(!appended ? ": " : ", ");
|
||||
AbstractAspectJAdvice ajAdvice = (AbstractAspectJAdvice) advice;
|
||||
sb.append("aspect name = ");
|
||||
sb.append(ajAdvice.getAspectName());
|
||||
sb.append(", declaration order = ");
|
||||
sb.append(", declaration order ");
|
||||
sb.append(ajAdvice.getDeclarationOrder());
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
+31
-27
@@ -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.
|
||||
@@ -27,22 +27,20 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* Orders AspectJ advice/advisors by precedence (<i>not</i> invocation order).
|
||||
*
|
||||
* <p>Given two pieces of advice, {@code A} and {@code B}:
|
||||
* <p>Given two pieces of advice, {@code a} and {@code b}:
|
||||
* <ul>
|
||||
* <li>If {@code A} and {@code B} are defined in different aspects, then the advice
|
||||
* in the aspect with the lowest order value has the highest precedence.</li>
|
||||
* <li>If {@code A} and {@code B} are defined in the same aspect, if one of
|
||||
* {@code A} or {@code B} is a form of <em>after</em> advice, then the advice declared
|
||||
* last in the aspect has the highest precedence. If neither {@code A} nor {@code B}
|
||||
* is a form of <em>after</em> advice, then the advice declared first in the aspect
|
||||
* has the highest precedence.</li>
|
||||
* <li>if {@code a} and {@code b} are defined in different aspects, then the advice
|
||||
* in the aspect with the lowest order value has the highest precedence</li>
|
||||
* <li>if {@code a} and {@code b} are defined in the same aspect, then if one of
|
||||
* {@code a} or {@code b} is a form of after advice, then the advice declared last
|
||||
* in the aspect has the highest precedence. If neither {@code a} nor {@code b} is
|
||||
* a form of after advice, then the advice declared first in the aspect has the
|
||||
* highest precedence.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Important: This comparator is used with AspectJ's
|
||||
* {@link org.aspectj.util.PartialOrder PartialOrder} sorting utility. Thus, unlike
|
||||
* a normal {@link Comparator}, a return value of {@code 0} from this comparator
|
||||
* means we don't care about the ordering, not that the two elements must be sorted
|
||||
* identically.
|
||||
* <p>Important: Note that unlike a normal comparator a return of 0 means
|
||||
* we don't care about the ordering, not that the two elements must be sorted
|
||||
* identically. Used with AspectJ PartialOrder class.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
@@ -61,16 +59,16 @@ class AspectJPrecedenceComparator implements Comparator<Advisor> {
|
||||
|
||||
|
||||
/**
|
||||
* Create a default {@code AspectJPrecedenceComparator}.
|
||||
* Create a default AspectJPrecedenceComparator.
|
||||
*/
|
||||
public AspectJPrecedenceComparator() {
|
||||
this.advisorComparator = AnnotationAwareOrderComparator.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an {@code AspectJPrecedenceComparator}, using the given {@link Comparator}
|
||||
* Create a AspectJPrecedenceComparator, using the given Comparator
|
||||
* for comparing {@link org.springframework.aop.Advisor} instances.
|
||||
* @param advisorComparator the {@code Comparator} to use for advisors
|
||||
* @param advisorComparator the Comparator to use for Advisors
|
||||
*/
|
||||
public AspectJPrecedenceComparator(Comparator<? super Advisor> advisorComparator) {
|
||||
Assert.notNull(advisorComparator, "Advisor comparator must not be null");
|
||||
@@ -127,21 +125,27 @@ class AspectJPrecedenceComparator implements Comparator<Advisor> {
|
||||
getAspectName(advisor1).equals(getAspectName(advisor2)));
|
||||
}
|
||||
|
||||
private boolean hasAspectName(Advisor advisor) {
|
||||
return (advisor instanceof AspectJPrecedenceInformation ||
|
||||
advisor.getAdvice() instanceof AspectJPrecedenceInformation);
|
||||
private boolean hasAspectName(Advisor anAdvisor) {
|
||||
return (anAdvisor instanceof AspectJPrecedenceInformation ||
|
||||
anAdvisor.getAdvice() instanceof AspectJPrecedenceInformation);
|
||||
}
|
||||
|
||||
// pre-condition is that hasAspectName returned true
|
||||
private String getAspectName(Advisor advisor) {
|
||||
AspectJPrecedenceInformation precedenceInfo = AspectJAopUtils.getAspectJPrecedenceInformationFor(advisor);
|
||||
Assert.state(precedenceInfo != null, () -> "Unresolvable AspectJPrecedenceInformation for " + advisor);
|
||||
return precedenceInfo.getAspectName();
|
||||
private String getAspectName(Advisor anAdvisor) {
|
||||
AspectJPrecedenceInformation pi = AspectJAopUtils.getAspectJPrecedenceInformationFor(anAdvisor);
|
||||
Assert.state(pi != null, "Unresolvable precedence information");
|
||||
return pi.getAspectName();
|
||||
}
|
||||
|
||||
private int getAspectDeclarationOrder(Advisor advisor) {
|
||||
AspectJPrecedenceInformation precedenceInfo = AspectJAopUtils.getAspectJPrecedenceInformationFor(advisor);
|
||||
return (precedenceInfo != null ? precedenceInfo.getDeclarationOrder() : 0);
|
||||
private int getAspectDeclarationOrder(Advisor anAdvisor) {
|
||||
AspectJPrecedenceInformation precedenceInfo =
|
||||
AspectJAopUtils.getAspectJPrecedenceInformationFor(anAdvisor);
|
||||
if (precedenceInfo != null) {
|
||||
return precedenceInfo.getDeclarationOrder();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,14 +30,13 @@ public class AdviceEntry implements ParseState.Entry {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code AdviceEntry} instance.
|
||||
* @param kind the kind of advice represented by this entry (before, after, around)
|
||||
* Creates a new instance of the {@link AdviceEntry} class.
|
||||
* @param kind the kind of advice represented by this entry (before, after, around, etc.)
|
||||
*/
|
||||
public AdviceEntry(String kind) {
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Advice (" + this.kind + ")";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,14 +30,13 @@ public class AdvisorEntry implements ParseState.Entry {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code AdvisorEntry} instance.
|
||||
* Creates a new instance of the {@link AdvisorEntry} class.
|
||||
* @param name the bean name of the advisor
|
||||
*/
|
||||
public AdvisorEntry(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Advisor '" + this.name + "'";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -61,12 +61,12 @@ public class AopNamespaceHandler extends NamespaceHandlerSupport {
|
||||
*/
|
||||
@Override
|
||||
public void init() {
|
||||
// In 2.0 XSD as well as in 2.5+ XSDs
|
||||
// In 2.0 XSD as well as in 2.1 XSD.
|
||||
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
|
||||
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
|
||||
|
||||
// Only in 2.0 XSD: moved to context namespace in 2.5+
|
||||
// Only in 2.0 XSD: moved to context namespace as of 2.1
|
||||
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,7 +34,7 @@ public class AspectEntry implements ParseState.Entry {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code AspectEntry} instance.
|
||||
* Create a new AspectEntry.
|
||||
* @param id the id of the aspect element
|
||||
* @param ref the bean name referenced by this aspect element
|
||||
*/
|
||||
@@ -43,7 +43,6 @@ public class AspectEntry implements ParseState.Entry {
|
||||
this.ref = ref;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Aspect: " + (StringUtils.hasLength(this.id) ? "id='" + this.id + "'" : "ref='" + this.ref + "'");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,16 +28,14 @@ public class PointcutEntry implements ParseState.Entry {
|
||||
|
||||
private final String name;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code PointcutEntry} instance.
|
||||
* Creates a new instance of the {@link PointcutEntry} class.
|
||||
* @param name the bean name of the pointcut
|
||||
*/
|
||||
public PointcutEntry(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Pointcut '" + this.name + "'";
|
||||
|
||||
+1
-1
@@ -189,7 +189,7 @@ public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
|
||||
|
||||
/**
|
||||
* Determine a TargetSource for the given target (or TargetSource).
|
||||
* @param target the target. If this is an implementation of TargetSource it is
|
||||
* @param target target. If this is an implementation of TargetSource it is
|
||||
* used as our TargetSource; otherwise it is wrapped in a SingletonTargetSource.
|
||||
* @return a TargetSource for this object
|
||||
*/
|
||||
|
||||
@@ -142,7 +142,7 @@ public interface Advised extends TargetClassAware {
|
||||
|
||||
/**
|
||||
* Remove the advisor at the given index.
|
||||
* @param index the index of advisor to remove
|
||||
* @param index index of advisor to remove
|
||||
* @throws AopConfigException if the index is invalid
|
||||
*/
|
||||
void removeAdvisor(int index) throws AopConfigException;
|
||||
@@ -177,7 +177,7 @@ public interface Advised extends TargetClassAware {
|
||||
* <p>Note that the given advice will apply to all invocations on the proxy,
|
||||
* even to the {@code toString()} method! Use appropriate advice implementations
|
||||
* or specify appropriate pointcuts to apply to a narrower set of methods.
|
||||
* @param advice the advice to add to the tail of the chain
|
||||
* @param advice advice to add to the tail of the chain
|
||||
* @throws AopConfigException in case of invalid advice
|
||||
* @see #addAdvice(int, Advice)
|
||||
* @see org.springframework.aop.support.DefaultPointcutAdvisor
|
||||
@@ -193,7 +193,7 @@ public interface Advised extends TargetClassAware {
|
||||
* even to the {@code toString()} method! Use appropriate advice implementations
|
||||
* or specify appropriate pointcuts to apply to a narrower set of methods.
|
||||
* @param pos index from 0 (head)
|
||||
* @param advice the advice to add at the specified position in the advice chain
|
||||
* @param advice advice to add at the specified position in the advice chain
|
||||
* @throws AopConfigException in case of invalid advice
|
||||
*/
|
||||
void addAdvice(int pos, Advice advice) throws AopConfigException;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -49,7 +49,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;
|
||||
@@ -237,7 +236,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
* validates it if not.
|
||||
*/
|
||||
private void validateClassIfNecessary(Class<?> proxySuperClass, @Nullable ClassLoader proxyClassLoader) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
synchronized (validatedClasses) {
|
||||
if (!validatedClasses.containsKey(proxySuperClass)) {
|
||||
doValidateClass(proxySuperClass, proxyClassLoader,
|
||||
@@ -259,17 +258,15 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
int mod = method.getModifiers();
|
||||
if (!Modifier.isStatic(mod) && !Modifier.isPrivate(mod)) {
|
||||
if (Modifier.isFinal(mod)) {
|
||||
if (logger.isInfoEnabled() && implementsInterface(method, ifcs)) {
|
||||
if (implementsInterface(method, ifcs)) {
|
||||
logger.info("Unable to proxy interface-implementing method [" + method + "] because " +
|
||||
"it is marked as final: Consider using interface-based JDK proxies instead!");
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Final method [" + method + "] cannot get proxied via CGLIB: " +
|
||||
"Calls to this method will NOT be routed to the target instance and " +
|
||||
"might lead to NPEs against uninitialized fields in the proxy instance.");
|
||||
}
|
||||
logger.debug("Final method [" + method + "] cannot get proxied via CGLIB: " +
|
||||
"Calls to this method will NOT be routed to the target instance and " +
|
||||
"might lead to NPEs against uninitialized fields in the proxy instance.");
|
||||
}
|
||||
else if (logger.isDebugEnabled() && !Modifier.isPublic(mod) && !Modifier.isProtected(mod) &&
|
||||
else if (!Modifier.isPublic(mod) && !Modifier.isProtected(mod) &&
|
||||
proxyClassLoader != null && proxySuperClass.getClassLoader() != proxyClassLoader) {
|
||||
logger.debug("Method [" + method + "] is package-visible across different ClassLoaders " +
|
||||
"and cannot get proxied via CGLIB: Declare this method as public or protected " +
|
||||
@@ -375,22 +372,6 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the given method with a CGLIB MethodProxy if possible, falling back
|
||||
* to a plain reflection invocation in case of a fast-class generation failure.
|
||||
*/
|
||||
@Nullable
|
||||
private static Object invokeMethod(@Nullable Object target, Method method, Object[] args, MethodProxy methodProxy)
|
||||
throws Throwable {
|
||||
try {
|
||||
return methodProxy.invoke(target, args);
|
||||
}
|
||||
catch (CodeGenerationException ex) {
|
||||
CglibMethodInvocation.logFastClassGenerationFailure(method);
|
||||
return AopUtils.invokeJoinpointUsingReflection(target, method, args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a return value. Wraps a return of {@code this} if necessary to be the
|
||||
* {@code proxy} and also verifies that {@code null} is not returned as a primitive.
|
||||
@@ -441,7 +422,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
@Override
|
||||
@Nullable
|
||||
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
|
||||
Object retVal = invokeMethod(this.target, method, args, methodProxy);
|
||||
Object retVal = methodProxy.invoke(this.target, args);
|
||||
return processReturnType(proxy, this.target, method, retVal);
|
||||
}
|
||||
}
|
||||
@@ -466,7 +447,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
Object oldProxy = null;
|
||||
try {
|
||||
oldProxy = AopContext.setCurrentProxy(proxy);
|
||||
Object retVal = invokeMethod(this.target, method, args, methodProxy);
|
||||
Object retVal = methodProxy.invoke(this.target, args);
|
||||
return processReturnType(proxy, this.target, method, retVal);
|
||||
}
|
||||
finally {
|
||||
@@ -494,7 +475,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
|
||||
Object target = this.targetSource.getTarget();
|
||||
try {
|
||||
Object retVal = invokeMethod(target, method, args, methodProxy);
|
||||
Object retVal = methodProxy.invoke(target, args);
|
||||
return processReturnType(proxy, target, method, retVal);
|
||||
}
|
||||
finally {
|
||||
@@ -524,7 +505,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
Object target = this.targetSource.getTarget();
|
||||
try {
|
||||
oldProxy = AopContext.setCurrentProxy(proxy);
|
||||
Object retVal = invokeMethod(target, method, args, methodProxy);
|
||||
Object retVal = methodProxy.invoke(target, args);
|
||||
return processReturnType(proxy, target, method, retVal);
|
||||
}
|
||||
finally {
|
||||
@@ -545,7 +526,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
private static class StaticDispatcher implements Dispatcher, Serializable {
|
||||
|
||||
@Nullable
|
||||
private final Object target;
|
||||
private Object target;
|
||||
|
||||
public StaticDispatcher(@Nullable Object target) {
|
||||
this.target = target;
|
||||
@@ -571,7 +552,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object loadObject() {
|
||||
public Object loadObject() throws Exception {
|
||||
return this.advised;
|
||||
}
|
||||
}
|
||||
@@ -695,13 +676,13 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
Object retVal;
|
||||
// Check whether we only have one InvokerInterceptor: that is,
|
||||
// no real advice, but just reflective invocation of the target.
|
||||
if (chain.isEmpty() && CglibMethodInvocation.isMethodProxyCompatible(method)) {
|
||||
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
|
||||
// We can skip creating a MethodInvocation: just invoke the target directly.
|
||||
// Note that the final invoker must be an InvokerInterceptor, so we know
|
||||
// it does nothing but a reflective operation on the target, and no hot
|
||||
// swapping or fancy proxying.
|
||||
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
|
||||
retVal = invokeMethod(target, method, argsToUse, methodProxy);
|
||||
retVal = methodProxy.invoke(target, argsToUse);
|
||||
}
|
||||
else {
|
||||
// We need to create a method invocation...
|
||||
@@ -753,7 +734,10 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
|
||||
|
||||
// Only use method proxy for public methods not derived from java.lang.Object
|
||||
this.methodProxy = (isMethodProxyCompatible(method) ? methodProxy : null);
|
||||
this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
|
||||
method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
|
||||
!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
|
||||
methodProxy : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -766,17 +750,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);
|
||||
}
|
||||
}
|
||||
@@ -789,25 +766,10 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
@Override
|
||||
protected Object invokeJoinpoint() throws Throwable {
|
||||
if (this.methodProxy != null) {
|
||||
try {
|
||||
return this.methodProxy.invoke(this.target, this.arguments);
|
||||
}
|
||||
catch (CodeGenerationException ex) {
|
||||
logFastClassGenerationFailure(this.method);
|
||||
}
|
||||
return this.methodProxy.invoke(this.target, this.arguments);
|
||||
}
|
||||
return super.invokeJoinpoint();
|
||||
}
|
||||
|
||||
static boolean isMethodProxyCompatible(Method method) {
|
||||
return (Modifier.isPublic(method.getModifiers()) &&
|
||||
method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
|
||||
!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method));
|
||||
}
|
||||
|
||||
static void logFastClassGenerationFailure(Method method) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to generate CGLIB fast class for method: " + method);
|
||||
else {
|
||||
return super.invokeJoinpoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -910,14 +872,15 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
return AOP_PROXY;
|
||||
}
|
||||
Method key = method;
|
||||
// Check to see if we have fixed interceptor to serve this method.
|
||||
// Else use the AOP_PROXY.
|
||||
if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(method)) {
|
||||
if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Method has advice and optimizations are enabled: " + method);
|
||||
}
|
||||
// We know that we are optimizing so we can use the FixedStaticChainInterceptors.
|
||||
int index = this.fixedInterceptorMap.get(method);
|
||||
int index = this.fixedInterceptorMap.get(key);
|
||||
return (index + this.fixedInterceptorOffset);
|
||||
}
|
||||
else {
|
||||
@@ -996,11 +959,11 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean equalsAdviceClasses(Advisor a, Advisor b) {
|
||||
private boolean equalsAdviceClasses(Advisor a, Advisor b) {
|
||||
return (a.getAdvice().getClass() == b.getAdvice().getClass());
|
||||
}
|
||||
|
||||
private static boolean equalsPointcuts(Advisor a, Advisor b) {
|
||||
private boolean equalsPointcuts(Advisor a, Advisor b) {
|
||||
// If only one of the advisor (but not both) is PointcutAdvisor, then it is a mismatch.
|
||||
// Takes care of the situations where an IntroductionAdvisor is used (see SPR-3959).
|
||||
return (!(a instanceof PointcutAdvisor) ||
|
||||
|
||||
+2
-4
@@ -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.
|
||||
@@ -43,11 +43,9 @@ import org.springframework.aop.SpringProxy;
|
||||
* @see AdvisedSupport#setProxyTargetClass
|
||||
* @see AdvisedSupport#setInterfaces
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7930414337282325166L;
|
||||
|
||||
|
||||
@Override
|
||||
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
|
||||
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
|
||||
|
||||
@@ -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.
|
||||
@@ -21,7 +21,9 @@ import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.aopalliance.intercept.Interceptor;
|
||||
@@ -340,8 +342,11 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
// an independent instance of the configuration.
|
||||
// In this case, no proxy will have an instance of this object's configuration,
|
||||
// but will have an independent copy.
|
||||
ProxyCreatorSupport copy = new ProxyCreatorSupport(getAopProxyFactory());
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Creating copy of prototype ProxyFactoryBean config: " + this);
|
||||
}
|
||||
|
||||
ProxyCreatorSupport copy = new ProxyCreatorSupport(getAopProxyFactory());
|
||||
// The copy needs a fresh advisor chain, and a fresh TargetSource.
|
||||
TargetSource targetSource = freshTargetSource();
|
||||
copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain());
|
||||
@@ -354,6 +359,9 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
}
|
||||
copy.setFrozen(this.freezeProxy);
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Using ProxyCreatorSupport copy: " + copy);
|
||||
}
|
||||
return getProxy(copy.createAopProxy());
|
||||
}
|
||||
|
||||
@@ -421,7 +429,11 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
* are unaffected by such changes.
|
||||
*/
|
||||
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
|
||||
if (!this.advisorChainInitialized && !ObjectUtils.isEmpty(this.interceptorNames)) {
|
||||
if (this.advisorChainInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
|
||||
if (this.beanFactory == null) {
|
||||
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
|
||||
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
|
||||
@@ -435,12 +447,16 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
|
||||
// Materialize interceptor chain from bean names.
|
||||
for (String name : this.interceptorNames) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Configuring advisor or advice '" + name + "'");
|
||||
}
|
||||
|
||||
if (name.endsWith(GLOBAL_SUFFIX)) {
|
||||
if (!(this.beanFactory instanceof ListableBeanFactory)) {
|
||||
throw new AopConfigException(
|
||||
"Can only use global advisors or interceptors with a ListableBeanFactory");
|
||||
}
|
||||
addGlobalAdvisors((ListableBeanFactory) this.beanFactory,
|
||||
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
|
||||
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
|
||||
}
|
||||
|
||||
@@ -457,12 +473,12 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
|
||||
advice = new PrototypePlaceholderAdvisor(name);
|
||||
}
|
||||
addAdvisorOnChainCreation(advice);
|
||||
addAdvisorOnChainCreation(advice, name);
|
||||
}
|
||||
}
|
||||
|
||||
this.advisorChainInitialized = true;
|
||||
}
|
||||
|
||||
this.advisorChainInitialized = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -480,10 +496,11 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Refreshing bean named '" + pa.getBeanName() + "'");
|
||||
}
|
||||
// Replace the placeholder with a fresh prototype instance resulting from a getBean lookup
|
||||
// Replace the placeholder with a fresh prototype instance resulting
|
||||
// from a getBean() lookup
|
||||
if (this.beanFactory == null) {
|
||||
throw new IllegalStateException("No BeanFactory available anymore (probably due to " +
|
||||
"serialization) - cannot resolve prototype advisor '" + pa.getBeanName() + "'");
|
||||
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
|
||||
"- cannot resolve prototype advisor '" + pa.getBeanName() + "'");
|
||||
}
|
||||
Object bean = this.beanFactory.getBean(pa.getBeanName());
|
||||
Advisor refreshedAdvisor = namedBeanToAdvisor(bean);
|
||||
@@ -500,26 +517,28 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
/**
|
||||
* Add all global interceptors and pointcuts.
|
||||
*/
|
||||
private void addGlobalAdvisors(ListableBeanFactory beanFactory, String prefix) {
|
||||
private void addGlobalAdvisor(ListableBeanFactory beanFactory, String prefix) {
|
||||
String[] globalAdvisorNames =
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Advisor.class);
|
||||
String[] globalInterceptorNames =
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Interceptor.class);
|
||||
if (globalAdvisorNames.length > 0 || globalInterceptorNames.length > 0) {
|
||||
List<Object> beans = new ArrayList<>(globalAdvisorNames.length + globalInterceptorNames.length);
|
||||
for (String name : globalAdvisorNames) {
|
||||
if (name.startsWith(prefix)) {
|
||||
beans.add(beanFactory.getBean(name));
|
||||
}
|
||||
}
|
||||
for (String name : globalInterceptorNames) {
|
||||
if (name.startsWith(prefix)) {
|
||||
beans.add(beanFactory.getBean(name));
|
||||
}
|
||||
}
|
||||
AnnotationAwareOrderComparator.sort(beans);
|
||||
for (Object bean : beans) {
|
||||
addAdvisorOnChainCreation(bean);
|
||||
List<Object> beans = new ArrayList<>(globalAdvisorNames.length + globalInterceptorNames.length);
|
||||
Map<Object, String> names = new HashMap<>(beans.size());
|
||||
for (String name : globalAdvisorNames) {
|
||||
Object bean = beanFactory.getBean(name);
|
||||
beans.add(bean);
|
||||
names.put(bean, name);
|
||||
}
|
||||
for (String name : globalInterceptorNames) {
|
||||
Object bean = beanFactory.getBean(name);
|
||||
beans.add(bean);
|
||||
names.put(bean, name);
|
||||
}
|
||||
AnnotationAwareOrderComparator.sort(beans);
|
||||
for (Object bean : beans) {
|
||||
String name = names.get(bean);
|
||||
if (name.startsWith(prefix)) {
|
||||
addAdvisorOnChainCreation(bean, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -530,11 +549,17 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
* Because of these three possibilities, we can't type the signature
|
||||
* more strongly.
|
||||
* @param next advice, advisor or target object
|
||||
* @param name bean name from which we obtained this object in our owning
|
||||
* bean factory
|
||||
*/
|
||||
private void addAdvisorOnChainCreation(Object next) {
|
||||
private void addAdvisorOnChainCreation(Object next, String name) {
|
||||
// We need to convert to an Advisor if necessary so that our source reference
|
||||
// matches what we find from superclass interceptors.
|
||||
addAdvisor(namedBeanToAdvisor(next));
|
||||
Advisor advisor = namedBeanToAdvisor(next);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Adding advisor with name '" + name + "'");
|
||||
}
|
||||
addAdvisor(advisor);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -545,7 +570,9 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
*/
|
||||
private TargetSource freshTargetSource() {
|
||||
if (this.targetName == null) {
|
||||
// Not refreshing target: bean name not specified in 'interceptorNames'
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Not refreshing target: Bean name not specified in 'interceptorNames'.");
|
||||
}
|
||||
return this.targetSource;
|
||||
}
|
||||
else {
|
||||
@@ -573,8 +600,8 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
// We expected this to be an Advisor or Advice,
|
||||
// but it wasn't. This is a configuration error.
|
||||
throw new AopConfigException("Unknown advisor type " + next.getClass() +
|
||||
"; can only include Advisor or Advice type beans in interceptorNames chain " +
|
||||
"except for last entry which may also be target instance or TargetSource", ex);
|
||||
"; Can only include Advisor or Advice type beans in interceptorNames chain except for last entry, " +
|
||||
"which may also be target or TargetSource", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,7 +612,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
protected void adviceChanged() {
|
||||
super.adviceChanged();
|
||||
if (this.singleton) {
|
||||
logger.debug("Advice has changed; re-caching singleton instance");
|
||||
logger.debug("Advice has changed; recaching singleton instance");
|
||||
synchronized (this) {
|
||||
this.singletonInstance = null;
|
||||
}
|
||||
|
||||
+4
-4
@@ -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.
|
||||
@@ -26,9 +26,9 @@ import org.springframework.aop.MethodBeforeAdvice;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Interceptor to wrap a {@link MethodBeforeAdvice}.
|
||||
* <p>Used internally by the AOP framework; application developers should not
|
||||
* need to use this class directly.
|
||||
* Interceptor to wrap am {@link org.springframework.aop.MethodBeforeAdvice}.
|
||||
* Used internally by the AOP framework; application developers should not need
|
||||
* to use this class directly.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see AfterReturningAdviceInterceptor
|
||||
|
||||
+5
-7
@@ -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,13 +36,11 @@ import org.springframework.util.Assert;
|
||||
* also override the inherited {@link #shouldSkip} method to exclude certain
|
||||
* objects from auto-proxying.
|
||||
*
|
||||
* <p>Advisors or advices requiring ordering should be annotated with
|
||||
* {@link org.springframework.core.annotation.Order @Order} or implement the
|
||||
* <p>Advisors or advices requiring ordering should implement the
|
||||
* {@link org.springframework.core.Ordered} interface. This class sorts
|
||||
* advisors using the {@link AnnotationAwareOrderComparator}. Advisors that are
|
||||
* not annotated with {@code @Order} or don't implement the {@code Ordered}
|
||||
* interface will be considered as unordered; they will appear at the end of the
|
||||
* advisor chain in an undefined order.
|
||||
* Advisors by Ordered order value. Advisors that don't implement the
|
||||
* Ordered interface will be considered as unordered; they will appear
|
||||
* at the end of the advisor chain in undefined order.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+3
-17
@@ -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.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.aop.framework.autoproxy;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -450,17 +449,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.copyFrom(this);
|
||||
|
||||
if (proxyFactory.isProxyTargetClass()) {
|
||||
// Explicit handling of JDK proxy targets (for introduction advice scenarios)
|
||||
if (Proxy.isProxyClass(beanClass)) {
|
||||
// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
|
||||
for (Class<?> ifc : beanClass.getInterfaces()) {
|
||||
proxyFactory.addInterface(ifc);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No proxyTargetClass flag enforced, let's apply our default checks...
|
||||
if (!proxyFactory.isProxyTargetClass()) {
|
||||
if (shouldProxyTargetClass(beanClass, beanName)) {
|
||||
proxyFactory.setProxyTargetClass(true);
|
||||
}
|
||||
@@ -524,10 +513,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
|
||||
List<Object> allInterceptors = new ArrayList<>();
|
||||
if (specificInterceptors != null) {
|
||||
if (specificInterceptors.length > 0) {
|
||||
// specificInterceptors may equals PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS
|
||||
allInterceptors.addAll(Arrays.asList(specificInterceptors));
|
||||
}
|
||||
allInterceptors.addAll(Arrays.asList(specificInterceptors));
|
||||
if (commonInterceptors.length > 0) {
|
||||
if (this.applyCommonInterceptorsFirst) {
|
||||
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
|
||||
|
||||
+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.
|
||||
@@ -103,8 +103,7 @@ public abstract class AbstractMonitoringInterceptor extends AbstractTraceInterce
|
||||
if (this.logTargetClassInvocation && clazz.isInstance(invocation.getThis())) {
|
||||
clazz = invocation.getThis().getClass();
|
||||
}
|
||||
String className = clazz.getName();
|
||||
return getPrefix() + className + '.' + method.getName() + getSuffix();
|
||||
return getPrefix() + clazz.getName() + '.' + method.getName() + getSuffix();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -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.
|
||||
@@ -147,7 +147,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
/**
|
||||
* The {@code Pattern} used to match placeholders.
|
||||
*/
|
||||
private static final Pattern PATTERN = Pattern.compile("\\$\\[\\p{Alpha}+]");
|
||||
private static final Pattern PATTERN = Pattern.compile("\\$\\[\\p{Alpha}+\\]");
|
||||
|
||||
/**
|
||||
* The {@code Set} of allowed placeholders.
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ public abstract class AbstractExpressionPointcut implements ExpressionPointcut,
|
||||
* Called when a new pointcut expression is set.
|
||||
* The expression should be parsed at this point if possible.
|
||||
* <p>This implementation is empty.
|
||||
* @param expression the expression to set
|
||||
* @param expression expression to set
|
||||
* @throws IllegalArgumentException if the expression is invalid
|
||||
* @see #setExpression
|
||||
*/
|
||||
|
||||
+2
-3
@@ -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.
|
||||
@@ -71,8 +71,7 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
|
||||
if (introductionInfo != null) {
|
||||
Class<?>[] introducedInterfaces = introductionInfo.getInterfaces();
|
||||
if (introducedInterfaces.length == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"IntroductionInfo defines no interfaces to introduce: " + introductionInfo);
|
||||
throw new IllegalArgumentException("IntroductionAdviceSupport implements no interfaces");
|
||||
}
|
||||
for (Class<?> ifc : introducedInterfaces) {
|
||||
addInterface(ifc);
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut impleme
|
||||
* before a proxy is used.
|
||||
* <p><b>NB:</b> This method does not work after the proxy is in
|
||||
* use, as advice chains will be cached.
|
||||
* @param name the name of the additional method that will match
|
||||
* @param name name of the additional method that will match
|
||||
* @return this pointcut to allow for multiple additions in one line
|
||||
*/
|
||||
public NameMatchMethodPointcut addMethodName(String name) {
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ public class NameMatchMethodPointcutAdvisor extends AbstractGenericPointcutAdvis
|
||||
* Add another eligible method name, in addition to those already named.
|
||||
* Like the set methods, this method is for use when configuring proxies,
|
||||
* before a proxy is used.
|
||||
* @param name the name of the additional method that will match
|
||||
* @param name name of the additional method that will match
|
||||
* @return this pointcut to allow for multiple additions in one line
|
||||
* @see NameMatchMethodPointcut#addMethodName
|
||||
*/
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ public class TrickyAspectJPointcutExpressionTests {
|
||||
testAdvice(new DefaultPointcutAdvisor(pointcut, logAdvice), logAdvice, new TestServiceImpl(), "TestServiceImpl");
|
||||
|
||||
// Then try again with a different class loader on the target...
|
||||
SimpleThrowawayClassLoader loader = new SimpleThrowawayClassLoader(TestServiceImpl.class.getClassLoader());
|
||||
SimpleThrowawayClassLoader loader = new SimpleThrowawayClassLoader(new TestServiceImpl().getClass().getClassLoader());
|
||||
// Make sure the interface is loaded from the parent class loader
|
||||
loader.excludeClass(TestService.class.getName());
|
||||
loader.excludeClass(TestException.class.getName());
|
||||
|
||||
+123
-140
@@ -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.
|
||||
@@ -22,7 +22,6 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -64,16 +63,14 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
|
||||
/**
|
||||
* Abstract tests for {@link AspectJAdvisorFactory} implementations.
|
||||
*
|
||||
* <p>See subclasses for tests of concrete factories.
|
||||
* Abstract tests for AspectJAdvisorFactory.
|
||||
* See subclasses for tests of concrete factories.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
/**
|
||||
* To be overridden by concrete test subclasses.
|
||||
@@ -83,7 +80,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
|
||||
@Test
|
||||
void rejectsPerCflowAspect() {
|
||||
public void testRejectsPerCflowAspect() {
|
||||
assertThatExceptionOfType(AopConfigException.class).isThrownBy(() ->
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new PerCflowAspect(), "someBean")))
|
||||
@@ -91,7 +88,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsPerCflowBelowAspect() {
|
||||
public void testRejectsPerCflowBelowAspect() {
|
||||
assertThatExceptionOfType(AopConfigException.class).isThrownBy(() ->
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new PerCflowBelowAspect(), "someBean")))
|
||||
@@ -99,7 +96,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void perTargetAspect() throws SecurityException, NoSuchMethodException {
|
||||
public void testPerTargetAspect() throws SecurityException, NoSuchMethodException {
|
||||
TestBean target = new TestBean();
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
@@ -131,7 +128,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void multiplePerTargetAspects() throws SecurityException, NoSuchMethodException {
|
||||
public void testMultiplePerTargetAspects() throws SecurityException, NoSuchMethodException {
|
||||
TestBean target = new TestBean();
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
@@ -159,7 +156,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void multiplePerTargetAspectsWithOrderAnnotation() throws SecurityException, NoSuchMethodException {
|
||||
public void testMultiplePerTargetAspectsWithOrderAnnotation() throws SecurityException, NoSuchMethodException {
|
||||
TestBean target = new TestBean();
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
@@ -185,7 +182,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void perThisAspect() throws SecurityException, NoSuchMethodException {
|
||||
public void testPerThisAspect() throws SecurityException, NoSuchMethodException {
|
||||
TestBean target = new TestBean();
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
@@ -221,7 +218,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void perTypeWithinAspect() throws SecurityException, NoSuchMethodException {
|
||||
public void testPerTypeWithinAspect() throws SecurityException, NoSuchMethodException {
|
||||
TestBean target = new TestBean();
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
@@ -262,22 +259,22 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void namedPointcutAspectWithFQN() {
|
||||
namedPointcuts(new NamedPointcutAspectWithFQN());
|
||||
public void testNamedPointcutAspectWithFQN() {
|
||||
testNamedPointcuts(new NamedPointcutAspectWithFQN());
|
||||
}
|
||||
|
||||
@Test
|
||||
void namedPointcutAspectWithoutFQN() {
|
||||
namedPointcuts(new NamedPointcutAspectWithoutFQN());
|
||||
public void testNamedPointcutAspectWithoutFQN() {
|
||||
testNamedPointcuts(new NamedPointcutAspectWithoutFQN());
|
||||
}
|
||||
|
||||
@Test
|
||||
void namedPointcutFromAspectLibrary() {
|
||||
namedPointcuts(new NamedPointcutAspectFromLibrary());
|
||||
public void testNamedPointcutFromAspectLibrary() {
|
||||
testNamedPointcuts(new NamedPointcutAspectFromLibrary());
|
||||
}
|
||||
|
||||
@Test
|
||||
void namedPointcutFromAspectLibraryWithBinding() {
|
||||
public void testNamedPointcutFromAspectLibraryWithBinding() {
|
||||
TestBean target = new TestBean();
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(
|
||||
@@ -288,7 +285,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
assertThat(target.getAge()).isEqualTo(20);
|
||||
}
|
||||
|
||||
private void namedPointcuts(Object aspectInstance) {
|
||||
private void testNamedPointcuts(Object aspectInstance) {
|
||||
TestBean target = new TestBean();
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
@@ -300,7 +297,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void bindingWithSingleArg() {
|
||||
public void testBindingWithSingleArg() {
|
||||
TestBean target = new TestBean();
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(
|
||||
@@ -312,7 +309,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void bindingWithMultipleArgsDifferentlyOrdered() {
|
||||
public void testBindingWithMultipleArgsDifferentlyOrdered() {
|
||||
ManyValuedArgs target = new ManyValuedArgs();
|
||||
ManyValuedArgs mva = (ManyValuedArgs) createProxy(target,
|
||||
getFixture().getAdvisors(
|
||||
@@ -332,7 +329,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
* In this case the introduction will be made.
|
||||
*/
|
||||
@Test
|
||||
void introductionOnTargetNotImplementingInterface() {
|
||||
public void testIntroductionOnTargetNotImplementingInterface() {
|
||||
NotLockable notLockableTarget = new NotLockable();
|
||||
assertThat(notLockableTarget instanceof Lockable).isFalse();
|
||||
NotLockable notLockable1 = (NotLockable) createProxy(notLockableTarget,
|
||||
@@ -361,7 +358,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void introductionAdvisorExcludedFromTargetImplementingInterface() {
|
||||
public void testIntroductionAdvisorExcludedFromTargetImplementingInterface() {
|
||||
assertThat(AopUtils.findAdvisorsThatCanApply(
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
@@ -371,7 +368,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void introductionOnTargetImplementingInterface() {
|
||||
public void testIntroductionOnTargetImplementingInterface() {
|
||||
CannotBeUnlocked target = new CannotBeUnlocked();
|
||||
Lockable proxy = (Lockable) createProxy(target,
|
||||
// Ensure that we exclude
|
||||
@@ -391,7 +388,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void introductionOnTargetExcludedByTypePattern() {
|
||||
public void testIntroductionOnTargetExcludedByTypePattern() {
|
||||
LinkedList<Object> target = new LinkedList<>();
|
||||
List<?> proxy = (List<?>) createProxy(target,
|
||||
AopUtils.findAdvisorsThatCanApply(
|
||||
@@ -403,7 +400,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void introductionBasedOnAnnotationMatch_SPR5307() {
|
||||
public void testIntroductionBasedOnAnnotationMatch_SPR5307() {
|
||||
AnnotatedTarget target = new AnnotatedTargetImpl();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeAnnotatedTypeModifiable(), "someBean"));
|
||||
@@ -417,7 +414,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
// TODO: Why does this test fail? It hasn't been run before, so it maybe never actually passed...
|
||||
@Test
|
||||
@Disabled
|
||||
void introductionWithArgumentBinding() {
|
||||
public void testIntroductionWithArgumentBinding() {
|
||||
TestBean target = new TestBean();
|
||||
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
@@ -451,11 +448,11 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void aspectMethodThrowsExceptionLegalOnSignature() {
|
||||
public void testAspectMethodThrowsExceptionLegalOnSignature() {
|
||||
TestBean target = new TestBean();
|
||||
UnsupportedOperationException expectedException = new UnsupportedOperationException();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionThrowingAspect(expectedException), "someBean"));
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException), "someBean"));
|
||||
assertThat(advisors.size()).as("One advice method was found").isEqualTo(1);
|
||||
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(
|
||||
@@ -465,11 +462,11 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
// TODO document this behaviour.
|
||||
// Is it different AspectJ behaviour, at least for checked exceptions?
|
||||
@Test
|
||||
void aspectMethodThrowsExceptionIllegalOnSignature() {
|
||||
public void testAspectMethodThrowsExceptionIllegalOnSignature() {
|
||||
TestBean target = new TestBean();
|
||||
RemoteException expectedException = new RemoteException();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionThrowingAspect(expectedException), "someBean"));
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException), "someBean"));
|
||||
assertThat(advisors.size()).as("One advice method was found").isEqualTo(1);
|
||||
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
|
||||
assertThatExceptionOfType(UndeclaredThrowableException.class).isThrownBy(
|
||||
@@ -494,7 +491,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void twoAdvicesOnOneAspect() {
|
||||
public void testTwoAdvicesOnOneAspect() {
|
||||
TestBean target = new TestBean();
|
||||
TwoAdviceAspect twoAdviceAspect = new TwoAdviceAspect();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
@@ -509,23 +506,25 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void afterAdviceTypes() throws Exception {
|
||||
InvocationTrackingAspect aspect = new InvocationTrackingAspect();
|
||||
public void testAfterAdviceTypes() throws Exception {
|
||||
Echo target = new Echo();
|
||||
ExceptionHandling afterReturningAspect = new ExceptionHandling();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(aspect, "exceptionHandlingAspect"));
|
||||
Echo echo = (Echo) createProxy(new Echo(), advisors, Echo.class);
|
||||
|
||||
assertThat(aspect.invocations).isEmpty();
|
||||
assertThat(echo.echo(42)).isEqualTo(42);
|
||||
assertThat(aspect.invocations).containsExactly("around - start", "before", "after returning", "after", "around - end");
|
||||
|
||||
aspect.invocations.clear();
|
||||
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() -> echo.echo(new FileNotFoundException()));
|
||||
assertThat(aspect.invocations).containsExactly("around - start", "before", "after throwing", "after", "around - end");
|
||||
new SingletonMetadataAwareAspectInstanceFactory(afterReturningAspect, "someBean"));
|
||||
Echo echo = (Echo) createProxy(target, advisors, Echo.class);
|
||||
assertThat(afterReturningAspect.successCount).isEqualTo(0);
|
||||
assertThat(echo.echo("")).isEqualTo("");
|
||||
assertThat(afterReturningAspect.successCount).isEqualTo(1);
|
||||
assertThat(afterReturningAspect.failureCount).isEqualTo(0);
|
||||
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() ->
|
||||
echo.echo(new FileNotFoundException()));
|
||||
assertThat(afterReturningAspect.successCount).isEqualTo(1);
|
||||
assertThat(afterReturningAspect.failureCount).isEqualTo(1);
|
||||
assertThat(afterReturningAspect.afterCount).isEqualTo(afterReturningAspect.failureCount + afterReturningAspect.successCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
void failureWithoutExplicitDeclarePrecedence() {
|
||||
public void testFailureWithoutExplicitDeclarePrecedence() {
|
||||
TestBean target = new TestBean();
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory = new SingletonMetadataAwareAspectInstanceFactory(
|
||||
new NoDeclarePrecedenceShouldFail(), "someBean");
|
||||
@@ -535,7 +534,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void declarePrecedenceNotSupported() {
|
||||
public void testDeclarePrecedenceNotSupported() {
|
||||
TestBean target = new TestBean();
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> {
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory = new SingletonMetadataAwareAspectInstanceFactory(
|
||||
@@ -546,28 +545,28 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
|
||||
@Aspect("percflow(execution(* *(..)))")
|
||||
static class PerCflowAspect {
|
||||
public static class PerCflowAspect {
|
||||
}
|
||||
|
||||
|
||||
@Aspect("percflowbelow(execution(* *(..)))")
|
||||
static class PerCflowBelowAspect {
|
||||
public static class PerCflowBelowAspect {
|
||||
}
|
||||
|
||||
|
||||
@Aspect("pertarget(execution(* *.getSpouse()))")
|
||||
@Order(10)
|
||||
static class PerTargetAspectWithOrderAnnotation10 {
|
||||
public static class PerTargetAspectWithOrderAnnotation10 {
|
||||
|
||||
int count;
|
||||
public int count;
|
||||
|
||||
@Around("execution(int *.getAge())")
|
||||
int returnCountAsAge() {
|
||||
public int returnCountAsAge() {
|
||||
return count++;
|
||||
}
|
||||
|
||||
@Before("execution(void *.set*(int))")
|
||||
void countSetter() {
|
||||
public void countSetter() {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
@@ -575,34 +574,34 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Aspect("pertarget(execution(* *.getSpouse()))")
|
||||
@Order(5)
|
||||
static class PerTargetAspectWithOrderAnnotation5 {
|
||||
public static class PerTargetAspectWithOrderAnnotation5 {
|
||||
|
||||
int count;
|
||||
public int count;
|
||||
|
||||
@Around("execution(int *.getAge())")
|
||||
int returnCountAsAge() {
|
||||
public int returnCountAsAge() {
|
||||
return count++;
|
||||
}
|
||||
|
||||
@Before("execution(void *.set*(int))")
|
||||
void countSetter() {
|
||||
public void countSetter() {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Aspect("pertypewithin(org.springframework.beans.testfixture.beans.IOther+)")
|
||||
static class PerTypeWithinAspect {
|
||||
public static class PerTypeWithinAspect {
|
||||
|
||||
int count;
|
||||
public int count;
|
||||
|
||||
@Around("execution(int *.getAge())")
|
||||
int returnCountAsAge() {
|
||||
public int returnCountAsAge() {
|
||||
return count++;
|
||||
}
|
||||
|
||||
@Before("execution(void *.*(..))")
|
||||
void countAnythingVoid() {
|
||||
public void countAnythingVoid() {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
@@ -612,7 +611,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
private int count;
|
||||
|
||||
int getInstantiationCount() {
|
||||
public int getInstantiationCount() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
@@ -645,96 +644,97 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
|
||||
@Aspect
|
||||
static class NamedPointcutAspectWithFQN {
|
||||
public static class NamedPointcutAspectWithFQN {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private ITestBean fieldThatShouldBeIgnoredBySpringAtAspectJProcessing = new TestBean();
|
||||
|
||||
@Pointcut("execution(* getAge())")
|
||||
void getAge() {
|
||||
public void getAge() {
|
||||
}
|
||||
|
||||
@Around("org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactoryTests.NamedPointcutAspectWithFQN.getAge()")
|
||||
int changeReturnValue(ProceedingJoinPoint pjp) {
|
||||
public int changeReturnValue(ProceedingJoinPoint pjp) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
static class NamedPointcutAspectWithoutFQN {
|
||||
public static class NamedPointcutAspectWithoutFQN {
|
||||
|
||||
@Pointcut("execution(* getAge())")
|
||||
void getAge() {
|
||||
public void getAge() {
|
||||
}
|
||||
|
||||
@Around("getAge()")
|
||||
int changeReturnValue(ProceedingJoinPoint pjp) {
|
||||
public int changeReturnValue(ProceedingJoinPoint pjp) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
static class NamedPointcutAspectFromLibrary {
|
||||
public static class NamedPointcutAspectFromLibrary {
|
||||
|
||||
@Around("org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactoryTests.Library.propertyAccess()")
|
||||
int changeReturnType(ProceedingJoinPoint pjp) {
|
||||
public int changeReturnType(ProceedingJoinPoint pjp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Around(value="org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactoryTests.Library.integerArgOperation(x)", argNames="x")
|
||||
void doubleArg(ProceedingJoinPoint pjp, int x) throws Throwable {
|
||||
public void doubleArg(ProceedingJoinPoint pjp, int x) throws Throwable {
|
||||
pjp.proceed(new Object[] {x*2});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
static class Library {
|
||||
public static class Library {
|
||||
|
||||
@Pointcut("execution(!void get*())")
|
||||
void propertyAccess() {}
|
||||
public void propertyAccess() {}
|
||||
|
||||
@Pointcut("execution(* *(..)) && args(i)")
|
||||
void integerArgOperation(int i) {}
|
||||
public void integerArgOperation(int i) {}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
static class NamedPointcutAspectFromLibraryWithBinding {
|
||||
public static class NamedPointcutAspectFromLibraryWithBinding {
|
||||
|
||||
@Around(value="org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactoryTests.Library.integerArgOperation(x)", argNames="x")
|
||||
void doubleArg(ProceedingJoinPoint pjp, int x) throws Throwable {
|
||||
public void doubleArg(ProceedingJoinPoint pjp, int x) throws Throwable {
|
||||
pjp.proceed(new Object[] {x*2});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
static class BindingAspectWithSingleArg {
|
||||
public static class BindingAspectWithSingleArg {
|
||||
|
||||
@Pointcut(value="args(a)", argNames="a")
|
||||
void setAge(int a) {}
|
||||
public void setAge(int a) {}
|
||||
|
||||
@Around(value="setAge(age)",argNames="age")
|
||||
// @ArgNames({"age"}) // AMC needs more work here? ignoring pjp arg... ok??
|
||||
// argNames should be supported in Around as it is in Pointcut
|
||||
void changeReturnType(ProceedingJoinPoint pjp, int age) throws Throwable {
|
||||
public void changeReturnType(ProceedingJoinPoint pjp, int age) throws Throwable {
|
||||
pjp.proceed(new Object[] {age*2});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
static class ManyValuedArgs {
|
||||
public static class ManyValuedArgs {
|
||||
|
||||
String mungeArgs(String a, int b, int c, String d, StringBuffer e) {
|
||||
public String mungeArgs(String a, int b, int c, String d, StringBuffer e) {
|
||||
return a + b + c + d + e;
|
||||
}
|
||||
|
||||
@Around(value="execution(String mungeArgs(..)) && args(a, b, c, d, e)", argNames="b,c,d,e,a")
|
||||
String reverseAdvice(ProceedingJoinPoint pjp, int b, int c, String d, StringBuffer e, String a) throws Throwable {
|
||||
public String reverseAdvice(ProceedingJoinPoint pjp, int b, int c, String d, StringBuffer e, String a) throws Throwable {
|
||||
assertThat(pjp.proceed()).isEqualTo(a + b+ c+ d+ e);
|
||||
return a + b + c + d + e;
|
||||
}
|
||||
@@ -742,24 +742,24 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
|
||||
@Aspect
|
||||
static class ExceptionThrowingAspect {
|
||||
public static class ExceptionAspect {
|
||||
|
||||
private final Exception ex;
|
||||
|
||||
ExceptionThrowingAspect(Exception ex) {
|
||||
public ExceptionAspect(Exception ex) {
|
||||
this.ex = ex;
|
||||
}
|
||||
|
||||
@Before("execution(* getAge())")
|
||||
void throwException() throws Exception {
|
||||
public void throwException() throws Exception {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class Echo {
|
||||
public static class Echo {
|
||||
|
||||
Object echo(Object o) throws Exception {
|
||||
public Object echo(Object o) throws Exception {
|
||||
if (o instanceof Exception) {
|
||||
throw (Exception) o;
|
||||
}
|
||||
@@ -769,62 +769,45 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
|
||||
@Aspect
|
||||
private static class InvocationTrackingAspect {
|
||||
public static class ExceptionHandling {
|
||||
|
||||
List<String> invocations = new ArrayList<>();
|
||||
public int successCount;
|
||||
|
||||
public int failureCount;
|
||||
|
||||
@Pointcut("execution(* echo(*))")
|
||||
void echo() {
|
||||
public int afterCount;
|
||||
|
||||
@AfterReturning("execution(* echo(*))")
|
||||
public void succeeded() {
|
||||
++successCount;
|
||||
}
|
||||
|
||||
@Around("echo()")
|
||||
Object around(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
invocations.add("around - start");
|
||||
try {
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
finally {
|
||||
invocations.add("around - end");
|
||||
}
|
||||
@AfterThrowing("execution(* echo(*))")
|
||||
public void failed() {
|
||||
++failureCount;
|
||||
}
|
||||
|
||||
@Before("echo()")
|
||||
void before() {
|
||||
invocations.add("before");
|
||||
}
|
||||
|
||||
@AfterReturning("echo()")
|
||||
void afterReturning() {
|
||||
invocations.add("after returning");
|
||||
}
|
||||
|
||||
@AfterThrowing("echo()")
|
||||
void afterThrowing() {
|
||||
invocations.add("after throwing");
|
||||
}
|
||||
|
||||
@After("echo()")
|
||||
void after() {
|
||||
invocations.add("after");
|
||||
@After("execution(* echo(*))")
|
||||
public void invoked() {
|
||||
++afterCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
static class NoDeclarePrecedenceShouldFail {
|
||||
public static class NoDeclarePrecedenceShouldFail {
|
||||
|
||||
@Pointcut("execution(int *.getAge())")
|
||||
void getAge() {
|
||||
public void getAge() {
|
||||
}
|
||||
|
||||
@Before("getAge()")
|
||||
void blowUpButDoesntMatterBecauseAroundAdviceWontLetThisBeInvoked() {
|
||||
public void blowUpButDoesntMatterBecauseAroundAdviceWontLetThisBeInvoked() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Around("getAge()")
|
||||
int preventExecution(ProceedingJoinPoint pjp) {
|
||||
public int preventExecution(ProceedingJoinPoint pjp) {
|
||||
return 666;
|
||||
}
|
||||
}
|
||||
@@ -832,19 +815,19 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Aspect
|
||||
@DeclarePrecedence("test..*")
|
||||
static class DeclarePrecedenceShouldSucceed {
|
||||
public static class DeclarePrecedenceShouldSucceed {
|
||||
|
||||
@Pointcut("execution(int *.getAge())")
|
||||
void getAge() {
|
||||
public void getAge() {
|
||||
}
|
||||
|
||||
@Before("getAge()")
|
||||
void blowUpButDoesntMatterBecauseAroundAdviceWontLetThisBeInvoked() {
|
||||
public void blowUpButDoesntMatterBecauseAroundAdviceWontLetThisBeInvoked() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Around("getAge()")
|
||||
int preventExecution(ProceedingJoinPoint pjp) {
|
||||
public int preventExecution(ProceedingJoinPoint pjp) {
|
||||
return 666;
|
||||
}
|
||||
}
|
||||
@@ -862,12 +845,12 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Aspect
|
||||
abstract class AbstractMakeModifiable {
|
||||
|
||||
interface MutableModifiable extends Modifiable {
|
||||
public interface MutableModifiable extends Modifiable {
|
||||
|
||||
void markDirty();
|
||||
}
|
||||
|
||||
static class ModifiableImpl implements MutableModifiable {
|
||||
public static class ModifiableImpl implements MutableModifiable {
|
||||
|
||||
private boolean modified;
|
||||
|
||||
@@ -888,7 +871,7 @@ abstract class AbstractMakeModifiable {
|
||||
}
|
||||
|
||||
@Before(value="execution(void set*(*)) && this(modifiable) && args(newValue)", argNames="modifiable,newValue")
|
||||
void recordModificationIfSetterArgumentDiffersFromOldValue(
|
||||
public void recordModificationIfSetterArgumentDiffersFromOldValue(
|
||||
JoinPoint jp, MutableModifiable mixin, Object newValue) {
|
||||
|
||||
/*
|
||||
@@ -950,7 +933,7 @@ class MakeITestBeanModifiable extends AbstractMakeModifiable {
|
||||
|
||||
@DeclareParents(value = "org.springframework.beans.testfixture.beans.ITestBean+",
|
||||
defaultImpl=ModifiableImpl.class)
|
||||
static MutableModifiable mixin;
|
||||
public static MutableModifiable mixin;
|
||||
|
||||
}
|
||||
|
||||
@@ -965,7 +948,7 @@ class MakeAnnotatedTypeModifiable extends AbstractMakeModifiable {
|
||||
|
||||
@DeclareParents(value = "(@org.springframework.aop.aspectj.annotation.Measured *)",
|
||||
defaultImpl = DefaultLockable.class)
|
||||
static Lockable mixin;
|
||||
public static Lockable mixin;
|
||||
|
||||
}
|
||||
|
||||
@@ -977,10 +960,10 @@ class MakeAnnotatedTypeModifiable extends AbstractMakeModifiable {
|
||||
class MakeLockable {
|
||||
|
||||
@DeclareParents(value = "org.springframework..*", defaultImpl = DefaultLockable.class)
|
||||
static Lockable mixin;
|
||||
public static Lockable mixin;
|
||||
|
||||
@Before(value="execution(void set*(*)) && this(mixin)", argNames="mixin")
|
||||
void checkNotLocked( Lockable mixin) {
|
||||
public void checkNotLocked( Lockable mixin) {
|
||||
// Can also obtain the mixin (this) this way
|
||||
//Lockable mixin = (Lockable) jp.getThis();
|
||||
if (mixin.locked()) {
|
||||
@@ -1049,11 +1032,11 @@ class NotLockable {
|
||||
|
||||
private int intValue;
|
||||
|
||||
int getIntValue() {
|
||||
public int getIntValue() {
|
||||
return intValue;
|
||||
}
|
||||
|
||||
void setIntValue(int intValue) {
|
||||
public void setIntValue(int intValue) {
|
||||
this.intValue = intValue;
|
||||
}
|
||||
|
||||
@@ -1063,19 +1046,19 @@ class NotLockable {
|
||||
@Aspect("perthis(execution(* *.getSpouse()))")
|
||||
class PerThisAspect {
|
||||
|
||||
int count;
|
||||
public int count;
|
||||
|
||||
// Just to check that this doesn't cause problems with introduction processing
|
||||
@SuppressWarnings("unused")
|
||||
private ITestBean fieldThatShouldBeIgnoredBySpringAtAspectJProcessing = new TestBean();
|
||||
|
||||
@Around("execution(int *.getAge())")
|
||||
int returnCountAsAge() {
|
||||
public int returnCountAsAge() {
|
||||
return count++;
|
||||
}
|
||||
|
||||
@Before("execution(void *.set*(int))")
|
||||
void countSetter() {
|
||||
public void countSetter() {
|
||||
++count;
|
||||
}
|
||||
|
||||
|
||||
+2
-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.
|
||||
@@ -22,7 +22,6 @@ import test.aop.PerTargetAspect;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcutTests;
|
||||
import org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactoryTests.ExceptionThrowingAspect;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
|
||||
@@ -45,7 +44,7 @@ public class AspectJPointcutAdvisorTests {
|
||||
|
||||
InstantiationModelAwarePointcutAdvisorImpl ajpa = new InstantiationModelAwarePointcutAdvisorImpl(
|
||||
ajexp, TestBean.class.getMethod("getAge"), af,
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionThrowingAspect(null), "someBean"),
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new AbstractAspectJAdvisorFactoryTests.ExceptionAspect(null), "someBean"),
|
||||
1, "someBean");
|
||||
|
||||
assertThat(ajpa.getAspectMetadata().getPerClausePointcut()).isSameAs(Pointcut.TRUE);
|
||||
|
||||
+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.
|
||||
@@ -22,7 +22,7 @@ import test.aop.PerTargetAspect;
|
||||
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactoryTests.ExceptionThrowingAspect;
|
||||
import org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactoryTests.ExceptionAspect;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
@@ -42,7 +42,7 @@ class AspectMetadataTests {
|
||||
|
||||
@Test
|
||||
void singletonAspect() {
|
||||
AspectMetadata am = new AspectMetadata(ExceptionThrowingAspect.class, "someBean");
|
||||
AspectMetadata am = new AspectMetadata(ExceptionAspect.class, "someBean");
|
||||
assertThat(am.isPerThisOrPerTarget()).isFalse();
|
||||
assertThat(am.getPerClausePointcut()).isSameAs(Pointcut.TRUE);
|
||||
assertThat(am.getAjType().getPerClause().getKind()).isEqualTo(PerClauseKind.SINGLETON);
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2012 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,14 +17,13 @@
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
/**
|
||||
* Tests for {@link ReflectiveAspectJAdvisorFactory}.
|
||||
*
|
||||
* <p>Tests are inherited: we only set the test fixture here.
|
||||
* Tests for ReflectiveAtAspectJAdvisorFactory.
|
||||
* Tests are inherited: we only set the test fixture here.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
*/
|
||||
class ReflectiveAspectJAdvisorFactoryTests extends AbstractAspectJAdvisorFactoryTests {
|
||||
public class ReflectiveAspectJAdvisorFactoryTests extends AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Override
|
||||
protected AspectJAdvisorFactory getFixture() {
|
||||
|
||||
@@ -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.
|
||||
@@ -183,7 +183,7 @@ public class ProxyFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetsAllInterfaces() {
|
||||
public void testGetsAllInterfaces() throws Exception {
|
||||
// Extend to get new interface
|
||||
class TestBeanSubclass extends TestBean implements Comparable<Object> {
|
||||
@Override
|
||||
|
||||
@@ -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.
|
||||
@@ -83,12 +83,12 @@ public class MethodMatchersTests {
|
||||
MethodMatcher intersection = MethodMatchers.intersection(mm1, mm2);
|
||||
assertThat(intersection.isRuntime()).as("Intersection is a dynamic matcher").isTrue();
|
||||
assertThat(intersection.matches(ITESTBEAN_SETAGE, TestBean.class)).as("2Matched setAge method").isTrue();
|
||||
assertThat(intersection.matches(ITESTBEAN_SETAGE, TestBean.class, 5)).as("3Matched setAge method").isTrue();
|
||||
assertThat(intersection.matches(ITESTBEAN_SETAGE, TestBean.class, new Integer(5))).as("3Matched setAge method").isTrue();
|
||||
// Knock out dynamic part
|
||||
intersection = MethodMatchers.intersection(intersection, new TestDynamicMethodMatcherWhichDoesNotMatch());
|
||||
assertThat(intersection.isRuntime()).as("Intersection is a dynamic matcher").isTrue();
|
||||
assertThat(intersection.matches(ITESTBEAN_SETAGE, TestBean.class)).as("2Matched setAge method").isTrue();
|
||||
assertThat(intersection.matches(ITESTBEAN_SETAGE, TestBean.class, 5)).as("3 - not Matched setAge method").isFalse();
|
||||
assertThat(intersection.matches(ITESTBEAN_SETAGE, TestBean.class, new Integer(5))).as("3 - not Matched setAge method").isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -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.
|
||||
@@ -121,20 +121,20 @@ public class PointcutsTests {
|
||||
|
||||
@Test
|
||||
public void testTrue() {
|
||||
assertThat(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, 6)).isTrue();
|
||||
assertThat(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6))).isTrue();
|
||||
assertThat(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_GET_AGE, TestBean.class)).isTrue();
|
||||
assertThat(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_ABSQUATULATE, TestBean.class)).isTrue();
|
||||
assertThat(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, 6)).isTrue();
|
||||
assertThat(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6))).isTrue();
|
||||
assertThat(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_GET_AGE, TestBean.class)).isTrue();
|
||||
assertThat(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_ABSQUATULATE, TestBean.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatches() {
|
||||
assertThat(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, 6)).isTrue();
|
||||
assertThat(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6))).isTrue();
|
||||
assertThat(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_GET_AGE, TestBean.class)).isFalse();
|
||||
assertThat(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_ABSQUATULATE, TestBean.class)).isFalse();
|
||||
assertThat(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, 6)).isFalse();
|
||||
assertThat(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6))).isFalse();
|
||||
assertThat(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_GET_AGE, TestBean.class)).isTrue();
|
||||
assertThat(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_ABSQUATULATE, TestBean.class)).isFalse();
|
||||
}
|
||||
@@ -145,7 +145,7 @@ public class PointcutsTests {
|
||||
@Test
|
||||
public void testUnionOfSettersAndGetters() {
|
||||
Pointcut union = Pointcuts.union(allClassGetterPointcut, allClassSetterPointcut);
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, 6)).isTrue();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6))).isTrue();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class)).isTrue();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class)).isFalse();
|
||||
}
|
||||
@@ -153,7 +153,7 @@ public class PointcutsTests {
|
||||
@Test
|
||||
public void testUnionOfSpecificGetters() {
|
||||
Pointcut union = Pointcuts.union(allClassGetAgePointcut, allClassGetNamePointcut);
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, 6)).isFalse();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6))).isFalse();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class)).isTrue();
|
||||
assertThat(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_NAME, TestBean.class)).isFalse();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class)).isTrue();
|
||||
@@ -161,13 +161,13 @@ public class PointcutsTests {
|
||||
|
||||
// Union with all setters
|
||||
union = Pointcuts.union(union, allClassSetterPointcut);
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, 6)).isTrue();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6))).isTrue();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class)).isTrue();
|
||||
assertThat(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_NAME, TestBean.class)).isFalse();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class)).isTrue();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class)).isFalse();
|
||||
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, 6)).isTrue();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6))).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,16 +176,16 @@ public class PointcutsTests {
|
||||
*/
|
||||
@Test
|
||||
public void testUnionOfAllSettersAndSubclassSetters() {
|
||||
assertThat(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, 6)).isFalse();
|
||||
assertThat(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, MyTestBean.class, 6)).isTrue();
|
||||
assertThat(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6))).isFalse();
|
||||
assertThat(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, MyTestBean.class, new Integer(6))).isTrue();
|
||||
assertThat(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_GET_AGE, TestBean.class)).isFalse();
|
||||
|
||||
Pointcut union = Pointcuts.union(myTestBeanSetterPointcut, allClassGetterPointcut);
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class)).isTrue();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBean.class)).isTrue();
|
||||
// Still doesn't match superclass setter
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_SET_AGE, MyTestBean.class, 6)).isTrue();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, 6)).isFalse();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_SET_AGE, MyTestBean.class, new Integer(6))).isTrue();
|
||||
assertThat(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6))).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,7 +241,7 @@ public class PointcutsTests {
|
||||
@Test
|
||||
public void testSimpleIntersection() {
|
||||
Pointcut intersection = Pointcuts.intersection(allClassGetterPointcut, allClassSetterPointcut);
|
||||
assertThat(Pointcuts.matches(intersection, TEST_BEAN_SET_AGE, TestBean.class, 6)).isFalse();
|
||||
assertThat(Pointcuts.matches(intersection, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6))).isFalse();
|
||||
assertThat(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class)).isFalse();
|
||||
assertThat(Pointcuts.matches(intersection, TEST_BEAN_ABSQUATULATE, TestBean.class)).isFalse();
|
||||
}
|
||||
|
||||
+6
-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.
|
||||
@@ -25,7 +25,6 @@ import java.util.HashMap;
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MethodCounter implements Serializable {
|
||||
@@ -40,12 +39,15 @@ public class MethodCounter implements Serializable {
|
||||
}
|
||||
|
||||
protected void count(String methodName) {
|
||||
map.merge(methodName, 1, (n, m) -> n + 1);
|
||||
Integer i = map.get(methodName);
|
||||
i = (i != null) ? new Integer(i.intValue() + 1) : new Integer(1);
|
||||
map.put(methodName, i);
|
||||
++allCount;
|
||||
}
|
||||
|
||||
public int getCalls(String methodName) {
|
||||
return map.getOrDefault(methodName, 0);
|
||||
Integer i = map.get(methodName);
|
||||
return (i != null ? i.intValue() : 0);
|
||||
}
|
||||
|
||||
public int getCalls() {
|
||||
|
||||
@@ -11,6 +11,7 @@ sourceSets.test.java.srcDirs = files()
|
||||
aspectj.version = dependencyManagement.managedVersions['org.aspectj:aspectjweaver']
|
||||
|
||||
dependencies {
|
||||
aspect(project(":spring-orm"))
|
||||
compile("org.aspectj:aspectjweaver")
|
||||
compileOnly("org.aspectj:aspectjrt")
|
||||
optional(project(":spring-aop")) // for @Async support
|
||||
|
||||
+1
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -67,7 +67,6 @@ import java.io.Serializable;
|
||||
* @since 2.5.2
|
||||
*/
|
||||
public abstract aspect AbstractInterfaceDrivenDependencyInjectionAspect extends AbstractDependencyInjectionAspect {
|
||||
|
||||
/**
|
||||
* Select initialization join point as object construction
|
||||
*/
|
||||
|
||||
+2
-6
@@ -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.
|
||||
@@ -47,26 +47,22 @@ import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||
public aspect AnnotationBeanConfigurerAspect extends AbstractInterfaceDrivenDependencyInjectionAspect
|
||||
implements BeanFactoryAware, InitializingBean, DisposableBean {
|
||||
|
||||
private final BeanConfigurerSupport beanConfigurerSupport = new BeanConfigurerSupport();
|
||||
private BeanConfigurerSupport beanConfigurerSupport = new BeanConfigurerSupport();
|
||||
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanConfigurerSupport.setBeanWiringInfoResolver(new AnnotationBeanWiringInfoResolver());
|
||||
this.beanConfigurerSupport.setBeanFactory(beanFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
this.beanConfigurerSupport.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureBean(Object bean) {
|
||||
this.beanConfigurerSupport.configureBean(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
this.beanConfigurerSupport.destroy();
|
||||
}
|
||||
|
||||
+1
-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.
|
||||
@@ -37,7 +37,6 @@ import org.springframework.scheduling.config.TaskManagementConfigUtils;
|
||||
* @see org.springframework.scheduling.annotation.ProxyAsyncConfiguration
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class AspectJAsyncConfiguration extends AbstractAsyncConfiguration {
|
||||
|
||||
@Bean(name = TaskManagementConfigUtils.ASYNC_EXECUTION_ASPECT_BEAN_NAME)
|
||||
|
||||
+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")
|
||||
|
||||
+1
-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.
|
||||
@@ -36,7 +36,6 @@ import org.springframework.transaction.config.TransactionManagementConfigUtils;
|
||||
* @see TransactionManagementConfigurationSelector
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class AspectJJtaTransactionManagementConfiguration extends AspectJTransactionManagementConfiguration {
|
||||
|
||||
@Bean(name = TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_BEAN_NAME)
|
||||
|
||||
+1
-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.
|
||||
@@ -38,7 +38,6 @@ import org.springframework.transaction.config.TransactionManagementConfigUtils;
|
||||
* @see AspectJJtaTransactionManagementConfiguration
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class AspectJTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
|
||||
|
||||
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME)
|
||||
|
||||
+3
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,18 +22,13 @@ import org.springframework.contextsupport.testfixture.jcache.AbstractJCacheAnnot
|
||||
|
||||
/**
|
||||
* @author Stephane Nicoll
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public class JCacheAspectJNamespaceConfigTests extends AbstractJCacheAnnotationTests {
|
||||
|
||||
@Override
|
||||
protected ApplicationContext getApplicationContext() {
|
||||
GenericXmlApplicationContext context = new GenericXmlApplicationContext();
|
||||
// Disallow bean definition overriding to test https://github.com/spring-projects/spring-framework/pull/27499
|
||||
context.setAllowBeanDefinitionOverriding(false);
|
||||
context.load("/org/springframework/cache/config/annotation-jcache-aspectj.xml");
|
||||
context.refresh();
|
||||
return context;
|
||||
return new GenericXmlApplicationContext(
|
||||
"/org/springframework/cache/config/annotation-jcache-aspectj.xml");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ sourceSets {
|
||||
compileGroovy {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
options.compilerArgs += "-Werror"
|
||||
}
|
||||
|
||||
// This module also builds Kotlin code and the compileKotlin task naturally depends on
|
||||
|
||||
+10
-14
@@ -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.
|
||||
@@ -115,7 +115,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
|
||||
/**
|
||||
* Create a new accessor for the given object.
|
||||
* @param object the object wrapped by this accessor
|
||||
* @param object object wrapped by this accessor
|
||||
*/
|
||||
protected AbstractNestablePropertyAccessor(Object object) {
|
||||
registerDefaultEditors();
|
||||
@@ -134,7 +134,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
/**
|
||||
* Create a new accessor for the given object,
|
||||
* registering a nested path that the object is in.
|
||||
* @param object the object wrapped by this accessor
|
||||
* @param object object wrapped by this accessor
|
||||
* @param nestedPath the nested path of the object
|
||||
* @param rootObject the root object at the top of the path
|
||||
*/
|
||||
@@ -146,7 +146,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
/**
|
||||
* Create a new accessor for the given object,
|
||||
* registering a nested path that the object is in.
|
||||
* @param object the object wrapped by this accessor
|
||||
* @param object object wrapped by this accessor
|
||||
* @param nestedPath the nested path of the object
|
||||
* @param parent the containing accessor (must not be {@code null})
|
||||
*/
|
||||
@@ -305,10 +305,8 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
Class<?> componentType = propValue.getClass().getComponentType();
|
||||
Object newArray = Array.newInstance(componentType, arrayIndex + 1);
|
||||
System.arraycopy(propValue, 0, newArray, 0, length);
|
||||
int lastKeyIndex = tokens.canonicalName.lastIndexOf('[');
|
||||
String propName = tokens.canonicalName.substring(0, lastKeyIndex);
|
||||
setPropertyValue(propName, newArray);
|
||||
propValue = getPropertyValue(propName);
|
||||
setPropertyValue(tokens.actualName, newArray);
|
||||
propValue = getPropertyValue(tokens.actualName);
|
||||
}
|
||||
Array.set(propValue, arrayIndex, convertedValue);
|
||||
}
|
||||
@@ -424,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;
|
||||
@@ -742,7 +737,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
/**
|
||||
* Create a new nested property accessor instance.
|
||||
* Can be overridden in subclasses to create a PropertyAccessor subclass.
|
||||
* @param object the object wrapped by this PropertyAccessor
|
||||
* @param object object wrapped by this PropertyAccessor
|
||||
* @param nestedPath the nested path of the object
|
||||
* @return the nested PropertyAccessor instance
|
||||
*/
|
||||
@@ -811,6 +806,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
* @param propertyPath property path, which may be nested
|
||||
* @return a property accessor for the target bean
|
||||
*/
|
||||
@SuppressWarnings("unchecked") // avoid nested generic
|
||||
protected AbstractNestablePropertyAccessor getPropertyAccessorForPropertyPath(String propertyPath) {
|
||||
int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(propertyPath);
|
||||
// Handle nested properties recursively.
|
||||
|
||||
+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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ import kotlin.jvm.JvmClassMappingKt;
|
||||
import kotlin.reflect.KFunction;
|
||||
import kotlin.reflect.KParameter;
|
||||
import kotlin.reflect.full.KClasses;
|
||||
import kotlin.reflect.jvm.KCallablesJvm;
|
||||
import kotlin.reflect.jvm.ReflectJvmMapping;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -83,10 +82,7 @@ public abstract class BeanUtils {
|
||||
values.put(byte.class, (byte) 0);
|
||||
values.put(short.class, (short) 0);
|
||||
values.put(int.class, 0);
|
||||
values.put(long.class, 0L);
|
||||
values.put(float.class, 0F);
|
||||
values.put(double.class, 0D);
|
||||
values.put(char.class, '\0');
|
||||
values.put(long.class, (long) 0);
|
||||
DEFAULT_TYPE_VALUES = Collections.unmodifiableMap(values);
|
||||
}
|
||||
|
||||
@@ -230,6 +226,7 @@ public abstract class BeanUtils {
|
||||
* @since 5.0
|
||||
* @see <a href="https://kotlinlang.org/docs/reference/classes.html#constructors">Kotlin docs</a>
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
public static <T> Constructor<T> findPrimaryConstructor(Class<T> clazz) {
|
||||
Assert.notNull(clazz, "Class must not be null");
|
||||
@@ -444,7 +441,8 @@ public abstract class BeanUtils {
|
||||
* @throws BeansException if PropertyDescriptor look fails
|
||||
*/
|
||||
public static PropertyDescriptor[] getPropertyDescriptors(Class<?> clazz) throws BeansException {
|
||||
return CachedIntrospectionResults.forClass(clazz).getPropertyDescriptors();
|
||||
CachedIntrospectionResults cr = CachedIntrospectionResults.forClass(clazz);
|
||||
return cr.getPropertyDescriptors();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -455,8 +453,11 @@ public abstract class BeanUtils {
|
||||
* @throws BeansException if PropertyDescriptor lookup fails
|
||||
*/
|
||||
@Nullable
|
||||
public static PropertyDescriptor getPropertyDescriptor(Class<?> clazz, String propertyName) throws BeansException {
|
||||
return CachedIntrospectionResults.forClass(clazz).getPropertyDescriptor(propertyName);
|
||||
public static PropertyDescriptor getPropertyDescriptor(Class<?> clazz, String propertyName)
|
||||
throws BeansException {
|
||||
|
||||
CachedIntrospectionResults cr = CachedIntrospectionResults.forClass(clazz);
|
||||
return cr.getPropertyDescriptor(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -509,7 +510,6 @@ public abstract class BeanUtils {
|
||||
if (targetType == null || targetType.isArray() || unknownEditorTypes.contains(targetType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ClassLoader cl = targetType.getClassLoader();
|
||||
if (cl == null) {
|
||||
try {
|
||||
@@ -526,34 +526,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -786,11 +780,6 @@ public abstract class BeanUtils {
|
||||
if (kotlinConstructor == null) {
|
||||
return ctor.newInstance(args);
|
||||
}
|
||||
|
||||
if ((!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(ctor.getDeclaringClass().getModifiers()))) {
|
||||
KCallablesJvm.setAccessible(kotlinConstructor, true);
|
||||
}
|
||||
|
||||
List<KParameter> parameters = kotlinConstructor.getParameters();
|
||||
Map<KParameter, Object> argParameters = new HashMap<>(parameters.size());
|
||||
Assert.isTrue(args.length <= parameters.size(),
|
||||
|
||||
@@ -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.
|
||||
@@ -97,7 +97,7 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
|
||||
/**
|
||||
* Create a new BeanWrapperImpl for the given object.
|
||||
* @param object the object wrapped by this BeanWrapper
|
||||
* @param object object wrapped by this BeanWrapper
|
||||
*/
|
||||
public BeanWrapperImpl(Object object) {
|
||||
super(object);
|
||||
@@ -114,7 +114,7 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
/**
|
||||
* Create a new BeanWrapperImpl for the given object,
|
||||
* registering a nested path that the object is in.
|
||||
* @param object the object wrapped by this BeanWrapper
|
||||
* @param object object wrapped by this BeanWrapper
|
||||
* @param nestedPath the nested path of the object
|
||||
* @param rootObject the root object at the top of the path
|
||||
*/
|
||||
@@ -125,7 +125,7 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
/**
|
||||
* Create a new BeanWrapperImpl for the given object,
|
||||
* registering a nested path that the object is in.
|
||||
* @param object the object wrapped by this BeanWrapper
|
||||
* @param object object wrapped by this BeanWrapper
|
||||
* @param nestedPath the nested path of the object
|
||||
* @param parent the containing BeanWrapper (must not be {@code null})
|
||||
*/
|
||||
@@ -289,15 +289,15 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
@Override
|
||||
@Nullable
|
||||
public Object getValue() throws Exception {
|
||||
Method readMethod = this.pd.getReadMethod();
|
||||
final Method readMethod = this.pd.getReadMethod();
|
||||
if (System.getSecurityManager() != null) {
|
||||
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
|
||||
ReflectionUtils.makeAccessible(readMethod);
|
||||
return null;
|
||||
});
|
||||
try {
|
||||
return AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
|
||||
() -> readMethod.invoke(getWrappedInstance(), (Object[]) null), acc);
|
||||
return AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
|
||||
readMethod.invoke(getWrappedInstance(), (Object[]) null), acc);
|
||||
}
|
||||
catch (PrivilegedActionException pae) {
|
||||
throw pae.getException();
|
||||
@@ -310,8 +310,8 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(@Nullable Object value) throws Exception {
|
||||
Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
|
||||
public void setValue(final @Nullable Object value) throws Exception {
|
||||
final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
|
||||
((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
|
||||
this.pd.getWriteMethod());
|
||||
if (System.getSecurityManager() != null) {
|
||||
@@ -320,8 +320,8 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
return null;
|
||||
});
|
||||
try {
|
||||
AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
|
||||
() -> writeMethod.invoke(getWrappedInstance(), value), acc);
|
||||
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
|
||||
writeMethod.invoke(getWrappedInstance(), value), acc);
|
||||
}
|
||||
catch (PrivilegedActionException ex) {
|
||||
throw ex.getException();
|
||||
|
||||
+23
-37
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -20,8 +20,6 @@ import java.beans.BeanInfo;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.net.URL;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -94,14 +92,12 @@ public final class CachedIntrospectionResults {
|
||||
*/
|
||||
public static final String IGNORE_BEANINFO_PROPERTY_NAME = "spring.beaninfo.ignore";
|
||||
|
||||
private static final PropertyDescriptor[] EMPTY_PROPERTY_DESCRIPTOR_ARRAY = {};
|
||||
|
||||
|
||||
private static final boolean shouldIntrospectorIgnoreBeaninfoClasses =
|
||||
SpringProperties.getFlag(IGNORE_BEANINFO_PROPERTY_NAME);
|
||||
|
||||
/** Stores the BeanInfoFactory instances. */
|
||||
private static final List<BeanInfoFactory> beanInfoFactories = SpringFactoriesLoader.loadFactories(
|
||||
private static List<BeanInfoFactory> beanInfoFactories = SpringFactoriesLoader.loadFactories(
|
||||
BeanInfoFactory.class, CachedIntrospectionResults.class.getClassLoader());
|
||||
|
||||
private static final Log logger = LogFactory.getLog(CachedIntrospectionResults.class);
|
||||
@@ -257,7 +253,7 @@ public final class CachedIntrospectionResults {
|
||||
private final BeanInfo beanInfo;
|
||||
|
||||
/** PropertyDescriptor objects keyed by property name String. */
|
||||
private final Map<String, PropertyDescriptor> propertyDescriptors;
|
||||
private final Map<String, PropertyDescriptor> propertyDescriptorCache;
|
||||
|
||||
/** TypeDescriptor objects keyed by PropertyDescriptor. */
|
||||
private final ConcurrentMap<PropertyDescriptor, TypeDescriptor> typeDescriptorCache;
|
||||
@@ -278,22 +274,14 @@ public final class CachedIntrospectionResults {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Caching PropertyDescriptors for class [" + beanClass.getName() + "]");
|
||||
}
|
||||
this.propertyDescriptors = new LinkedHashMap<>();
|
||||
this.propertyDescriptorCache = new LinkedHashMap<>();
|
||||
|
||||
// This call is slow so we do it once.
|
||||
PropertyDescriptor[] pds = this.beanInfo.getPropertyDescriptors();
|
||||
for (PropertyDescriptor pd : pds) {
|
||||
if (Class.class == beanClass && !("name".equals(pd.getName()) ||
|
||||
(pd.getName().endsWith("Name") && String.class == pd.getPropertyType()))) {
|
||||
// Only allow all name variants of Class properties
|
||||
continue;
|
||||
}
|
||||
if (URL.class == beanClass && "content".equals(pd.getName())) {
|
||||
// Only allow URL attribute introspection, not content resolution
|
||||
continue;
|
||||
}
|
||||
if (pd.getWriteMethod() == null && isInvalidReadOnlyPropertyType(pd.getPropertyType())) {
|
||||
// Ignore read-only properties such as ClassLoader - no need to bind to those
|
||||
if (Class.class == beanClass &&
|
||||
("classLoader".equals(pd.getName()) || "protectionDomain".equals(pd.getName()))) {
|
||||
// Ignore Class.getClassLoader() and getProtectionDomain() methods - nobody needs to bind to those
|
||||
continue;
|
||||
}
|
||||
if (logger.isTraceEnabled()) {
|
||||
@@ -303,7 +291,7 @@ public final class CachedIntrospectionResults {
|
||||
"; editor [" + pd.getPropertyEditorClass().getName() + "]" : ""));
|
||||
}
|
||||
pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
|
||||
this.propertyDescriptors.put(pd.getName(), pd);
|
||||
this.propertyDescriptorCache.put(pd.getName(), pd);
|
||||
}
|
||||
|
||||
// Explicitly check implemented interfaces for setter/getter methods as well,
|
||||
@@ -325,17 +313,13 @@ public final class CachedIntrospectionResults {
|
||||
for (Class<?> ifc : currClass.getInterfaces()) {
|
||||
if (!ClassUtils.isJavaLanguageInterface(ifc)) {
|
||||
for (PropertyDescriptor pd : getBeanInfo(ifc).getPropertyDescriptors()) {
|
||||
PropertyDescriptor existingPd = this.propertyDescriptors.get(pd.getName());
|
||||
PropertyDescriptor existingPd = this.propertyDescriptorCache.get(pd.getName());
|
||||
if (existingPd == null ||
|
||||
(existingPd.getReadMethod() == null && pd.getReadMethod() != null)) {
|
||||
// GenericTypeAwarePropertyDescriptor leniently resolves a set* write method
|
||||
// against a declared read method, so we prefer read method descriptors here.
|
||||
pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
|
||||
if (pd.getWriteMethod() == null && isInvalidReadOnlyPropertyType(pd.getPropertyType())) {
|
||||
// Ignore read-only properties such as ClassLoader - no need to bind to those
|
||||
continue;
|
||||
}
|
||||
this.propertyDescriptors.put(pd.getName(), pd);
|
||||
this.propertyDescriptorCache.put(pd.getName(), pd);
|
||||
}
|
||||
}
|
||||
introspectInterfaces(ifc, ifc);
|
||||
@@ -343,12 +327,6 @@ public final class CachedIntrospectionResults {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInvalidReadOnlyPropertyType(@Nullable Class<?> returnType) {
|
||||
return (returnType != null && (AutoCloseable.class.isAssignableFrom(returnType) ||
|
||||
ClassLoader.class.isAssignableFrom(returnType) ||
|
||||
ProtectionDomain.class.isAssignableFrom(returnType)));
|
||||
}
|
||||
|
||||
|
||||
BeanInfo getBeanInfo() {
|
||||
return this.beanInfo;
|
||||
@@ -360,19 +338,27 @@ public final class CachedIntrospectionResults {
|
||||
|
||||
@Nullable
|
||||
PropertyDescriptor getPropertyDescriptor(String name) {
|
||||
PropertyDescriptor pd = this.propertyDescriptors.get(name);
|
||||
PropertyDescriptor pd = this.propertyDescriptorCache.get(name);
|
||||
if (pd == null && StringUtils.hasLength(name)) {
|
||||
// Same lenient fallback checking as in Property...
|
||||
pd = this.propertyDescriptors.get(StringUtils.uncapitalize(name));
|
||||
pd = this.propertyDescriptorCache.get(StringUtils.uncapitalize(name));
|
||||
if (pd == null) {
|
||||
pd = this.propertyDescriptors.get(StringUtils.capitalize(name));
|
||||
pd = this.propertyDescriptorCache.get(StringUtils.capitalize(name));
|
||||
}
|
||||
}
|
||||
return pd;
|
||||
return (pd == null || pd instanceof GenericTypeAwarePropertyDescriptor ? pd :
|
||||
buildGenericTypeAwarePropertyDescriptor(getBeanClass(), pd));
|
||||
}
|
||||
|
||||
PropertyDescriptor[] getPropertyDescriptors() {
|
||||
return this.propertyDescriptors.values().toArray(EMPTY_PROPERTY_DESCRIPTOR_ARRAY);
|
||||
PropertyDescriptor[] pds = new PropertyDescriptor[this.propertyDescriptorCache.size()];
|
||||
int i = 0;
|
||||
for (PropertyDescriptor pd : this.propertyDescriptorCache.values()) {
|
||||
pds[i] = (pd instanceof GenericTypeAwarePropertyDescriptor ? pd :
|
||||
buildGenericTypeAwarePropertyDescriptor(getBeanClass(), pd));
|
||||
i++;
|
||||
}
|
||||
return pds;
|
||||
}
|
||||
|
||||
private PropertyDescriptor buildGenericTypeAwarePropertyDescriptor(Class<?> beanClass, PropertyDescriptor pd) {
|
||||
|
||||
@@ -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.
|
||||
@@ -52,7 +52,7 @@ public class DirectFieldAccessor extends AbstractNestablePropertyAccessor {
|
||||
|
||||
/**
|
||||
* Create a new DirectFieldAccessor for the given object.
|
||||
* @param object the object wrapped by this DirectFieldAccessor
|
||||
* @param object object wrapped by this DirectFieldAccessor
|
||||
*/
|
||||
public DirectFieldAccessor(Object object) {
|
||||
super(object);
|
||||
@@ -61,7 +61,7 @@ public class DirectFieldAccessor extends AbstractNestablePropertyAccessor {
|
||||
/**
|
||||
* Create a new DirectFieldAccessor for the given object,
|
||||
* registering a nested path that the object is in.
|
||||
* @param object the object wrapped by this DirectFieldAccessor
|
||||
* @param object object wrapped by this DirectFieldAccessor
|
||||
* @param nestedPath the nested path of the object
|
||||
* @param parent the containing DirectFieldAccessor (must not be {@code null})
|
||||
*/
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
+4
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -60,13 +60,12 @@ final class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor {
|
||||
@Nullable
|
||||
private Class<?> propertyType;
|
||||
|
||||
@Nullable
|
||||
private final Class<?> propertyEditorClass;
|
||||
|
||||
|
||||
public GenericTypeAwarePropertyDescriptor(Class<?> beanClass, String propertyName,
|
||||
@Nullable Method readMethod, @Nullable Method writeMethod,
|
||||
@Nullable Class<?> propertyEditorClass) throws IntrospectionException {
|
||||
@Nullable Method readMethod, @Nullable Method writeMethod, Class<?> propertyEditorClass)
|
||||
throws IntrospectionException {
|
||||
|
||||
super(propertyName, null, null);
|
||||
this.beanClass = beanClass;
|
||||
@@ -138,7 +137,7 @@ final class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor {
|
||||
Set<Method> ambiguousCandidates = this.ambiguousWriteMethods;
|
||||
if (ambiguousCandidates != null) {
|
||||
this.ambiguousWriteMethods = null;
|
||||
LogFactory.getLog(GenericTypeAwarePropertyDescriptor.class).debug("Non-unique JavaBean property '" +
|
||||
LogFactory.getLog(GenericTypeAwarePropertyDescriptor.class).warn("Invalid JavaBean property '" +
|
||||
getName() + "' being accessed! Ambiguous write methods found next to actually used [" +
|
||||
this.writeMethod + "]: " + ambiguousCandidates);
|
||||
}
|
||||
@@ -157,7 +156,6 @@ final class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Class<?> getPropertyEditorClass() {
|
||||
return this.propertyEditorClass;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -23,9 +23,8 @@ import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Common interface for classes that can access named properties
|
||||
* (such as bean properties of an object or fields in an object).
|
||||
*
|
||||
* <p>Serves as base interface for {@link BeanWrapper}.
|
||||
* (such as bean properties of an object or fields in an object)
|
||||
* Serves as base interface for {@link BeanWrapper}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user