mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
363 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e0f56e7d80 | |||
| 83186b689f | |||
| dc2947c52d | |||
| e4ec376075 | |||
| c81e11d537 | |||
| de6180b093 | |||
| 1c10cdd1e8 | |||
| 941b92cbed | |||
| e26d8839b3 | |||
| a1c7380398 | |||
| 7dd622bdb2 | |||
| 64c96c579d | |||
| 39e3876301 | |||
| f771603789 | |||
| e441832e99 | |||
| f963fc5f98 | |||
| b55eee1b0d | |||
| 28742171fd | |||
| 7a75b94556 | |||
| ab71ff93bb | |||
| cf30327740 | |||
| e22a038725 | |||
| 7aedb9ee33 | |||
| 5b1719cd77 | |||
| c056b81753 | |||
| dbdd67ec62 | |||
| 4fcfa5b991 | |||
| ed06a6de26 | |||
| afa799b4f0 | |||
| f0d149b330 | |||
| caaf83b8e6 | |||
| b30f4d7bb7 | |||
| b6b03f38d7 | |||
| 46b0d7dc03 | |||
| fcf64798b5 | |||
| 94ed07d9cb | |||
| b81c62d064 | |||
| ca1a11acac | |||
| c261d40610 | |||
| 3017955eff | |||
| 22c82ff206 | |||
| f54952481b | |||
| 9e733b09e2 | |||
| a7cf19cec5 | |||
| 0cf7f7bd89 | |||
| 949c3d450c | |||
| 3b4ae7b028 | |||
| 8b39698553 | |||
| 6fad00ed22 | |||
| 5f6d8df34b | |||
| 35de7e19ee | |||
| 10e979e58b | |||
| 4143b445d6 | |||
| eefdd2c768 | |||
| 9f91168396 | |||
| 7aed6279a2 | |||
| c3fe112fd7 | |||
| 90103b0ae9 | |||
| 0cf15c0fdd | |||
| 4e9af3e277 | |||
| 01fd489b47 | |||
| 270b167e08 | |||
| b158110801 | |||
| 17f7a24118 | |||
| d518a7d8c8 | |||
| 24cd3c1f4c | |||
| 2a8c369cff | |||
| 002546b3e4 | |||
| 1627f57f1f | |||
| 3811cd4c0a | |||
| d927e37364 | |||
| 1d302bf384 | |||
| 4b150fd451 | |||
| 3a6016d356 | |||
| 135506f672 | |||
| cb36ca31f6 | |||
| edd66d96dd | |||
| 35610a535d | |||
| acf2955b96 | |||
| 8fc744f4f4 | |||
| 9a5891e6e6 | |||
| 64b64d9ba0 | |||
| 1419172fbd | |||
| 420e0ba25f | |||
| 29d98285be | |||
| ad708780ed | |||
| 8789b34ef8 | |||
| c9cd53f469 | |||
| c462fe30ed | |||
| 8a0c4caff6 | |||
| 46363c337b | |||
| c1261f2860 | |||
| c4c124b16d | |||
| ee7f60000e | |||
| f1fdc11fab | |||
| 21d61316be | |||
| cb39b07088 | |||
| 50771237cc | |||
| 9fbf5dc945 | |||
| a683e9e81b | |||
| 6e2e45d18f | |||
| 887389d341 | |||
| d9c22e657f | |||
| 8a510db00d | |||
| 9eec6d0834 | |||
| a3e23cd5fc | |||
| af977c0891 | |||
| 1bbcd706be | |||
| 83ac659158 | |||
| a2f02dbfc0 | |||
| 8cbb188455 | |||
| bc973d7001 | |||
| fa3130d716 | |||
| b3e5f86277 | |||
| 340f41af6d | |||
| 25aa295c2c | |||
| 67b91b2390 | |||
| d67034f99b | |||
| dcdea986f6 | |||
| a524857bd5 | |||
| af14eea1ef | |||
| f96872404d | |||
| a7d5fbfbea | |||
| 84de100fc6 | |||
| beab8ab4e7 | |||
| 6f41180cc5 | |||
| 7e2106b850 | |||
| 453c6d41f7 | |||
| 84b4cebb39 | |||
| 5689395678 | |||
| 071c2988d5 | |||
| 94af2ca06b | |||
| ff20a06876 | |||
| 2ffefbb211 | |||
| 4571626839 | |||
| f8a59c267f | |||
| 1166577d2c | |||
| 36dc4e4c5f | |||
| 3ac60147f3 | |||
| e3ceb9b23d | |||
| 5ab966fbde | |||
| 7276752e7c | |||
| 685a195ba1 | |||
| 3188c0f7db | |||
| 3ea540adbc | |||
| ec03e8830e | |||
| 11cb938232 | |||
| f004bb1b64 | |||
| 88f73bffa0 | |||
| 0ab054c7b9 | |||
| 8eb618b480 | |||
| 2f78abd56e | |||
| 3ec612aaf8 | |||
| 4eaee1e738 | |||
| eca755ec88 | |||
| 4201479546 | |||
| b60340b102 | |||
| 2fd39839f8 | |||
| ce87285be5 | |||
| 97582fd0a1 | |||
| d2c7dfb79e | |||
| 7139a877f4 | |||
| 669b05dc1d | |||
| 038b88e2a1 | |||
| eb84c84373 | |||
| 920be8e1b2 | |||
| a13ad3e969 | |||
| 874432b38a | |||
| 4ab03fede8 | |||
| 5bbdd36e19 | |||
| a22feac803 | |||
| bc9cd9a687 | |||
| a71a45e719 | |||
| 132d8c7f45 | |||
| 5d7a632965 | |||
| 6bc7d41734 | |||
| 05d3e820f9 | |||
| f8a5a8d7be | |||
| 82a2544918 | |||
| e702c22da4 | |||
| c4e362500b | |||
| 8d5a6520ce | |||
| 4effca35b5 | |||
| 8f9a1cdc0c | |||
| 136bd2002e | |||
| a749a6bf54 | |||
| 7072aab53b | |||
| dbeae27d3c | |||
| fb312d0ed5 | |||
| 0e670b1c15 | |||
| fadfcf4e43 | |||
| caa13690e8 | |||
| 6647023151 | |||
| e32f94bf8c | |||
| bd6d697395 | |||
| 7f65e17ff2 | |||
| 9095f1d584 | |||
| 4f16d5b5b2 | |||
| 6a6c7df824 | |||
| 5c9fbcc23c | |||
| f4f5cee76c | |||
| bf1cf549b1 | |||
| 1272cd557d | |||
| 993b6d1351 | |||
| 0a92d84778 | |||
| 652c13a6ea | |||
| cb3fa89946 | |||
| d01dca14e9 | |||
| d698446f7c | |||
| 5ef023afd2 | |||
| 316764cad0 | |||
| a681d6af22 | |||
| 7211912057 | |||
| 148eac0200 | |||
| 86be03945b | |||
| 537aced28b | |||
| 5c76ff5ef6 | |||
| d02d5adb54 | |||
| 71f7469578 | |||
| 420c4f3df3 | |||
| 420ff46b2a | |||
| 261bc2ad6a | |||
| c92b9bc7fe | |||
| 4b1b25496b | |||
| 9e8b6feb54 | |||
| 3631d2f36e | |||
| cfefcee788 | |||
| 5fb58e51e5 | |||
| 67c4b4182f | |||
| 6b3052200a | |||
| cf5b86369d | |||
| 7067461d71 | |||
| 34cb5df859 | |||
| 01231fe923 | |||
| 7665424ea8 | |||
| f63a106c85 | |||
| caaf48d4ec | |||
| e52fc2176d | |||
| e8e7fbba94 | |||
| bd1f34e174 | |||
| a490723f02 | |||
| df263d01b9 | |||
| 2a80b64d40 | |||
| e24043ab90 | |||
| 4078b73cec | |||
| dca155e438 | |||
| edabde8a11 | |||
| 8087eb69bf | |||
| e41d865193 | |||
| d68bb4eecd | |||
| 730ad4436f | |||
| 23ab9ca8ca | |||
| 51d263bd06 | |||
| 518dc6df65 | |||
| 59c6b7e445 | |||
| 3e75ec73ab | |||
| 709a41fd43 | |||
| 90072d06fb | |||
| 54bdab4553 | |||
| 75e1811470 | |||
| 18781e58ac | |||
| ed4e2289cd | |||
| ccf95413ed | |||
| fdd6e50721 | |||
| c04fa858fc | |||
| c3ce4f0f90 | |||
| e1200f34e7 | |||
| 999376f9f9 | |||
| c942d789c3 | |||
| 03668f9c10 | |||
| 3e14cdbc69 | |||
| f04e9a8366 | |||
| c1606c5a5e | |||
| 95fac2589f | |||
| 41c8bb4fe1 | |||
| 31a4c274b7 | |||
| d665977787 | |||
| 0b6a54dcc7 | |||
| 1885ab3e07 | |||
| de10bb69cb | |||
| c7642422c3 | |||
| 4c2e0ee5ff | |||
| 79804d92c2 | |||
| f191cf4eb3 | |||
| 0ebb1c5baa | |||
| 4b7d9b1f9c | |||
| ca84559588 | |||
| 1af21bb451 | |||
| ac581bed92 | |||
| 0802581aff | |||
| d7b9270672 | |||
| c44447f622 | |||
| 8b80d38c33 | |||
| b06d267232 | |||
| 8422d9d22f | |||
| c50a5096a0 | |||
| c25c550113 | |||
| 9e09d6cde4 | |||
| 31b8587ce6 | |||
| 00375df4e8 | |||
| b1352e1833 | |||
| b2e94f611f | |||
| ad7cdc5ce9 | |||
| 6cc9538ab9 | |||
| e9083d7d20 | |||
| 98ce171b30 | |||
| 57a5370eec | |||
| 99c7608ffe | |||
| c0f79ee00a | |||
| 9261766677 | |||
| 14f24f43d7 | |||
| d7e0eed8d2 | |||
| 7c834d98c2 | |||
| 70974e006e | |||
| 2f557d9583 | |||
| b84fe99d07 | |||
| 69df27a99f | |||
| 5649a6f8ef | |||
| be6eeafe78 | |||
| b77b45434f | |||
| 6582787678 | |||
| 8b89128c7b | |||
| 2a5713f389 | |||
| 40d2058b97 | |||
| 0d478ca8dd | |||
| 445c0def0c | |||
| ef696c787b | |||
| 27257fb82e | |||
| e209a460ca | |||
| d019c1f82b | |||
| 82d6e07090 | |||
| a1b2695c3a | |||
| 341f4882ed | |||
| 829bed03af | |||
| ce0aed216b | |||
| 0d7c562693 | |||
| 913cc079af | |||
| 3f7dec0b0d | |||
| 830cc3450f | |||
| 6f6d27f50f | |||
| 19a8b94b21 | |||
| 2c53e9e308 | |||
| 2271b6078e | |||
| e8eeb99ac8 | |||
| b67e97d388 | |||
| 656f0591c6 | |||
| 23babe27bb | |||
| bcb9f159ca | |||
| 8ca9187938 | |||
| 1e0bdf95d0 | |||
| 44da9451c4 | |||
| 544f357661 | |||
| ca4f338d75 | |||
| 8e8c88ea5c | |||
| 767299c6dd | |||
| 3290495222 | |||
| b4b3c2ead6 | |||
| dfd5374f02 | |||
| 722ab25f27 | |||
| c37d6c30a0 | |||
| 5fbdd6dcfe | |||
| 29572600dc | |||
| aaf626a537 |
@@ -0,0 +1,3 @@
|
||||
# Enable auto-env through the sdkman_auto_env config
|
||||
# Add key=value pairs of SDKs to use below
|
||||
java=8.0.332-librca
|
||||
+65
-60
@@ -2,9 +2,9 @@ plugins {
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE' apply false
|
||||
id 'io.spring.nohttp' version '0.0.10'
|
||||
id "io.freefair.aspectj" version '6.2.0' apply false
|
||||
id 'org.jetbrains.dokka' version '1.5.0' apply false
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.5.31' apply false
|
||||
id "org.jetbrains.kotlin.plugin.serialization" version "1.5.31" apply false
|
||||
id 'org.jetbrains.dokka' version '1.6.10' apply false
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.5.32' apply false
|
||||
id "org.jetbrains.kotlin.plugin.serialization" version "1.5.32" apply false
|
||||
id 'org.asciidoctor.jvm.convert' version '3.3.2'
|
||||
id 'org.asciidoctor.jvm.pdf' version '3.3.2'
|
||||
id "org.unbroken-dome.xjc" version '2.0.0' apply false
|
||||
@@ -27,25 +27,25 @@ configure(allprojects) { project ->
|
||||
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom "com.fasterxml.jackson:jackson-bom:2.12.5"
|
||||
mavenBom "io.netty:netty-bom:4.1.70.Final"
|
||||
mavenBom "io.projectreactor:reactor-bom:2020.0.13"
|
||||
mavenBom "io.r2dbc:r2dbc-bom:Arabba-SR10"
|
||||
mavenBom "io.rsocket:rsocket-bom:1.1.1"
|
||||
mavenBom "org.eclipse.jetty:jetty-bom:9.4.44.v20210927"
|
||||
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.5.31"
|
||||
mavenBom "com.fasterxml.jackson:jackson-bom:2.12.6"
|
||||
mavenBom "io.netty:netty-bom:4.1.77.Final"
|
||||
mavenBom "io.projectreactor:reactor-bom:2020.0.19"
|
||||
mavenBom "io.r2dbc:r2dbc-bom:Arabba-SR13"
|
||||
mavenBom "io.rsocket:rsocket-bom:1.1.2"
|
||||
mavenBom "org.eclipse.jetty:jetty-bom:9.4.46.v20220331"
|
||||
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.5.32"
|
||||
mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.5.2"
|
||||
mavenBom "org.jetbrains.kotlinx:kotlinx-serialization-bom:1.2.2"
|
||||
mavenBom "org.junit:junit-bom:5.8.1"
|
||||
mavenBom "org.junit:junit-bom:5.8.2"
|
||||
}
|
||||
dependencies {
|
||||
dependencySet(group: 'org.apache.logging.log4j', version: '2.14.1') {
|
||||
dependencySet(group: 'org.apache.logging.log4j', version: '2.17.2') {
|
||||
entry 'log4j-api'
|
||||
entry 'log4j-core'
|
||||
entry 'log4j-jul'
|
||||
entry 'log4j-slf4j-impl'
|
||||
}
|
||||
dependency "org.slf4j:slf4j-api:1.7.32"
|
||||
dependency "org.slf4j:slf4j-api:1.7.36"
|
||||
dependency("com.google.code.findbugs:findbugs:3.0.1") {
|
||||
exclude group: "dom4j", name: "dom4j"
|
||||
}
|
||||
@@ -67,23 +67,23 @@ 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.reactivex.rxjava3:rxjava:3.1.1"
|
||||
dependency "io.smallrye.reactive:mutiny:1.1.1"
|
||||
dependency "io.reactivex.rxjava3:rxjava:3.1.4"
|
||||
dependency "io.smallrye.reactive:mutiny:1.4.0"
|
||||
dependency "io.projectreactor.tools:blockhound:1.0.6.RELEASE"
|
||||
|
||||
dependency "com.caucho:hessian:4.0.63"
|
||||
dependency "com.fasterxml:aalto-xml:1.3.0"
|
||||
dependency("com.fasterxml.woodstox:woodstox-core:6.2.6") {
|
||||
dependency "com.fasterxml:aalto-xml:1.3.1"
|
||||
dependency("com.fasterxml.woodstox:woodstox-core:6.2.8") {
|
||||
exclude group: "stax", name: "stax-api"
|
||||
}
|
||||
dependency "com.google.code.gson:gson:2.8.8"
|
||||
dependency "com.google.protobuf:protobuf-java-util:3.18.0"
|
||||
dependency "com.google.code.gson:gson:2.8.9"
|
||||
dependency "com.google.protobuf:protobuf-java-util:3.19.3"
|
||||
dependency "com.googlecode.protobuf-java-format:protobuf-java-format:1.4"
|
||||
dependency("com.thoughtworks.xstream:xstream:1.4.18") {
|
||||
exclude group: "xpp3", name: "xpp3_min"
|
||||
exclude group: "xmlpull", name: "xmlpull"
|
||||
}
|
||||
dependency "org.apache.johnzon:johnzon-jsonb:1.2.14"
|
||||
dependency "org.apache.johnzon:johnzon-jsonb:1.2.16"
|
||||
dependency("org.codehaus.jettison:jettison:1.3.8") {
|
||||
exclude group: "stax", name: "stax-api"
|
||||
}
|
||||
@@ -92,12 +92,12 @@ configure(allprojects) { project ->
|
||||
entry 'jibx-run'
|
||||
}
|
||||
dependency "org.ogce:xpp3:1.1.6"
|
||||
dependency "org.yaml:snakeyaml:1.29"
|
||||
dependency "org.yaml:snakeyaml:1.30"
|
||||
|
||||
dependency "com.h2database:h2:1.4.200"
|
||||
dependency "com.github.ben-manes.caffeine:caffeine:2.9.2"
|
||||
dependency "com.github.librepdf:openpdf:1.3.26"
|
||||
dependency "com.rometools:rome:1.16.0"
|
||||
dependency "com.h2database:h2:2.1.210"
|
||||
dependency "com.github.ben-manes.caffeine:caffeine:2.9.3"
|
||||
dependency "com.github.librepdf:openpdf:1.3.27"
|
||||
dependency "com.rometools:rome:1.18.0"
|
||||
dependency "commons-io:commons-io:2.5"
|
||||
dependency "io.vavr:vavr:0.10.4"
|
||||
dependency "net.sf.jopt-simple:jopt-simple:5.0.4"
|
||||
@@ -123,48 +123,48 @@ configure(allprojects) { project ->
|
||||
dependency "net.sf.ehcache:ehcache:2.10.6"
|
||||
dependency "org.ehcache:jcache:1.0.1"
|
||||
dependency "org.ehcache:ehcache:3.4.0"
|
||||
dependency "org.hibernate:hibernate-core:5.4.32.Final"
|
||||
dependency "org.hibernate:hibernate-validator:6.2.0.Final"
|
||||
dependency "org.hibernate:hibernate-core:5.4.33.Final"
|
||||
dependency "org.hibernate:hibernate-validator:6.2.3.Final"
|
||||
dependency "org.webjars:webjars-locator-core:0.48"
|
||||
dependency "org.webjars:underscorejs:1.8.3"
|
||||
|
||||
dependencySet(group: 'org.apache.tomcat', version: '9.0.54') {
|
||||
dependencySet(group: 'org.apache.tomcat', version: '9.0.62') {
|
||||
entry 'tomcat-util'
|
||||
entry('tomcat-websocket') {
|
||||
exclude group: "org.apache.tomcat", name: "tomcat-websocket-api"
|
||||
exclude group: "org.apache.tomcat", name: "tomcat-servlet-api"
|
||||
exclude group: "org.apache.tomcat", name: "tomcat-websocket-api"
|
||||
}
|
||||
}
|
||||
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.54') {
|
||||
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.62') {
|
||||
entry 'tomcat-embed-core'
|
||||
entry 'tomcat-embed-websocket'
|
||||
}
|
||||
dependencySet(group: 'io.undertow', version: '2.2.12.Final') {
|
||||
dependencySet(group: 'io.undertow', version: '2.2.17.Final') {
|
||||
entry 'undertow-core'
|
||||
entry('undertow-websockets-jsr') {
|
||||
exclude group: "org.jboss.spec.javax.websocket", name: "jboss-websocket-api_1.1_spec"
|
||||
}
|
||||
entry('undertow-servlet') {
|
||||
exclude group: "org.jboss.spec.javax.servlet", name: "jboss-servlet-api_4.0_spec"
|
||||
exclude group: "org.jboss.spec.javax.annotation", name: "jboss-annotations-api_1.3_spec"
|
||||
}
|
||||
entry('undertow-websockets-jsr') {
|
||||
exclude group: "org.jboss.spec.javax.websocket", name: "jboss-websocket-api_1.1_spec"
|
||||
}
|
||||
}
|
||||
|
||||
dependency "org.eclipse.jetty:jetty-reactive-httpclient:1.1.11"
|
||||
dependency 'org.apache.httpcomponents.client5:httpclient5:5.1.3'
|
||||
dependency 'org.apache.httpcomponents.core5:httpcore5-reactive:5.1.3'
|
||||
dependency("org.apache.httpcomponents:httpclient:4.5.13") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.apache.httpcomponents:httpasyncclient:4.1.5") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependencySet(group: 'com.squareup.okhttp3', version: '3.14.9') {
|
||||
entry 'okhttp'
|
||||
entry 'mockwebserver'
|
||||
}
|
||||
dependency("org.apache.httpcomponents:httpclient:4.5.13") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.apache.httpcomponents:httpasyncclient:4.1.4") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency 'org.apache.httpcomponents.client5:httpclient5:5.1'
|
||||
dependency 'org.apache.httpcomponents.core5:httpcore5-reactive:5.1.1'
|
||||
dependency "org.eclipse.jetty:jetty-reactive-httpclient:1.1.9"
|
||||
|
||||
dependency "org.jruby:jruby:9.2.19.0"
|
||||
dependency "org.jruby:jruby:9.2.20.1"
|
||||
dependency "org.python:jython-standalone:2.7.1"
|
||||
dependency "org.mozilla:rhino:1.7.11"
|
||||
|
||||
@@ -191,25 +191,25 @@ configure(allprojects) { project ->
|
||||
dependency "org.junit.support:testng-engine:1.0.1"
|
||||
dependency "org.hamcrest:hamcrest:2.1"
|
||||
dependency "org.awaitility:awaitility:3.1.6"
|
||||
dependency "org.assertj:assertj-core:3.21.0"
|
||||
dependencySet(group: 'org.xmlunit', version: '2.8.3') {
|
||||
dependency "org.assertj:assertj-core:3.22.0"
|
||||
dependencySet(group: 'org.xmlunit', version: '2.9.0') {
|
||||
entry 'xmlunit-assertj'
|
||||
entry('xmlunit-matchers') {
|
||||
exclude group: "org.hamcrest", name: "hamcrest-core"
|
||||
}
|
||||
}
|
||||
dependencySet(group: 'org.mockito', version: '4.0.0') {
|
||||
dependencySet(group: 'org.mockito', version: '4.5.1') {
|
||||
entry('mockito-core') {
|
||||
exclude group: "org.hamcrest", name: "hamcrest-core"
|
||||
}
|
||||
entry 'mockito-junit-jupiter'
|
||||
}
|
||||
dependency "io.mockk:mockk:1.12.0"
|
||||
dependency "io.mockk:mockk:1.12.1"
|
||||
|
||||
dependency("net.sourceforge.htmlunit:htmlunit:2.54.0") {
|
||||
dependency("net.sourceforge.htmlunit:htmlunit:2.61.0") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.seleniumhq.selenium:htmlunit-driver:2.54.0") {
|
||||
dependency("org.seleniumhq.selenium:htmlunit-driver:2.61.0") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.seleniumhq.selenium:selenium-java:3.141.59") {
|
||||
@@ -237,8 +237,8 @@ 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.9"
|
||||
dependency "joda-time:joda-time:2.10.13"
|
||||
dependency "org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.10"
|
||||
dependency "org.javamoney:moneta:1.3"
|
||||
|
||||
dependency "com.sun.activation:javax.activation:1.2.0"
|
||||
@@ -340,7 +340,7 @@ configure([rootProject] + javaProjects) { project ->
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
toolVersion = "9.0"
|
||||
toolVersion = "10.1"
|
||||
configDirectory.set(rootProject.file("src/checkstyle"))
|
||||
}
|
||||
|
||||
@@ -353,16 +353,16 @@ configure([rootProject] + javaProjects) { project ->
|
||||
testImplementation("io.mockk:mockk")
|
||||
testImplementation("org.assertj:assertj-core")
|
||||
// Pull in the latest JUnit 5 Launcher API to ensure proper support in IDEs.
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-suite-engine")
|
||||
testRuntimeOnly("org.apache.logging.log4j:log4j-core")
|
||||
testRuntimeOnly("org.apache.logging.log4j:log4j-slf4j-impl")
|
||||
testRuntimeOnly("org.apache.logging.log4j:log4j-jul")
|
||||
testRuntimeOnly("org.apache.logging.log4j:log4j-slf4j-impl")
|
||||
// JSR-305 only used for non-required meta-annotations
|
||||
compileOnly("com.google.code.findbugs:jsr305")
|
||||
testCompileOnly("com.google.code.findbugs:jsr305")
|
||||
checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:0.0.29")
|
||||
checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:0.0.31")
|
||||
}
|
||||
|
||||
ext.javadocLinks = [
|
||||
@@ -383,12 +383,18 @@ configure([rootProject] + javaProjects) { project ->
|
||||
"https://hc.apache.org/httpcomponents-client-5.1.x/current/httpclient5/apidocs/",
|
||||
"https://projectreactor.io/docs/test/release/api/",
|
||||
"https://junit.org/junit4/javadoc/4.13.2/",
|
||||
// Disabling linking to JUnit 5.8.1, since the `package-list` file no longer exists due to
|
||||
// Disabling linking to JUnit 5.8.2, since the `package-list` file no longer exists due to
|
||||
// https://github.com/junit-team/junit5/commit/67ad4e545518b0ce2b0e7c96df31a669866d5003.
|
||||
// "https://junit.org/junit5/docs/5.8.1/api/",
|
||||
// "https://junit.org/junit5/docs/5.8.2/api/",
|
||||
"https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/",
|
||||
"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/",
|
||||
"https://r2dbc.io/spec/0.8.5.RELEASE/api/"
|
||||
"https://r2dbc.io/spec/0.8.5.RELEASE/api/",
|
||||
// The external Javadoc link for JSR 305 must come last to ensure that types from
|
||||
// JSR 250 (such as @PostConstruct) are still supported. This is due to the fact
|
||||
// that JSR 250 and JSR 305 both define types in javax.annotation, which results
|
||||
// in a split package, and the javadoc tool does not support split packages
|
||||
// across multiple external Javadoc sites.
|
||||
"https://www.javadoc.io/doc/com.google.code.findbugs/jsr305/3.0.2/"
|
||||
] as String[]
|
||||
}
|
||||
|
||||
@@ -399,7 +405,6 @@ configure(moduleProjects) { project ->
|
||||
configure(rootProject) {
|
||||
description = "Spring Framework"
|
||||
|
||||
apply plugin: "groovy"
|
||||
apply plugin: "kotlin"
|
||||
apply plugin: "io.spring.nohttp"
|
||||
apply plugin: 'org.springframework.build.api-diff'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:focal-20210827
|
||||
FROM ubuntu:focal-20220415
|
||||
|
||||
ADD setup.sh /setup.sh
|
||||
ADD get-jdk-url.sh /get-jdk-url.sh
|
||||
@@ -6,6 +6,6 @@ RUN ./setup.sh java8
|
||||
|
||||
ENV JAVA_HOME /opt/openjdk/java8
|
||||
ENV JDK11 /opt/openjdk/java11
|
||||
ENV JDK16 /opt/openjdk/java16
|
||||
ENV JDK17 /opt/openjdk/java17
|
||||
|
||||
ENV PATH $JAVA_HOME/bin:$PATH
|
||||
|
||||
@@ -3,13 +3,16 @@ set -e
|
||||
|
||||
case "$1" in
|
||||
java8)
|
||||
echo "https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u302-b08/OpenJDK8U-jdk_x64_linux_hotspot_8u302b08.tar.gz"
|
||||
echo "https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u332-b09/OpenJDK8U-jdk_x64_linux_hotspot_8u332b09.tar.gz"
|
||||
;;
|
||||
java11)
|
||||
echo "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.12%2B7/OpenJDK11U-jdk_x64_linux_hotspot_11.0.12_7.tar.gz"
|
||||
echo "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.15%2B10/OpenJDK11U-jdk_x64_linux_hotspot_11.0.15_10.tar.gz"
|
||||
;;
|
||||
java16)
|
||||
echo "https://github.com/adoptium/temurin16-binaries/releases/download/jdk-16.0.2%2B7/OpenJDK16U-jdk_x64_linux_hotspot_16.0.2_7.tar.gz"
|
||||
java17)
|
||||
echo "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.3%2B7/OpenJDK17U-jdk_x64_linux_hotspot_17.0.3_7.tar.gz"
|
||||
;;
|
||||
java18)
|
||||
echo "https://github.com/adoptium/temurin18-binaries/releases/download/jdk-18.0.1%2B10/OpenJDK18U-jdk_x64_linux_hotspot_18.0.1_10.tar.gz"
|
||||
;;
|
||||
*)
|
||||
echo $"Unknown java version"
|
||||
|
||||
+1
-3
@@ -14,15 +14,13 @@ 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
|
||||
###########################################################
|
||||
|
||||
mkdir -p /opt/openjdk
|
||||
pushd /opt/openjdk > /dev/null
|
||||
for jdk in java8 java11 java16
|
||||
for jdk in java8 java11 java17
|
||||
do
|
||||
JDK_URL=$( /get-jdk-url.sh $jdk )
|
||||
mkdir $jdk
|
||||
|
||||
+4
-3
@@ -1,8 +1,6 @@
|
||||
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"
|
||||
sonatype-staging-profile: "org.springframework"
|
||||
docker-hub-organization: "springci"
|
||||
artifactory-server: "https://repo.spring.io"
|
||||
branch: "5.3.x"
|
||||
@@ -10,4 +8,7 @@ milestone: "5.3.x"
|
||||
build-name: "spring-framework"
|
||||
pipeline-name: "spring-framework"
|
||||
concourse-url: "https://ci.spring.io"
|
||||
registry-mirror-host: docker.repo.spring.io
|
||||
registry-mirror-username: ((artifactory-username))
|
||||
registry-mirror-password: ((artifactory-password))
|
||||
task-timeout: 1h00m
|
||||
|
||||
+30
-17
@@ -12,7 +12,7 @@ anchors:
|
||||
SONATYPE_USERNAME: ((sonatype-username))
|
||||
SONATYPE_PASSWORD: ((sonatype-password))
|
||||
SONATYPE_URL: ((sonatype-url))
|
||||
SONATYPE_STAGING_PROFILE_ID: ((sonatype-staging-profile-id))
|
||||
SONATYPE_STAGING_PROFILE: ((sonatype-staging-profile))
|
||||
artifactory-task-params: &artifactory-task-params
|
||||
ARTIFACTORY_SERVER: ((artifactory-server))
|
||||
ARTIFACTORY_USERNAME: ((artifactory-username))
|
||||
@@ -24,6 +24,10 @@ anchors:
|
||||
username: ((docker-hub-username))
|
||||
password: ((docker-hub-password))
|
||||
tag: ((milestone))
|
||||
registry-mirror-vars: ®istry-mirror-vars
|
||||
registry-mirror-host: ((registry-mirror-host))
|
||||
registry-mirror-username: ((registry-mirror-username))
|
||||
registry-mirror-password: ((registry-mirror-password))
|
||||
slack-fail-params: &slack-fail-params
|
||||
text: >
|
||||
:concourse-failed: <https://ci.spring.io/teams/${BUILD_TEAM_NAME}/pipelines/${BUILD_PIPELINE_NAME}/jobs/${BUILD_JOB_NAME}/builds/${BUILD_NAME}|${BUILD_PIPELINE_NAME} ${BUILD_JOB_NAME} failed!>
|
||||
@@ -41,6 +45,11 @@ anchors:
|
||||
GITHUB_TOKEN: ((github-ci-release-token))
|
||||
|
||||
resource_types:
|
||||
- name: registry-image
|
||||
type: registry-image
|
||||
source:
|
||||
repository: concourse/registry-image-resource
|
||||
tag: 1.5.0
|
||||
- name: artifactory-resource
|
||||
type: registry-image
|
||||
source:
|
||||
@@ -87,7 +96,7 @@ resources:
|
||||
branch: ((branch))
|
||||
paths: ["ci/images/*"]
|
||||
- name: ci-image
|
||||
type: docker-image
|
||||
type: registry-image
|
||||
icon: docker
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
@@ -124,14 +133,14 @@ resources:
|
||||
access_token: ((github-ci-status-token))
|
||||
branch: ((branch))
|
||||
context: jdk11-build
|
||||
- name: repo-status-jdk16-build
|
||||
- name: repo-status-jdk17-build
|
||||
type: github-status-resource
|
||||
icon: eye-check-outline
|
||||
source:
|
||||
repository: ((github-repo-name))
|
||||
access_token: ((github-ci-status-token))
|
||||
branch: ((branch))
|
||||
context: jdk16-build
|
||||
context: jdk17-build
|
||||
- name: slack-alert
|
||||
type: slack-notification
|
||||
icon: slack
|
||||
@@ -157,13 +166,20 @@ resources:
|
||||
jobs:
|
||||
- name: build-ci-images
|
||||
plan:
|
||||
- get: ci-images-git-repo
|
||||
trigger: true
|
||||
- in_parallel:
|
||||
- get: git-repo
|
||||
- get: ci-images-git-repo
|
||||
trigger: true
|
||||
- task: build-ci-image
|
||||
privileged: true
|
||||
file: git-repo/ci/tasks/build-ci-image.yml
|
||||
output_mapping:
|
||||
image: ci-image
|
||||
vars:
|
||||
ci-image-name: ci-image
|
||||
<<: *registry-mirror-vars
|
||||
- put: ci-image
|
||||
params:
|
||||
build: ci-images-git-repo/ci/images
|
||||
dockerfile: ci-images-git-repo/ci/images/ci-image/Dockerfile
|
||||
image: ci-image/image.tar
|
||||
- name: build
|
||||
serial: true
|
||||
public: true
|
||||
@@ -249,7 +265,7 @@ jobs:
|
||||
<<: *slack-fail-params
|
||||
- put: repo-status-jdk11-build
|
||||
params: { state: "success", commit: "git-repo" }
|
||||
- name: jdk16-build
|
||||
- name: jdk17-build
|
||||
serial: true
|
||||
public: true
|
||||
plan:
|
||||
@@ -257,7 +273,7 @@ jobs:
|
||||
- get: git-repo
|
||||
- get: every-morning
|
||||
trigger: true
|
||||
- put: repo-status-jdk16-build
|
||||
- put: repo-status-jdk17-build
|
||||
params: { state: "pending", commit: "git-repo" }
|
||||
- do:
|
||||
- task: check-project
|
||||
@@ -270,12 +286,12 @@ jobs:
|
||||
<<: *build-project-task-params
|
||||
on_failure:
|
||||
do:
|
||||
- put: repo-status-jdk16-build
|
||||
- put: repo-status-jdk17-build
|
||||
params: { state: "failure", commit: "git-repo" }
|
||||
- put: slack-alert
|
||||
params:
|
||||
<<: *slack-fail-params
|
||||
- put: repo-status-jdk16-build
|
||||
- put: repo-status-jdk17-build
|
||||
params: { state: "success", commit: "git-repo" }
|
||||
- name: build-pull-requests
|
||||
serial: true
|
||||
@@ -340,7 +356,6 @@ jobs:
|
||||
download_artifacts: false
|
||||
save_build_info: true
|
||||
- task: promote
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/promote-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: M
|
||||
@@ -385,7 +400,6 @@ jobs:
|
||||
download_artifacts: false
|
||||
save_build_info: true
|
||||
- task: promote
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/promote-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: RC
|
||||
@@ -430,7 +444,6 @@ jobs:
|
||||
download_artifacts: true
|
||||
save_build_info: true
|
||||
- task: promote
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/promote-version.yml
|
||||
params:
|
||||
RELEASE_TYPE: RELEASE
|
||||
@@ -458,7 +471,7 @@ jobs:
|
||||
|
||||
groups:
|
||||
- name: "builds"
|
||||
jobs: ["build", "jdk11-build", "jdk16-build"]
|
||||
jobs: ["build", "jdk11-build", "jdk17-build"]
|
||||
- name: "releases"
|
||||
jobs: ["stage-milestone", "stage-rc", "stage-release", "promote-milestone", "promote-rc", "promote-release", "create-github-release"]
|
||||
- name: "ci-images"
|
||||
|
||||
@@ -6,11 +6,11 @@ CONFIG_DIR=git-repo/ci/config
|
||||
version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
|
||||
export BUILD_INFO_LOCATION=$(pwd)/artifactory-repo/build-info.json
|
||||
|
||||
java -jar /opt/concourse-release-scripts.jar \
|
||||
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 /opt/concourse-release-scripts.jar \
|
||||
java -jar /concourse-release-scripts.jar \
|
||||
--spring.config.location=${CONFIG_DIR}/release-scripts.yml \
|
||||
promote $RELEASE_TYPE $BUILD_INFO_LOCATION || { exit 1; }
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: concourse/oci-build-task
|
||||
tag: 0.9.1
|
||||
registry_mirror:
|
||||
host: ((registry-mirror-host))
|
||||
username: ((registry-mirror-username))
|
||||
password: ((registry-mirror-password))
|
||||
inputs:
|
||||
- name: ci-images-git-repo
|
||||
outputs:
|
||||
- name: image
|
||||
caches:
|
||||
- path: ci-image-cache
|
||||
params:
|
||||
CONTEXT: ci-images-git-repo/ci/images
|
||||
DOCKERFILE: ci-images-git-repo/ci/images/ci-image/Dockerfile
|
||||
DOCKER_HUB_AUTH: ((docker-hub-auth))
|
||||
run:
|
||||
path: /bin/sh
|
||||
args:
|
||||
- "-c"
|
||||
- |
|
||||
mkdir -p /root/.docker
|
||||
cat > /root/.docker/config.json <<EOF
|
||||
{ "auths": { "https://index.docker.io/v1/": { "auth": "$DOCKER_HUB_AUTH" }}}
|
||||
EOF
|
||||
build
|
||||
@@ -1,5 +1,10 @@
|
||||
---
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: springio/concourse-release-scripts
|
||||
tag: '0.3.4'
|
||||
inputs:
|
||||
- name: git-repo
|
||||
- name: artifactory-repo
|
||||
@@ -13,6 +18,6 @@ params:
|
||||
SONATYPE_USER:
|
||||
SONATYPE_PASSWORD:
|
||||
SONATYPE_URL:
|
||||
SONATYPE_STAGING_PROFILE_ID:
|
||||
SONATYPE_STAGING_PROFILE:
|
||||
run:
|
||||
path: git-repo/ci/scripts/promote-version.sh
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
version=5.3.13
|
||||
version=5.3.20
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
org.gradle.caching=true
|
||||
org.gradle.parallel=true
|
||||
|
||||
+18
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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,6 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
|
||||
import org.springframework.context.annotation.ScopeMetadata;
|
||||
import org.springframework.context.annotation.ScopeMetadataResolver;
|
||||
import org.springframework.context.annotation.ScopedProxyMode;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
@@ -307,29 +306,26 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext();
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
|
||||
scanner.setIncludeAnnotationConfig(false);
|
||||
scanner.setScopeMetadataResolver(new ScopeMetadataResolver() {
|
||||
@Override
|
||||
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
|
||||
ScopeMetadata metadata = new ScopeMetadata();
|
||||
if (definition instanceof AnnotatedBeanDefinition) {
|
||||
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
|
||||
for (String type : annDef.getMetadata().getAnnotationTypes()) {
|
||||
if (type.equals(javax.inject.Singleton.class.getName())) {
|
||||
metadata.setScopeName(BeanDefinition.SCOPE_SINGLETON);
|
||||
break;
|
||||
}
|
||||
else if (annDef.getMetadata().getMetaAnnotationTypes(type).contains(javax.inject.Scope.class.getName())) {
|
||||
metadata.setScopeName(type.substring(type.length() - 13, type.length() - 6).toLowerCase());
|
||||
metadata.setScopedProxyMode(scopedProxyMode);
|
||||
break;
|
||||
}
|
||||
else if (type.startsWith("javax.inject")) {
|
||||
metadata.setScopeName(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
}
|
||||
scanner.setScopeMetadataResolver(definition -> {
|
||||
ScopeMetadata metadata = new ScopeMetadata();
|
||||
if (definition instanceof AnnotatedBeanDefinition) {
|
||||
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
|
||||
for (String type : annDef.getMetadata().getAnnotationTypes()) {
|
||||
if (type.equals(javax.inject.Singleton.class.getName())) {
|
||||
metadata.setScopeName(BeanDefinition.SCOPE_SINGLETON);
|
||||
break;
|
||||
}
|
||||
else if (annDef.getMetadata().getMetaAnnotationTypes(type).contains(javax.inject.Scope.class.getName())) {
|
||||
metadata.setScopeName(type.substring(type.length() - 13, type.length() - 6).toLowerCase());
|
||||
metadata.setScopedProxyMode(scopedProxyMode);
|
||||
break;
|
||||
}
|
||||
else if (type.startsWith("javax.inject")) {
|
||||
metadata.setScopeName(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
}
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
return metadata;
|
||||
});
|
||||
|
||||
// Scan twice in order to find errors in the bean definition compatibility check.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -74,7 +74,7 @@ class ScheduledAndTransactionalAnnotationIntegrationTests {
|
||||
|
||||
MyRepository repository = ctx.getBean(MyRepository.class);
|
||||
CallCountingTransactionManager txManager = ctx.getBean(CallCountingTransactionManager.class);
|
||||
assertThat(AopUtils.isCglibProxy(repository)).isEqualTo(true);
|
||||
assertThat(AopUtils.isCglibProxy(repository)).isTrue();
|
||||
assertThat(repository.getInvocationCount()).isGreaterThan(0);
|
||||
assertThat(txManager.commits).isGreaterThan(0);
|
||||
}
|
||||
|
||||
+4
-3
@@ -1,13 +1,14 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
maven { url "https://repo.spring.io/plugins-release" }
|
||||
maven { url "https://repo.spring.io/release" }
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "com.gradle.enterprise" version "3.6.1"
|
||||
id "io.spring.ge.conventions" version "0.0.7"
|
||||
id "com.gradle.enterprise" version "3.9"
|
||||
id "io.spring.ge.conventions" version "0.0.9"
|
||||
}
|
||||
|
||||
include "spring-aop"
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,7 +34,7 @@ import org.springframework.util.ClassUtils;
|
||||
/**
|
||||
* AspectJ-based proxy factory, allowing for programmatic building
|
||||
* of proxies which include AspectJ aspects (code style as well
|
||||
* Java 5 annotation style).
|
||||
* annotation style).
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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,8 +60,8 @@ public class AspectMetadata implements Serializable {
|
||||
private final Class<?> aspectClass;
|
||||
|
||||
/**
|
||||
* AspectJ reflection information (AspectJ 5 / Java 5 specific).
|
||||
* Re-resolved on deserialization since it isn't serializable itself.
|
||||
* AspectJ reflection information.
|
||||
* <p>Re-resolved on deserialization since it isn't serializable itself.
|
||||
*/
|
||||
private transient AjType<?> ajType;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -44,6 +44,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @see org.springframework.aop.support.AopUtils
|
||||
*/
|
||||
public abstract class AopProxyUtils {
|
||||
@@ -133,7 +134,7 @@ public abstract class AopProxyUtils {
|
||||
if (targetClass.isInterface()) {
|
||||
advised.setInterfaces(targetClass);
|
||||
}
|
||||
else if (Proxy.isProxyClass(targetClass)) {
|
||||
else if (Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
|
||||
advised.setInterfaces(targetClass.getInterfaces());
|
||||
}
|
||||
specifiedInterfaces = advised.getProxiedInterfaces();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -375,6 +375,22 @@ 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.
|
||||
@@ -425,7 +441,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
@Override
|
||||
@Nullable
|
||||
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
|
||||
Object retVal = methodProxy.invoke(this.target, args);
|
||||
Object retVal = invokeMethod(this.target, method, args, methodProxy);
|
||||
return processReturnType(proxy, this.target, method, retVal);
|
||||
}
|
||||
}
|
||||
@@ -450,7 +466,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
Object oldProxy = null;
|
||||
try {
|
||||
oldProxy = AopContext.setCurrentProxy(proxy);
|
||||
Object retVal = methodProxy.invoke(this.target, args);
|
||||
Object retVal = invokeMethod(this.target, method, args, methodProxy);
|
||||
return processReturnType(proxy, this.target, method, retVal);
|
||||
}
|
||||
finally {
|
||||
@@ -478,7 +494,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 = methodProxy.invoke(target, args);
|
||||
Object retVal = invokeMethod(target, method, args, methodProxy);
|
||||
return processReturnType(proxy, target, method, retVal);
|
||||
}
|
||||
finally {
|
||||
@@ -508,7 +524,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
Object target = this.targetSource.getTarget();
|
||||
try {
|
||||
oldProxy = AopContext.setCurrentProxy(proxy);
|
||||
Object retVal = methodProxy.invoke(target, args);
|
||||
Object retVal = invokeMethod(target, method, args, methodProxy);
|
||||
return processReturnType(proxy, target, method, retVal);
|
||||
}
|
||||
finally {
|
||||
@@ -685,13 +701,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
// it does nothing but a reflective operation on the target, and no hot
|
||||
// swapping or fancy proxying.
|
||||
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
|
||||
try {
|
||||
retVal = methodProxy.invoke(target, argsToUse);
|
||||
}
|
||||
catch (CodeGenerationException ex) {
|
||||
CglibMethodInvocation.logFastClassGenerationFailure(method);
|
||||
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
|
||||
}
|
||||
retVal = invokeMethod(target, method, argsToUse, methodProxy);
|
||||
}
|
||||
else {
|
||||
// We need to create a method invocation...
|
||||
|
||||
+6
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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,6 +21,7 @@ import java.lang.reflect.Proxy;
|
||||
|
||||
import org.springframework.aop.SpringProxy;
|
||||
import org.springframework.core.NativeDetector;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Default {@link AopProxyFactory} implementation, creating either a CGLIB proxy
|
||||
@@ -40,14 +41,16 @@ import org.springframework.core.NativeDetector;
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Sebastien Deleuze
|
||||
* @author Sam Brannen
|
||||
* @since 12.03.2004
|
||||
* @see AdvisedSupport#setOptimize
|
||||
* @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 {
|
||||
@@ -58,7 +61,7 @@ public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
|
||||
throw new AopConfigException("TargetSource cannot determine target class: " +
|
||||
"Either an interface or a target is required for proxy creation.");
|
||||
}
|
||||
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
|
||||
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
|
||||
return new JdkDynamicAopProxy(config);
|
||||
}
|
||||
return new ObjenesisCglibAopProxy(config);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -421,11 +421,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
* are unaffected by such changes.
|
||||
*/
|
||||
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
|
||||
if (this.advisorChainInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
|
||||
if (!this.advisorChainInitialized && !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));
|
||||
@@ -464,9 +460,9 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
addAdvisorOnChainCreation(advice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.advisorChainInitialized = true;
|
||||
this.advisorChainInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,8 +25,8 @@ import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.ThrowsAdvice;
|
||||
|
||||
/**
|
||||
* Adapter to enable {@link org.springframework.aop.MethodBeforeAdvice}
|
||||
* to be used in the Spring AOP framework.
|
||||
* Adapter to enable {@link org.springframework.aop.ThrowsAdvice} to be used
|
||||
* in the Spring AOP framework.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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,6 +50,7 @@ import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostP
|
||||
import org.springframework.core.SmartClassLoader;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -85,6 +86,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Juergen Hoeller
|
||||
* @author Rod Johnson
|
||||
* @author Rob Harrop
|
||||
* @author Sam Brannen
|
||||
* @since 13.10.2003
|
||||
* @see #setInterceptorNames
|
||||
* @see #getAdvicesAndAdvisorsForBean
|
||||
@@ -442,8 +444,8 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
proxyFactory.copyFrom(this);
|
||||
|
||||
if (proxyFactory.isProxyTargetClass()) {
|
||||
// Explicit handling of JDK proxy targets (for introduction advice scenarios)
|
||||
if (Proxy.isProxyClass(beanClass)) {
|
||||
// Explicit handling of JDK proxy targets and lambdas (for introduction advice scenarios)
|
||||
if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {
|
||||
// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
|
||||
for (Class<?> ifc : beanClass.getInterfaces()) {
|
||||
proxyFactory.addInterface(ifc);
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -233,7 +233,8 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
return beanFactory.getBean(TaskExecutor.class);
|
||||
}
|
||||
catch (NoUniqueBeanDefinitionException ex) {
|
||||
logger.debug("Could not find unique TaskExecutor bean", ex);
|
||||
logger.debug("Could not find unique TaskExecutor bean. " +
|
||||
"Continuing search for an Executor bean named 'taskExecutor'", ex);
|
||||
try {
|
||||
return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
|
||||
}
|
||||
@@ -246,7 +247,8 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
}
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
logger.debug("Could not find default TaskExecutor bean", ex);
|
||||
logger.debug("Could not find default TaskExecutor bean. " +
|
||||
"Continuing search for an Executor bean named 'taskExecutor'", ex);
|
||||
try {
|
||||
return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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,8 +183,8 @@ public abstract class AopUtils {
|
||||
* may be {@code DefaultFoo}. In this case, the method may be
|
||||
* {@code DefaultFoo.bar()}. This enables attributes on that method to be found.
|
||||
* <p><b>NOTE:</b> In contrast to {@link org.springframework.util.ClassUtils#getMostSpecificMethod},
|
||||
* this method resolves Java 5 bridge methods in order to retrieve attributes
|
||||
* from the <i>original</i> method definition.
|
||||
* this method resolves bridge methods in order to retrieve attributes from
|
||||
* the <i>original</i> method definition.
|
||||
* @param method the method to be invoked, which may come from an interface
|
||||
* @param targetClass the target class for the current invocation.
|
||||
* May be {@code null} or may not even implement the method.
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,8 +24,7 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple ClassFilter that looks for a specific Java 5 annotation
|
||||
* being present on a class.
|
||||
* Simple ClassFilter that looks for a specific annotation being present on a class.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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,8 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple Pointcut that looks for a specific Java 5 annotation
|
||||
* being present on a {@link #forClassAnnotation class} or
|
||||
* {@link #forMethodAnnotation method}.
|
||||
* Simple {@link Pointcut} that looks for a specific annotation being present on a
|
||||
* {@linkplain #forClassAnnotation class} or {@linkplain #forMethodAnnotation method}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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,9 +27,10 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple MethodMatcher that looks for a specific Java 5 annotation
|
||||
* being present on a method (checking both the method on the invoked
|
||||
* interface, if any, and the corresponding method on the target class).
|
||||
* Simple {@link org.springframework.aop.MethodMatcher MethodMatcher} that looks
|
||||
* for a specific annotation being present on a method (checking both the method
|
||||
* on the invoked interface, if any, and the corresponding method on the target
|
||||
* class).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.aspectj;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Additional parameter name discover tests that need Java 5.
|
||||
* Yes this will re-run the tests from the superclass, but that
|
||||
* doesn't matter in the grand scheme of things...
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class AspectJAdviceParameterNameDiscoverAnnotationTests extends AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
@Test
|
||||
public void testAnnotationBinding() {
|
||||
assertParameterNames(getMethod("pjpAndAnAnnotation"),
|
||||
"execution(* *(..)) && @annotation(ann)",
|
||||
new String[] {"thisJoinPoint","ann"});
|
||||
}
|
||||
|
||||
|
||||
public void pjpAndAnAnnotation(ProceedingJoinPoint pjp, MyAnnotation ann) {}
|
||||
|
||||
@interface MyAnnotation {}
|
||||
|
||||
}
|
||||
+259
-195
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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,8 +17,11 @@
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer.AmbiguousBindingException;
|
||||
@@ -27,200 +30,265 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link AspectJAdviceParameterNameDiscoverer} class.
|
||||
*
|
||||
* <p>See also {@link TigerAspectJAdviceParameterNameDiscovererTests} for tests relating to annotations.
|
||||
* Unit tests for {@link AspectJAdviceParameterNameDiscoverer}.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Chris Beams
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public class AspectJAdviceParameterNameDiscovererTests {
|
||||
class AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
@Test
|
||||
public void testNoArgs() {
|
||||
assertParameterNames(getMethod("noArgs"), "execution(* *(..))", new String[0]);
|
||||
@Nested
|
||||
class StandardTests {
|
||||
|
||||
@Test
|
||||
void noArgs() {
|
||||
assertParameterNames(getMethod("noArgs"), "execution(* *(..))", new String[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
void joinPointOnly() {
|
||||
assertParameterNames(getMethod("tjp"), "execution(* *(..))", new String[] {"thisJoinPoint"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void joinPointStaticPartOnly() {
|
||||
assertParameterNames(getMethod("tjpsp"), "execution(* *(..))", new String[] {"thisJoinPointStaticPart"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void twoJoinPoints() {
|
||||
assertException(getMethod("twoJoinPoints"), "foo()", IllegalStateException.class,
|
||||
"Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
}
|
||||
|
||||
@Test
|
||||
void oneThrowable() {
|
||||
assertParameterNames(getMethod("oneThrowable"), "foo()", null, "ex", new String[] {"ex"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void oneJPAndOneThrowable() {
|
||||
assertParameterNames(getMethod("jpAndOneThrowable"), "foo()", null, "ex", new String[] {"thisJoinPoint", "ex"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void oneJPAndTwoThrowables() {
|
||||
assertException(getMethod("jpAndTwoThrowables"), "foo()", null, "ex", AmbiguousBindingException.class,
|
||||
"Binding of throwing parameter 'ex' is ambiguous: could be bound to argument 1 or argument 2");
|
||||
}
|
||||
|
||||
@Test
|
||||
void throwableNoCandidates() {
|
||||
assertException(getMethod("noArgs"), "foo()", null, "ex", IllegalStateException.class,
|
||||
"Not enough arguments in method to satisfy binding of returning and throwing variables");
|
||||
}
|
||||
|
||||
@Test
|
||||
void returning() {
|
||||
assertParameterNames(getMethod("oneObject"), "foo()", "obj", null, new String[] {"obj"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void ambiguousReturning() {
|
||||
assertException(getMethod("twoObjects"), "foo()", "obj", null, AmbiguousBindingException.class,
|
||||
"Binding of returning parameter 'obj' is ambiguous, there are 2 candidates.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void returningNoCandidates() {
|
||||
assertException(getMethod("noArgs"), "foo()", "obj", null, IllegalStateException.class,
|
||||
"Not enough arguments in method to satisfy binding of returning and throwing variables");
|
||||
}
|
||||
|
||||
@Test
|
||||
void thisBindingOneCandidate() {
|
||||
assertParameterNames(getMethod("oneObject"), "this(x)", new String[] {"x"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void thisBindingWithAlternateTokenizations() {
|
||||
assertParameterNames(getMethod("oneObject"), "this( x )", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "this( x)", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "this (x )", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "this(x )", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "foo() && this(x)", new String[] {"x"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void thisBindingTwoCandidates() {
|
||||
assertException(getMethod("oneObject"), "this(x) || this(y)", AmbiguousBindingException.class,
|
||||
"Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
|
||||
}
|
||||
|
||||
@Test
|
||||
void thisBindingWithBadPointcutExpressions() {
|
||||
assertException(getMethod("oneObject"), "this(", IllegalStateException.class,
|
||||
"Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
assertException(getMethod("oneObject"), "this(x && foo()", IllegalStateException.class,
|
||||
"Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
}
|
||||
|
||||
@Test
|
||||
void targetBindingOneCandidate() {
|
||||
assertParameterNames(getMethod("oneObject"), "target(x)", new String[] {"x"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void targetBindingWithAlternateTokenizations() {
|
||||
assertParameterNames(getMethod("oneObject"), "target( x )", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "target( x)", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "target (x )", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "target(x )", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "foo() && target(x)", new String[] {"x"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void targetBindingTwoCandidates() {
|
||||
assertException(getMethod("oneObject"), "target(x) || target(y)", AmbiguousBindingException.class,
|
||||
"Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
|
||||
}
|
||||
|
||||
@Test
|
||||
void targetBindingWithBadPointcutExpressions() {
|
||||
assertException(getMethod("oneObject"), "target(", IllegalStateException.class,
|
||||
"Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
assertException(getMethod("oneObject"), "target(x && foo()", IllegalStateException.class,
|
||||
"Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
}
|
||||
|
||||
@Test
|
||||
void argsBindingOneObject() {
|
||||
assertParameterNames(getMethod("oneObject"), "args(x)", new String[] {"x"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void argsBindingOneObjectTwoCandidates() {
|
||||
assertException(getMethod("oneObject"), "args(x,y)", AmbiguousBindingException.class,
|
||||
"Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
|
||||
}
|
||||
|
||||
@Test
|
||||
void ambiguousArgsBinding() {
|
||||
assertException(getMethod("twoObjects"), "args(x,y)", AmbiguousBindingException.class,
|
||||
"Still 2 unbound args at this(),target(),args() binding stage, with no way to determine between them");
|
||||
}
|
||||
|
||||
@Test
|
||||
void argsOnePrimitive() {
|
||||
assertParameterNames(getMethod("onePrimitive"), "args(count)", new String[] {"count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void argsOnePrimitiveOneObject() {
|
||||
assertException(getMethod("oneObjectOnePrimitive"), "args(count,obj)", AmbiguousBindingException.class,
|
||||
"Found 2 candidate variable names but only one candidate binding slot when matching primitive args");
|
||||
}
|
||||
|
||||
@Test
|
||||
void thisAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && this(obj)",
|
||||
new String[] {"obj", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void targetAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && target(obj)",
|
||||
new String[] {"obj", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void throwingAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneThrowableOnePrimitive"), "args(count)", null, "ex",
|
||||
new String[] {"ex", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void allTogetherNow() {
|
||||
assertParameterNames(getMethod("theBigOne"), "this(foo) && args(x)", null, "ex",
|
||||
new String[] {"thisJoinPoint", "ex", "x", "foo"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void referenceBinding() {
|
||||
assertParameterNames(getMethod("onePrimitive"),"somepc(foo)", new String[] {"foo"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void referenceBindingWithAlternateTokenizations() {
|
||||
assertParameterNames(getMethod("onePrimitive"),"call(bar *) && somepc(foo)", new String[] {"foo"});
|
||||
assertParameterNames(getMethod("onePrimitive"),"somepc ( foo )", new String[] {"foo"});
|
||||
assertParameterNames(getMethod("onePrimitive"),"somepc( foo)", new String[] {"foo"});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJoinPointOnly() {
|
||||
assertParameterNames(getMethod("tjp"), "execution(* *(..))", new String[] {"thisJoinPoint"});
|
||||
}
|
||||
/**
|
||||
* Tests just the annotation binding part of {@link AspectJAdviceParameterNameDiscoverer}.
|
||||
*/
|
||||
@Nested
|
||||
class AnnotationTests {
|
||||
|
||||
@Test
|
||||
public void testJoinPointStaticPartOnly() {
|
||||
assertParameterNames(getMethod("tjpsp"), "execution(* *(..))", new String[] {"thisJoinPointStaticPart"});
|
||||
}
|
||||
@Test
|
||||
void atThis() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@this(a)", new String[] {"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoJoinPoints() {
|
||||
assertException(getMethod("twoJoinPoints"), "foo()", IllegalStateException.class,
|
||||
"Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
}
|
||||
@Test
|
||||
void atTarget() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@target(a)", new String[] {"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneThrowable() {
|
||||
assertParameterNames(getMethod("oneThrowable"), "foo()", null, "ex", new String[] {"ex"});
|
||||
}
|
||||
@Test
|
||||
void atArgs() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@args(a)", new String[] {"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneJPAndOneThrowable() {
|
||||
assertParameterNames(getMethod("jpAndOneThrowable"), "foo()", null, "ex", new String[] {"thisJoinPoint", "ex"});
|
||||
}
|
||||
@Test
|
||||
void atWithin() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@within(a)", new String[] {"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneJPAndTwoThrowables() {
|
||||
assertException(getMethod("jpAndTwoThrowables"), "foo()", null, "ex", AmbiguousBindingException.class,
|
||||
"Binding of throwing parameter 'ex' is ambiguous: could be bound to argument 1 or argument 2");
|
||||
}
|
||||
@Test
|
||||
void atWithincode() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@withincode(a)", new String[] {"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrowableNoCandidates() {
|
||||
assertException(getMethod("noArgs"), "foo()", null, "ex", IllegalStateException.class,
|
||||
"Not enough arguments in method to satisfy binding of returning and throwing variables");
|
||||
}
|
||||
@Test
|
||||
void atAnnotation() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@annotation(a)", new String[] {"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReturning() {
|
||||
assertParameterNames(getMethod("oneObject"), "foo()", "obj", null, new String[] {"obj"});
|
||||
}
|
||||
@Test
|
||||
void ambiguousAnnotationTwoVars() {
|
||||
assertException(getMethod("twoAnnotations"),"@annotation(a) && @this(x)", AmbiguousBindingException.class,
|
||||
"Found 2 potential annotation variable(s), and 2 potential argument slots");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAmbiguousReturning() {
|
||||
assertException(getMethod("twoObjects"), "foo()", "obj", null, AmbiguousBindingException.class,
|
||||
"Binding of returning parameter 'obj' is ambiguous, there are 2 candidates.");
|
||||
}
|
||||
@Test
|
||||
void ambiguousAnnotationOneVar() {
|
||||
assertException(getMethod("oneAnnotation"),"@annotation(a) && @this(x)",IllegalArgumentException.class,
|
||||
"Found 2 candidate annotation binding variables but only one potential argument binding slot");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReturningNoCandidates() {
|
||||
assertException(getMethod("noArgs"), "foo()", "obj", null, IllegalStateException.class,
|
||||
"Not enough arguments in method to satisfy binding of returning and throwing variables");
|
||||
}
|
||||
@Test
|
||||
void annotationMedley() {
|
||||
assertParameterNames(getMethod("annotationMedley"),"@annotation(a) && args(count) && this(foo)",
|
||||
null, "ex", new String[] {"ex", "foo", "count", "a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThisBindingOneCandidate() {
|
||||
assertParameterNames(getMethod("oneObject"), "this(x)", new String[] {"x"});
|
||||
}
|
||||
@Test
|
||||
void annotationBinding() {
|
||||
assertParameterNames(getMethod("pjpAndAnAnnotation"),
|
||||
"execution(* *(..)) && @annotation(ann)",
|
||||
new String[] {"thisJoinPoint","ann"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThisBindingWithAlternateTokenizations() {
|
||||
assertParameterNames(getMethod("oneObject"), "this( x )", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "this( x)", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "this (x )", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "this(x )", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "foo() && this(x)", new String[] {"x"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThisBindingTwoCandidates() {
|
||||
assertException(getMethod("oneObject"), "this(x) || this(y)", AmbiguousBindingException.class,
|
||||
"Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThisBindingWithBadPointcutExpressions() {
|
||||
assertException(getMethod("oneObject"), "this(", IllegalStateException.class,
|
||||
"Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
assertException(getMethod("oneObject"), "this(x && foo()", IllegalStateException.class,
|
||||
"Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargetBindingOneCandidate() {
|
||||
assertParameterNames(getMethod("oneObject"), "target(x)", new String[] {"x"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargetBindingWithAlternateTokenizations() {
|
||||
assertParameterNames(getMethod("oneObject"), "target( x )", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "target( x)", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "target (x )", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "target(x )", new String[] {"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "foo() && target(x)", new String[] {"x"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargetBindingTwoCandidates() {
|
||||
assertException(getMethod("oneObject"), "target(x) || target(y)", AmbiguousBindingException.class,
|
||||
"Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargetBindingWithBadPointcutExpressions() {
|
||||
assertException(getMethod("oneObject"), "target(", IllegalStateException.class,
|
||||
"Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
assertException(getMethod("oneObject"), "target(x && foo()", IllegalStateException.class,
|
||||
"Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArgsBindingOneObject() {
|
||||
assertParameterNames(getMethod("oneObject"), "args(x)", new String[] {"x"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArgsBindingOneObjectTwoCandidates() {
|
||||
assertException(getMethod("oneObject"), "args(x,y)", AmbiguousBindingException.class,
|
||||
"Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAmbiguousArgsBinding() {
|
||||
assertException(getMethod("twoObjects"), "args(x,y)", AmbiguousBindingException.class,
|
||||
"Still 2 unbound args at this(),target(),args() binding stage, with no way to determine between them");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArgsOnePrimitive() {
|
||||
assertParameterNames(getMethod("onePrimitive"), "args(count)", new String[] {"count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArgsOnePrimitiveOneObject() {
|
||||
assertException(getMethod("oneObjectOnePrimitive"), "args(count,obj)", AmbiguousBindingException.class,
|
||||
"Found 2 candidate variable names but only one candidate binding slot when matching primitive args");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThisAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && this(obj)",
|
||||
new String[] {"obj", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargetAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && target(obj)",
|
||||
new String[] {"obj", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrowingAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneThrowableOnePrimitive"), "args(count)", null, "ex",
|
||||
new String[] {"ex", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllTogetherNow() {
|
||||
assertParameterNames(getMethod("theBigOne"), "this(foo) && args(x)", null, "ex",
|
||||
new String[] {"thisJoinPoint", "ex", "x", "foo"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReferenceBinding() {
|
||||
assertParameterNames(getMethod("onePrimitive"),"somepc(foo)", new String[] {"foo"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReferenceBindingWithAlternateTokenizations() {
|
||||
assertParameterNames(getMethod("onePrimitive"),"call(bar *) && somepc(foo)", new String[] {"foo"});
|
||||
assertParameterNames(getMethod("onePrimitive"),"somepc ( foo )", new String[] {"foo"});
|
||||
assertParameterNames(getMethod("onePrimitive"),"somepc( foo)", new String[] {"foo"});
|
||||
}
|
||||
|
||||
|
||||
protected Method getMethod(String name) {
|
||||
private Method getMethod(String name) {
|
||||
// Assumes no overloading of test methods...
|
||||
Method[] candidates = getClass().getMethods();
|
||||
for (Method candidate : candidates) {
|
||||
for (Method candidate : getClass().getMethods()) {
|
||||
if (candidate.getName().equals(name)) {
|
||||
return candidate;
|
||||
}
|
||||
@@ -228,11 +296,11 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
throw new AssertionError("Bad test specification, no method '" + name + "' found in test class");
|
||||
}
|
||||
|
||||
protected void assertParameterNames(Method method, String pointcut, String[] parameterNames) {
|
||||
private void assertParameterNames(Method method, String pointcut, String[] parameterNames) {
|
||||
assertParameterNames(method, pointcut, null, null, parameterNames);
|
||||
}
|
||||
|
||||
protected void assertParameterNames(
|
||||
private void assertParameterNames(
|
||||
Method method, String pointcut, String returning, String throwing, String[] parameterNames) {
|
||||
|
||||
assertThat(parameterNames.length).as("bad test specification, must have same number of parameter names as method arguments").isEqualTo(method.getParameterCount());
|
||||
@@ -243,8 +311,8 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
discoverer.setThrowingName(throwing);
|
||||
String[] discoveredNames = discoverer.getParameterNames(method);
|
||||
|
||||
String formattedExpectedNames = format(parameterNames);
|
||||
String formattedActualNames = format(discoveredNames);
|
||||
String formattedExpectedNames = Arrays.toString(parameterNames);
|
||||
String formattedActualNames = Arrays.toString(discoveredNames);
|
||||
|
||||
assertThat(discoveredNames.length).as("Expecting " + parameterNames.length + " parameter names in return set '" +
|
||||
formattedExpectedNames + "', but found " + discoveredNames.length +
|
||||
@@ -257,37 +325,23 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
}
|
||||
}
|
||||
|
||||
protected void assertException(Method method, String pointcut, Class<? extends Throwable> exceptionType, String message) {
|
||||
private void assertException(Method method, String pointcut, Class<? extends Throwable> exceptionType, String message) {
|
||||
assertException(method, pointcut, null, null, exceptionType, message);
|
||||
}
|
||||
|
||||
protected void assertException(Method method, String pointcut, String returning,
|
||||
private void assertException(Method method, String pointcut, String returning,
|
||||
String throwing, Class<? extends Throwable> exceptionType, String message) {
|
||||
|
||||
AspectJAdviceParameterNameDiscoverer discoverer = new AspectJAdviceParameterNameDiscoverer(pointcut);
|
||||
discoverer.setRaiseExceptions(true);
|
||||
discoverer.setReturningName(returning);
|
||||
discoverer.setThrowingName(throwing);
|
||||
assertThatExceptionOfType(exceptionType).isThrownBy(() ->
|
||||
discoverer.getParameterNames(method))
|
||||
assertThatExceptionOfType(exceptionType)
|
||||
.isThrownBy(() -> discoverer.getParameterNames(method))
|
||||
.withMessageContaining(message);
|
||||
}
|
||||
|
||||
|
||||
private static String format(String[] names) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('(');
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
sb.append(names[i]);
|
||||
if ((i + 1) < names.length) {
|
||||
sb.append(',');
|
||||
}
|
||||
}
|
||||
sb.append(')');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
// Methods to discover parameter names for
|
||||
|
||||
public void noArgs() {
|
||||
@@ -329,4 +383,14 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
public void theBigOne(JoinPoint jp, Throwable x, int y, Object foo) {
|
||||
}
|
||||
|
||||
public void oneAnnotation(MyAnnotation ann) {}
|
||||
|
||||
public void twoAnnotations(MyAnnotation ann, MyAnnotation anotherAnn) {}
|
||||
|
||||
public void annotationMedley(Throwable t, Object foo, int x, MyAnnotation ma) {}
|
||||
|
||||
public void pjpAndAnAnnotation(ProceedingJoinPoint pjp, MyAnnotation ann) {}
|
||||
|
||||
@interface MyAnnotation {}
|
||||
|
||||
}
|
||||
|
||||
+286
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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,6 +17,9 @@
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
@@ -25,6 +28,8 @@ import org.aspectj.weaver.tools.PointcutPrimitive;
|
||||
import org.aspectj.weaver.tools.UnsupportedPointcutPrimitiveException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import test.annotation.EmptySpringAnnotation;
|
||||
import test.annotation.transaction.Tx;
|
||||
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.MethodMatcher;
|
||||
@@ -56,12 +61,19 @@ public class AspectJExpressionPointcutTests {
|
||||
|
||||
private Method setSomeNumber;
|
||||
|
||||
private final Map<String, Method> methodsOnHasGeneric = new HashMap<>();
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws NoSuchMethodException {
|
||||
getAge = TestBean.class.getMethod("getAge");
|
||||
setAge = TestBean.class.getMethod("setAge", int.class);
|
||||
setSomeNumber = TestBean.class.getMethod("setSomeNumber", Number.class);
|
||||
|
||||
// Assumes no overloading
|
||||
for (Method method : HasGeneric.class.getMethods()) {
|
||||
methodsOnHasGeneric.put(method.getName(), method);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -299,6 +311,279 @@ public class AspectJExpressionPointcutTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchGenericArgument() {
|
||||
String expression = "execution(* set*(java.util.List<org.springframework.beans.testfixture.beans.TestBean>) )";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
// TODO this will currently map, would be nice for optimization
|
||||
//assertTrue(ajexp.matches(HasGeneric.class));
|
||||
//assertFalse(ajexp.matches(TestBean.class));
|
||||
|
||||
Method takesGenericList = methodsOnHasGeneric.get("setFriends");
|
||||
assertThat(ajexp.matches(takesGenericList, HasGeneric.class)).isTrue();
|
||||
assertThat(ajexp.matches(methodsOnHasGeneric.get("setEnemies"), HasGeneric.class)).isTrue();
|
||||
assertThat(ajexp.matches(methodsOnHasGeneric.get("setPartners"), HasGeneric.class)).isFalse();
|
||||
assertThat(ajexp.matches(methodsOnHasGeneric.get("setPhoneNumbers"), HasGeneric.class)).isFalse();
|
||||
|
||||
assertThat(ajexp.matches(getAge, TestBean.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchVarargs() throws Exception {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
class MyTemplate {
|
||||
public int queryForInt(String sql, Object... params) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
String expression = "execution(int *.*(String, Object...))";
|
||||
AspectJExpressionPointcut jdbcVarArgs = new AspectJExpressionPointcut();
|
||||
jdbcVarArgs.setExpression(expression);
|
||||
|
||||
assertThat(jdbcVarArgs.matches(
|
||||
MyTemplate.class.getMethod("queryForInt", String.class, Object[].class),
|
||||
MyTemplate.class)).isTrue();
|
||||
|
||||
Method takesGenericList = methodsOnHasGeneric.get("setFriends");
|
||||
assertThat(jdbcVarArgs.matches(takesGenericList, HasGeneric.class)).isFalse();
|
||||
assertThat(jdbcVarArgs.matches(methodsOnHasGeneric.get("setEnemies"), HasGeneric.class)).isFalse();
|
||||
assertThat(jdbcVarArgs.matches(methodsOnHasGeneric.get("setPartners"), HasGeneric.class)).isFalse();
|
||||
assertThat(jdbcVarArgs.matches(methodsOnHasGeneric.get("setPhoneNumbers"), HasGeneric.class)).isFalse();
|
||||
assertThat(jdbcVarArgs.matches(getAge, TestBean.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithAtWithin() throws Exception {
|
||||
String expression = "@within(test.annotation.transaction.Tx)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithoutBinding() throws Exception {
|
||||
String expression = "within(@test.annotation.transaction.Tx *)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithSubpackageWildcard() throws Exception {
|
||||
String expression = "within(@(test.annotation..*) *)";
|
||||
AspectJExpressionPointcut springAnnotatedPc = testMatchAnnotationOnClass(expression);
|
||||
assertThat(springAnnotatedPc.matches(TestBean.class.getMethod("setName", String.class), TestBean.class)).isFalse();
|
||||
assertThat(springAnnotatedPc.matches(SpringAnnotated.class.getMethod("foo"), SpringAnnotated.class)).isTrue();
|
||||
|
||||
expression = "within(@(test.annotation.transaction..*) *)";
|
||||
AspectJExpressionPointcut springTxAnnotatedPc = testMatchAnnotationOnClass(expression);
|
||||
assertThat(springTxAnnotatedPc.matches(SpringAnnotated.class.getMethod("foo"), SpringAnnotated.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithExactPackageWildcard() throws Exception {
|
||||
String expression = "within(@(test.annotation.transaction.*) *)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
private AspectJExpressionPointcut testMatchAnnotationOnClass(String expression) throws Exception {
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
assertThat(ajexp.matches(getAge, TestBean.class)).isFalse();
|
||||
assertThat(ajexp.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class)).isTrue();
|
||||
assertThat(ajexp.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class)).isTrue();
|
||||
assertThat(ajexp.matches(BeanB.class.getMethod("setName", String.class), BeanB.class)).isTrue();
|
||||
assertThat(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
return ajexp;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodWithFQN() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
assertThat(ajexp.matches(getAge, TestBean.class)).isFalse();
|
||||
assertThat(ajexp.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(ajexp.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
assertThat(ajexp.matches(BeanA.class.getMethod("getAge"), BeanA.class)).isTrue();
|
||||
assertThat(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnCglibProxyMethod() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
ProxyFactory factory = new ProxyFactory(new BeanA());
|
||||
factory.setProxyTargetClass(true);
|
||||
BeanA proxy = (BeanA) factory.getProxy();
|
||||
assertThat(ajexp.matches(BeanA.class.getMethod("getAge"), proxy.getClass())).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnDynamicProxyMethod() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
ProxyFactory factory = new ProxyFactory(new BeanA());
|
||||
factory.setProxyTargetClass(false);
|
||||
IBeanA proxy = (IBeanA) factory.getProxy();
|
||||
assertThat(ajexp.matches(IBeanA.class.getMethod("getAge"), proxy.getClass())).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodWithWildcard() throws Exception {
|
||||
String expression = "execution(@(test.annotation..*) * *(..))";
|
||||
AspectJExpressionPointcut anySpringMethodAnnotation = new AspectJExpressionPointcut();
|
||||
anySpringMethodAnnotation.setExpression(expression);
|
||||
|
||||
assertThat(anySpringMethodAnnotation.matches(getAge, TestBean.class)).isFalse();
|
||||
assertThat(anySpringMethodAnnotation.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(anySpringMethodAnnotation.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
assertThat(anySpringMethodAnnotation.matches(BeanA.class.getMethod("getAge"), BeanA.class)).isTrue();
|
||||
assertThat(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodArgumentsWithFQN() throws Exception {
|
||||
String expression = "@args(*, test.annotation.EmptySpringAnnotation))";
|
||||
AspectJExpressionPointcut takesSpringAnnotatedArgument2 = new AspectJExpressionPointcut();
|
||||
takesSpringAnnotatedArgument2.setExpression(expression);
|
||||
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge"), BeanA.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesAnnotatedParameters", TestBean.class, SpringAnnotated.class),
|
||||
ProcessesSpringAnnotatedParameters.class)).isTrue();
|
||||
|
||||
// True because it maybeMatches with potential argument subtypes
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesNoAnnotatedParameters", TestBean.class, BeanA.class),
|
||||
ProcessesSpringAnnotatedParameters.class)).isTrue();
|
||||
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesNoAnnotatedParameters", TestBean.class, BeanA.class),
|
||||
ProcessesSpringAnnotatedParameters.class, new TestBean(), new BeanA())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodArgumentsWithWildcards() throws Exception {
|
||||
String expression = "execution(* *(*, @(test..*) *))";
|
||||
AspectJExpressionPointcut takesSpringAnnotatedArgument2 = new AspectJExpressionPointcut();
|
||||
takesSpringAnnotatedArgument2.setExpression(expression);
|
||||
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge"), BeanA.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesAnnotatedParameters", TestBean.class, SpringAnnotated.class),
|
||||
ProcessesSpringAnnotatedParameters.class)).isTrue();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesNoAnnotatedParameters", TestBean.class, BeanA.class),
|
||||
ProcessesSpringAnnotatedParameters.class)).isFalse();
|
||||
}
|
||||
|
||||
|
||||
public static class HasGeneric {
|
||||
|
||||
public void setFriends(List<TestBean> friends) {
|
||||
}
|
||||
public void setEnemies(List<TestBean> enemies) {
|
||||
}
|
||||
public void setPartners(List<?> partners) {
|
||||
}
|
||||
public void setPhoneNumbers(List<String> numbers) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ProcessesSpringAnnotatedParameters {
|
||||
|
||||
public void takesAnnotatedParameters(TestBean tb, SpringAnnotated sa) {
|
||||
}
|
||||
|
||||
public void takesNoAnnotatedParameters(TestBean tb, BeanA tb3) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Tx
|
||||
public static class HasTransactionalAnnotation {
|
||||
|
||||
public void foo() {
|
||||
}
|
||||
public Object bar(String foo) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EmptySpringAnnotation
|
||||
public static class SpringAnnotated {
|
||||
|
||||
public void foo() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface IBeanA {
|
||||
|
||||
@Tx
|
||||
int getAge();
|
||||
}
|
||||
|
||||
|
||||
static class BeanA implements IBeanA {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Tx
|
||||
@Override
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Tx
|
||||
static class BeanB {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private String name;
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
-89
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.aspectj;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer.AmbiguousBindingException;
|
||||
|
||||
/**
|
||||
* Tests just the annotation binding part of {@link AspectJAdviceParameterNameDiscoverer};
|
||||
* see supertype for remaining tests.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class TigerAspectJAdviceParameterNameDiscovererTests extends AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
@Test
|
||||
public void testAtThis() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@this(a)", new String[] {"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAtTarget() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@target(a)", new String[] {"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAtArgs() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@args(a)", new String[] {"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAtWithin() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@within(a)", new String[] {"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAtWithincode() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@withincode(a)", new String[] {"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAtAnnotation() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@annotation(a)", new String[] {"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAmbiguousAnnotationTwoVars() {
|
||||
assertException(getMethod("twoAnnotations"),"@annotation(a) && @this(x)", AmbiguousBindingException.class,
|
||||
"Found 2 potential annotation variable(s), and 2 potential argument slots");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAmbiguousAnnotationOneVar() {
|
||||
assertException(getMethod("oneAnnotation"),"@annotation(a) && @this(x)",IllegalArgumentException.class,
|
||||
"Found 2 candidate annotation binding variables but only one potential argument binding slot");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationMedley() {
|
||||
assertParameterNames(getMethod("annotationMedley"),"@annotation(a) && args(count) && this(foo)",
|
||||
null, "ex", new String[] {"ex", "foo", "count", "a"});
|
||||
}
|
||||
|
||||
|
||||
public void oneAnnotation(MyAnnotation ann) {}
|
||||
|
||||
public void twoAnnotations(MyAnnotation ann, MyAnnotation anotherAnn) {}
|
||||
|
||||
public void annotationMedley(Throwable t, Object foo, int x, MyAnnotation ma) {}
|
||||
|
||||
@interface MyAnnotation {}
|
||||
|
||||
}
|
||||
-330
@@ -1,330 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import test.annotation.EmptySpringAnnotation;
|
||||
import test.annotation.transaction.Tx;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Java 5 specific {@link AspectJExpressionPointcutTests}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class TigerAspectJExpressionPointcutTests {
|
||||
|
||||
private Method getAge;
|
||||
|
||||
private final Map<String, Method> methodsOnHasGeneric = new HashMap<>();
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws NoSuchMethodException {
|
||||
getAge = TestBean.class.getMethod("getAge");
|
||||
// Assumes no overloading
|
||||
for (Method method : HasGeneric.class.getMethods()) {
|
||||
methodsOnHasGeneric.put(method.getName(), method);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMatchGenericArgument() {
|
||||
String expression = "execution(* set*(java.util.List<org.springframework.beans.testfixture.beans.TestBean>) )";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
// TODO this will currently map, would be nice for optimization
|
||||
//assertTrue(ajexp.matches(HasGeneric.class));
|
||||
//assertFalse(ajexp.matches(TestBean.class));
|
||||
|
||||
Method takesGenericList = methodsOnHasGeneric.get("setFriends");
|
||||
assertThat(ajexp.matches(takesGenericList, HasGeneric.class)).isTrue();
|
||||
assertThat(ajexp.matches(methodsOnHasGeneric.get("setEnemies"), HasGeneric.class)).isTrue();
|
||||
assertThat(ajexp.matches(methodsOnHasGeneric.get("setPartners"), HasGeneric.class)).isFalse();
|
||||
assertThat(ajexp.matches(methodsOnHasGeneric.get("setPhoneNumbers"), HasGeneric.class)).isFalse();
|
||||
|
||||
assertThat(ajexp.matches(getAge, TestBean.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchVarargs() throws Exception {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
class MyTemplate {
|
||||
public int queryForInt(String sql, Object... params) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
String expression = "execution(int *.*(String, Object...))";
|
||||
AspectJExpressionPointcut jdbcVarArgs = new AspectJExpressionPointcut();
|
||||
jdbcVarArgs.setExpression(expression);
|
||||
|
||||
assertThat(jdbcVarArgs.matches(
|
||||
MyTemplate.class.getMethod("queryForInt", String.class, Object[].class),
|
||||
MyTemplate.class)).isTrue();
|
||||
|
||||
Method takesGenericList = methodsOnHasGeneric.get("setFriends");
|
||||
assertThat(jdbcVarArgs.matches(takesGenericList, HasGeneric.class)).isFalse();
|
||||
assertThat(jdbcVarArgs.matches(methodsOnHasGeneric.get("setEnemies"), HasGeneric.class)).isFalse();
|
||||
assertThat(jdbcVarArgs.matches(methodsOnHasGeneric.get("setPartners"), HasGeneric.class)).isFalse();
|
||||
assertThat(jdbcVarArgs.matches(methodsOnHasGeneric.get("setPhoneNumbers"), HasGeneric.class)).isFalse();
|
||||
assertThat(jdbcVarArgs.matches(getAge, TestBean.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithAtWithin() throws Exception {
|
||||
String expression = "@within(test.annotation.transaction.Tx)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithoutBinding() throws Exception {
|
||||
String expression = "within(@test.annotation.transaction.Tx *)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithSubpackageWildcard() throws Exception {
|
||||
String expression = "within(@(test.annotation..*) *)";
|
||||
AspectJExpressionPointcut springAnnotatedPc = testMatchAnnotationOnClass(expression);
|
||||
assertThat(springAnnotatedPc.matches(TestBean.class.getMethod("setName", String.class), TestBean.class)).isFalse();
|
||||
assertThat(springAnnotatedPc.matches(SpringAnnotated.class.getMethod("foo"), SpringAnnotated.class)).isTrue();
|
||||
|
||||
expression = "within(@(test.annotation.transaction..*) *)";
|
||||
AspectJExpressionPointcut springTxAnnotatedPc = testMatchAnnotationOnClass(expression);
|
||||
assertThat(springTxAnnotatedPc.matches(SpringAnnotated.class.getMethod("foo"), SpringAnnotated.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithExactPackageWildcard() throws Exception {
|
||||
String expression = "within(@(test.annotation.transaction.*) *)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
private AspectJExpressionPointcut testMatchAnnotationOnClass(String expression) throws Exception {
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
assertThat(ajexp.matches(getAge, TestBean.class)).isFalse();
|
||||
assertThat(ajexp.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class)).isTrue();
|
||||
assertThat(ajexp.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class)).isTrue();
|
||||
assertThat(ajexp.matches(BeanB.class.getMethod("setName", String.class), BeanB.class)).isTrue();
|
||||
assertThat(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
return ajexp;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodWithFQN() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
assertThat(ajexp.matches(getAge, TestBean.class)).isFalse();
|
||||
assertThat(ajexp.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(ajexp.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
assertThat(ajexp.matches(BeanA.class.getMethod("getAge"), BeanA.class)).isTrue();
|
||||
assertThat(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnCglibProxyMethod() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
ProxyFactory factory = new ProxyFactory(new BeanA());
|
||||
factory.setProxyTargetClass(true);
|
||||
BeanA proxy = (BeanA) factory.getProxy();
|
||||
assertThat(ajexp.matches(BeanA.class.getMethod("getAge"), proxy.getClass())).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnDynamicProxyMethod() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
ProxyFactory factory = new ProxyFactory(new BeanA());
|
||||
factory.setProxyTargetClass(false);
|
||||
IBeanA proxy = (IBeanA) factory.getProxy();
|
||||
assertThat(ajexp.matches(IBeanA.class.getMethod("getAge"), proxy.getClass())).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodWithWildcard() throws Exception {
|
||||
String expression = "execution(@(test.annotation..*) * *(..))";
|
||||
AspectJExpressionPointcut anySpringMethodAnnotation = new AspectJExpressionPointcut();
|
||||
anySpringMethodAnnotation.setExpression(expression);
|
||||
|
||||
assertThat(anySpringMethodAnnotation.matches(getAge, TestBean.class)).isFalse();
|
||||
assertThat(anySpringMethodAnnotation.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(anySpringMethodAnnotation.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
assertThat(anySpringMethodAnnotation.matches(BeanA.class.getMethod("getAge"), BeanA.class)).isTrue();
|
||||
assertThat(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodArgumentsWithFQN() throws Exception {
|
||||
String expression = "@args(*, test.annotation.EmptySpringAnnotation))";
|
||||
AspectJExpressionPointcut takesSpringAnnotatedArgument2 = new AspectJExpressionPointcut();
|
||||
takesSpringAnnotatedArgument2.setExpression(expression);
|
||||
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge"), BeanA.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesAnnotatedParameters", TestBean.class, SpringAnnotated.class),
|
||||
ProcessesSpringAnnotatedParameters.class)).isTrue();
|
||||
|
||||
// True because it maybeMatches with potential argument subtypes
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesNoAnnotatedParameters", TestBean.class, BeanA.class),
|
||||
ProcessesSpringAnnotatedParameters.class)).isTrue();
|
||||
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesNoAnnotatedParameters", TestBean.class, BeanA.class),
|
||||
ProcessesSpringAnnotatedParameters.class, new TestBean(), new BeanA())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodArgumentsWithWildcards() throws Exception {
|
||||
String expression = "execution(* *(*, @(test..*) *))";
|
||||
AspectJExpressionPointcut takesSpringAnnotatedArgument2 = new AspectJExpressionPointcut();
|
||||
takesSpringAnnotatedArgument2.setExpression(expression);
|
||||
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge"), BeanA.class)).isFalse();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class)).isFalse();
|
||||
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesAnnotatedParameters", TestBean.class, SpringAnnotated.class),
|
||||
ProcessesSpringAnnotatedParameters.class)).isTrue();
|
||||
assertThat(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesNoAnnotatedParameters", TestBean.class, BeanA.class),
|
||||
ProcessesSpringAnnotatedParameters.class)).isFalse();
|
||||
}
|
||||
|
||||
|
||||
public static class HasGeneric {
|
||||
|
||||
public void setFriends(List<TestBean> friends) {
|
||||
}
|
||||
public void setEnemies(List<TestBean> enemies) {
|
||||
}
|
||||
public void setPartners(List<?> partners) {
|
||||
}
|
||||
public void setPhoneNumbers(List<String> numbers) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ProcessesSpringAnnotatedParameters {
|
||||
|
||||
public void takesAnnotatedParameters(TestBean tb, SpringAnnotated sa) {
|
||||
}
|
||||
|
||||
public void takesNoAnnotatedParameters(TestBean tb, BeanA tb3) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Tx
|
||||
public static class HasTransactionalAnnotation {
|
||||
|
||||
public void foo() {
|
||||
}
|
||||
public Object bar(String foo) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EmptySpringAnnotation
|
||||
public static class SpringAnnotated {
|
||||
|
||||
public void foo() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface IBeanA {
|
||||
|
||||
@Tx
|
||||
int getAge();
|
||||
}
|
||||
|
||||
|
||||
static class BeanA implements IBeanA {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Tx
|
||||
@Override
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Tx
|
||||
static class BeanB {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private String name;
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+9
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -98,7 +98,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void perTargetAspect() throws SecurityException, NoSuchMethodException {
|
||||
void perTargetAspect() throws Exception {
|
||||
TestBean target = new TestBean();
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
@@ -130,7 +130,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void multiplePerTargetAspects() throws SecurityException, NoSuchMethodException {
|
||||
void multiplePerTargetAspects() throws Exception {
|
||||
TestBean target = new TestBean();
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
@@ -158,7 +158,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void multiplePerTargetAspectsWithOrderAnnotation() throws SecurityException, NoSuchMethodException {
|
||||
void multiplePerTargetAspectsWithOrderAnnotation() throws Exception {
|
||||
TestBean target = new TestBean();
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
@@ -184,7 +184,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void perThisAspect() throws SecurityException, NoSuchMethodException {
|
||||
void perThisAspect() throws Exception {
|
||||
TestBean target = new TestBean();
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
@@ -220,7 +220,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void perTypeWithinAspect() throws SecurityException, NoSuchMethodException {
|
||||
void perTypeWithinAspect() throws Exception {
|
||||
TestBean target = new TestBean();
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
@@ -322,7 +322,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
int b = 12;
|
||||
int c = 25;
|
||||
String d = "d";
|
||||
StringBuffer e = new StringBuffer("stringbuf");
|
||||
StringBuilder e = new StringBuilder("stringbuf");
|
||||
String expectedResult = a + b+ c + d + e;
|
||||
assertThat(mva.mungeArgs(a, b, c, d, e)).isEqualTo(expectedResult);
|
||||
}
|
||||
@@ -728,12 +728,12 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Aspect
|
||||
static class ManyValuedArgs {
|
||||
|
||||
String mungeArgs(String a, int b, int c, String d, StringBuffer e) {
|
||||
String mungeArgs(String a, int b, int c, String d, StringBuilder 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 {
|
||||
String reverseAdvice(ProceedingJoinPoint pjp, int b, int c, String d, StringBuilder e, String a) throws Throwable {
|
||||
assertThat(pjp.proceed()).isEqualTo(a + b+ c+ d+ e);
|
||||
return a + b + c + d + e;
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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,7 +28,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* @since 2.0
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
* @author Sam Brannen
|
||||
@@ -56,7 +55,7 @@ class AspectMetadataTests {
|
||||
assertThat(am.getAjType().getPerClause().getKind()).isEqualTo(PerClauseKind.PERTARGET);
|
||||
assertThat(am.getPerClausePointcut()).isInstanceOf(AspectJExpressionPointcut.class);
|
||||
assertThat(((AspectJExpressionPointcut) am.getPerClausePointcut()).getExpression())
|
||||
.isEqualTo("execution(* *.getSpouse())");
|
||||
.isEqualTo("execution(* *.getSpouse())");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -67,7 +66,7 @@ class AspectMetadataTests {
|
||||
assertThat(am.getAjType().getPerClause().getKind()).isEqualTo(PerClauseKind.PERTHIS);
|
||||
assertThat(am.getPerClausePointcut()).isInstanceOf(AspectJExpressionPointcut.class);
|
||||
assertThat(((AspectJExpressionPointcut) am.getPerClausePointcut()).getExpression())
|
||||
.isEqualTo("execution(* *.getSpouse())");
|
||||
.isEqualTo("execution(* *.getSpouse())");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+37
-47
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.aop.config;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -40,7 +41,7 @@ import static org.springframework.core.testfixture.io.ResourceTestUtils.qualifie
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class AopNamespaceHandlerEventTests {
|
||||
class AopNamespaceHandlerEventTests {
|
||||
|
||||
private static final Class<?> CLASS = AopNamespaceHandlerEventTests.class;
|
||||
|
||||
@@ -57,25 +58,24 @@ public class AopNamespaceHandlerEventTests {
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
void setup() {
|
||||
this.reader = new XmlBeanDefinitionReader(this.beanFactory);
|
||||
this.reader.setEventListener(this.eventListener);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPointcutEvents() {
|
||||
void pointcutEvents() {
|
||||
this.reader.loadBeanDefinitions(POINTCUT_EVENTS_CONTEXT);
|
||||
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
|
||||
assertThat(componentDefinitions.length).as("Incorrect number of events fired").isEqualTo(1);
|
||||
boolean condition = componentDefinitions[0] instanceof CompositeComponentDefinition;
|
||||
assertThat(condition).as("No holder with nested components").isTrue();
|
||||
assertThat(componentDefinitions).as("Incorrect number of events fired").hasSize(1);
|
||||
assertThat(componentDefinitions[0]).as("No holder with nested components").isInstanceOf(CompositeComponentDefinition.class);
|
||||
|
||||
CompositeComponentDefinition compositeDef = (CompositeComponentDefinition) componentDefinitions[0];
|
||||
assertThat(compositeDef.getName()).isEqualTo("aop:config");
|
||||
|
||||
ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
|
||||
assertThat(nestedComponentDefs.length).as("Incorrect number of inner components").isEqualTo(2);
|
||||
assertThat(nestedComponentDefs).as("Incorrect number of inner components").hasSize(2);
|
||||
PointcutComponentDefinition pcd = null;
|
||||
for (ComponentDefinition componentDefinition : nestedComponentDefs) {
|
||||
if (componentDefinition instanceof PointcutComponentDefinition) {
|
||||
@@ -84,84 +84,77 @@ public class AopNamespaceHandlerEventTests {
|
||||
}
|
||||
}
|
||||
assertThat(pcd).as("PointcutComponentDefinition not found").isNotNull();
|
||||
assertThat(pcd.getBeanDefinitions().length).as("Incorrect number of BeanDefinitions").isEqualTo(1);
|
||||
assertThat(pcd.getBeanDefinitions()).as("Incorrect number of BeanDefinitions").hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdvisorEventsWithPointcutRef() {
|
||||
void advisorEventsWithPointcutRef() {
|
||||
this.reader.loadBeanDefinitions(POINTCUT_REF_CONTEXT);
|
||||
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
|
||||
assertThat(componentDefinitions.length).as("Incorrect number of events fired").isEqualTo(2);
|
||||
assertThat(componentDefinitions).as("Incorrect number of events fired").hasSize(2);
|
||||
|
||||
boolean condition1 = componentDefinitions[0] instanceof CompositeComponentDefinition;
|
||||
assertThat(condition1).as("No holder with nested components").isTrue();
|
||||
assertThat(componentDefinitions[0]).as("No holder with nested components").isInstanceOf(CompositeComponentDefinition.class);
|
||||
CompositeComponentDefinition compositeDef = (CompositeComponentDefinition) componentDefinitions[0];
|
||||
assertThat(compositeDef.getName()).isEqualTo("aop:config");
|
||||
|
||||
ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
|
||||
assertThat(nestedComponentDefs.length).as("Incorrect number of inner components").isEqualTo(3);
|
||||
assertThat(nestedComponentDefs).as("Incorrect number of inner components").hasSize(3);
|
||||
AdvisorComponentDefinition acd = null;
|
||||
for (int i = 0; i < nestedComponentDefs.length; i++) {
|
||||
ComponentDefinition componentDefinition = nestedComponentDefs[i];
|
||||
for (ComponentDefinition componentDefinition : nestedComponentDefs) {
|
||||
if (componentDefinition instanceof AdvisorComponentDefinition) {
|
||||
acd = (AdvisorComponentDefinition) componentDefinition;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertThat(acd).as("AdvisorComponentDefinition not found").isNotNull();
|
||||
assertThat(acd.getBeanDefinitions().length).isEqualTo(1);
|
||||
assertThat(acd.getBeanReferences().length).isEqualTo(2);
|
||||
assertThat(acd.getBeanDefinitions()).hasSize(1);
|
||||
assertThat(acd.getBeanReferences()).hasSize(2);
|
||||
|
||||
boolean condition = componentDefinitions[1] instanceof BeanComponentDefinition;
|
||||
assertThat(condition).as("No advice bean found").isTrue();
|
||||
assertThat(componentDefinitions[1]).as("No advice bean found").isInstanceOf(BeanComponentDefinition.class);
|
||||
BeanComponentDefinition adviceDef = (BeanComponentDefinition) componentDefinitions[1];
|
||||
assertThat(adviceDef.getBeanName()).isEqualTo("countingAdvice");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdvisorEventsWithDirectPointcut() {
|
||||
void advisorEventsWithDirectPointcut() {
|
||||
this.reader.loadBeanDefinitions(DIRECT_POINTCUT_EVENTS_CONTEXT);
|
||||
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
|
||||
assertThat(componentDefinitions.length).as("Incorrect number of events fired").isEqualTo(2);
|
||||
assertThat(componentDefinitions).as("Incorrect number of events fired").hasSize(2);
|
||||
|
||||
boolean condition1 = componentDefinitions[0] instanceof CompositeComponentDefinition;
|
||||
assertThat(condition1).as("No holder with nested components").isTrue();
|
||||
assertThat(componentDefinitions[0]).as("No holder with nested components").isInstanceOf(CompositeComponentDefinition.class);
|
||||
CompositeComponentDefinition compositeDef = (CompositeComponentDefinition) componentDefinitions[0];
|
||||
assertThat(compositeDef.getName()).isEqualTo("aop:config");
|
||||
|
||||
ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
|
||||
assertThat(nestedComponentDefs.length).as("Incorrect number of inner components").isEqualTo(2);
|
||||
assertThat(nestedComponentDefs).as("Incorrect number of inner components").hasSize(2);
|
||||
AdvisorComponentDefinition acd = null;
|
||||
for (int i = 0; i < nestedComponentDefs.length; i++) {
|
||||
ComponentDefinition componentDefinition = nestedComponentDefs[i];
|
||||
for (ComponentDefinition componentDefinition : nestedComponentDefs) {
|
||||
if (componentDefinition instanceof AdvisorComponentDefinition) {
|
||||
acd = (AdvisorComponentDefinition) componentDefinition;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertThat(acd).as("AdvisorComponentDefinition not found").isNotNull();
|
||||
assertThat(acd.getBeanDefinitions().length).isEqualTo(2);
|
||||
assertThat(acd.getBeanReferences().length).isEqualTo(1);
|
||||
assertThat(acd.getBeanDefinitions()).hasSize(2);
|
||||
assertThat(acd.getBeanReferences()).hasSize(1);
|
||||
|
||||
boolean condition = componentDefinitions[1] instanceof BeanComponentDefinition;
|
||||
assertThat(condition).as("No advice bean found").isTrue();
|
||||
assertThat(componentDefinitions[1]).as("No advice bean found").isInstanceOf(BeanComponentDefinition.class);
|
||||
BeanComponentDefinition adviceDef = (BeanComponentDefinition) componentDefinitions[1];
|
||||
assertThat(adviceDef.getBeanName()).isEqualTo("countingAdvice");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAspectEvent() {
|
||||
void aspectEvent() {
|
||||
this.reader.loadBeanDefinitions(CONTEXT);
|
||||
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
|
||||
assertThat(componentDefinitions.length).as("Incorrect number of events fired").isEqualTo(5);
|
||||
assertThat(componentDefinitions).as("Incorrect number of events fired").hasSize(2);
|
||||
|
||||
boolean condition = componentDefinitions[0] instanceof CompositeComponentDefinition;
|
||||
assertThat(condition).as("No holder with nested components").isTrue();
|
||||
assertThat(componentDefinitions[0]).as("No holder with nested components").isInstanceOf(CompositeComponentDefinition.class);
|
||||
CompositeComponentDefinition compositeDef = (CompositeComponentDefinition) componentDefinitions[0];
|
||||
assertThat(compositeDef.getName()).isEqualTo("aop:config");
|
||||
|
||||
ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
|
||||
assertThat(nestedComponentDefs.length).as("Incorrect number of inner components").isEqualTo(2);
|
||||
assertThat(nestedComponentDefs).as("Incorrect number of inner components").hasSize(2);
|
||||
AspectComponentDefinition acd = null;
|
||||
for (ComponentDefinition componentDefinition : nestedComponentDefs) {
|
||||
if (componentDefinition instanceof AspectComponentDefinition) {
|
||||
@@ -172,9 +165,9 @@ public class AopNamespaceHandlerEventTests {
|
||||
|
||||
assertThat(acd).as("AspectComponentDefinition not found").isNotNull();
|
||||
BeanDefinition[] beanDefinitions = acd.getBeanDefinitions();
|
||||
assertThat(beanDefinitions.length).isEqualTo(5);
|
||||
assertThat(beanDefinitions).hasSize(5);
|
||||
BeanReference[] beanReferences = acd.getBeanReferences();
|
||||
assertThat(beanReferences.length).isEqualTo(6);
|
||||
assertThat(beanReferences).hasSize(6);
|
||||
|
||||
Set<String> expectedReferences = new HashSet<>();
|
||||
expectedReferences.add("pc");
|
||||
@@ -182,19 +175,16 @@ public class AopNamespaceHandlerEventTests {
|
||||
for (BeanReference beanReference : beanReferences) {
|
||||
expectedReferences.remove(beanReference.getBeanName());
|
||||
}
|
||||
assertThat(expectedReferences.size()).as("Incorrect references found").isEqualTo(0);
|
||||
assertThat(expectedReferences).as("Incorrect references found").isEmpty();
|
||||
|
||||
for (int i = 1; i < componentDefinitions.length; i++) {
|
||||
boolean condition1 = componentDefinitions[i] instanceof BeanComponentDefinition;
|
||||
assertThat(condition1).isTrue();
|
||||
}
|
||||
Arrays.stream(componentDefinitions).skip(1).forEach(definition ->
|
||||
assertThat(definition).isInstanceOf(BeanComponentDefinition.class));
|
||||
|
||||
ComponentDefinition[] nestedComponentDefs2 = acd.getNestedComponents();
|
||||
assertThat(nestedComponentDefs2.length).as("Inner PointcutComponentDefinition not found").isEqualTo(1);
|
||||
boolean condition1 = nestedComponentDefs2[0] instanceof PointcutComponentDefinition;
|
||||
assertThat(condition1).isTrue();
|
||||
assertThat(nestedComponentDefs2).as("Inner PointcutComponentDefinition not found").hasSize(1);
|
||||
assertThat(nestedComponentDefs2[0]).isInstanceOf(PointcutComponentDefinition.class);
|
||||
PointcutComponentDefinition pcd = (PointcutComponentDefinition) nestedComponentDefs2[0];
|
||||
assertThat(pcd.getBeanDefinitions().length).as("Incorrect number of BeanDefinitions").isEqualTo(1);
|
||||
assertThat(pcd.getBeanDefinitions()).as("Incorrect number of BeanDefinitions").hasSize(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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,10 +30,10 @@ import static org.springframework.core.testfixture.io.ResourceTestUtils.qualifie
|
||||
* @author Mark Fisher
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class AopNamespaceHandlerPointcutErrorTests {
|
||||
class AopNamespaceHandlerPointcutErrorTests {
|
||||
|
||||
@Test
|
||||
public void testDuplicatePointcutConfig() {
|
||||
void duplicatePointcutConfig() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
assertThatExceptionOfType(BeanDefinitionStoreException.class).isThrownBy(() ->
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
|
||||
@@ -42,7 +42,7 @@ public class AopNamespaceHandlerPointcutErrorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingPointcutConfig() {
|
||||
void missingPointcutConfig() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
assertThatExceptionOfType(BeanDefinitionStoreException.class).isThrownBy(() ->
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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,10 +30,10 @@ import static org.springframework.core.testfixture.io.ResourceTestUtils.qualifie
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class TopLevelAopTagTests {
|
||||
class TopLevelAopTagTests {
|
||||
|
||||
@Test
|
||||
public void testParse() {
|
||||
void parse() {
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(beanFactory).loadBeanDefinitions(
|
||||
qualifiedResource(TopLevelAopTagTests.class, "context.xml"));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -32,6 +32,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public class AopProxyUtilsTests {
|
||||
|
||||
|
||||
+1
-10
@@ -125,16 +125,7 @@ public class ConcurrencyThrottleInterceptorTests {
|
||||
try {
|
||||
this.proxy.exceptional(this.ex);
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
if (ex == this.ex) {
|
||||
logger.debug("Expected exception thrown", ex);
|
||||
}
|
||||
else {
|
||||
// should never happen
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
catch (Error err) {
|
||||
catch (RuntimeException | Error err) {
|
||||
if (err == this.ex) {
|
||||
logger.debug("Expected exception thrown", err);
|
||||
}
|
||||
|
||||
-6
@@ -16,12 +16,6 @@
|
||||
</aop:aspect>
|
||||
</aop:config>
|
||||
|
||||
<bean id="getNameCounter" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
<bean id="getAgeCounter" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
<bean id="testBean" class="org.springframework.beans.testfixture.beans.TestBean"/>
|
||||
|
||||
<bean id="countingAdvice" class="org.springframework.aop.config.CountingAspectJAdvice"/>
|
||||
|
||||
</beans>
|
||||
|
||||
+1
-1
@@ -9,6 +9,6 @@
|
||||
<aop:advisor advice-ref="countingAdvice" pointcut="within(org.springframework..*)"/>
|
||||
</aop:config>
|
||||
|
||||
<bean id="countingAdvice" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
<bean id="countingAdvice" class="org.springframework.aop.testfixture.advice.CountingBeforeAdvice"/>
|
||||
|
||||
</beans>
|
||||
|
||||
+1
-1
@@ -10,6 +10,6 @@
|
||||
<aop:advisor advice-ref="countingAdvice" pointcut-ref="pc"/>
|
||||
</aop:config>
|
||||
|
||||
<bean id="countingAdvice" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
<bean id="countingAdvice" class="org.springframework.aop.testfixture.advice.CountingBeforeAdvice"/>
|
||||
|
||||
</beans>
|
||||
|
||||
-4
@@ -12,10 +12,6 @@
|
||||
</aop:aspect>
|
||||
</aop:config>
|
||||
|
||||
<bean id="getAgeCounter" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
<bean id="testBean" class="org.springframework.beans.testfixture.beans.TestBean"/>
|
||||
|
||||
<bean id="countingAdvice" class="org.springframework.aop.config.CountingAspectJAdvice"/>
|
||||
|
||||
</beans>
|
||||
|
||||
-4
@@ -12,10 +12,6 @@
|
||||
</aop:aspect>
|
||||
</aop:config>
|
||||
|
||||
<bean id="getAgeCounter" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
<bean id="testBean" class="org.springframework.beans.testfixture.beans.TestBean"/>
|
||||
|
||||
<bean id="countingAdvice" class="org.springframework.aop.config.CountingAspectJAdvice"/>
|
||||
|
||||
</beans>
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.aop.testfixture.advice;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Abstract superclass for counting advices etc.
|
||||
@@ -31,7 +32,7 @@ import java.util.HashMap;
|
||||
public class MethodCounter implements Serializable {
|
||||
|
||||
/** Method name --> count, does not understand overloading */
|
||||
private HashMap<String, Integer> map = new HashMap<>();
|
||||
private Map<String, Integer> map = new HashMap<>();
|
||||
|
||||
private int allCount;
|
||||
|
||||
|
||||
+2
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,6 @@ import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
@@ -107,10 +106,7 @@ public class AspectJEnableCachingIsolatedTests {
|
||||
try {
|
||||
load(MultiCacheManagerConfigurer.class, EnableCachingConfig.class);
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
Throwable root = ex.getRootCause();
|
||||
boolean condition = root instanceof IllegalStateException;
|
||||
assertThat(condition).isTrue();
|
||||
catch (IllegalStateException ex) {
|
||||
assertThat(ex.getMessage().contains("implementations of CachingConfigurer")).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -691,7 +691,25 @@ public abstract class BeanUtils {
|
||||
* from each other, as long as the properties match. Any bean properties that the
|
||||
* source bean exposes but the target bean does not will silently be ignored.
|
||||
* <p>This is just a convenience method. For more complex transfer needs,
|
||||
* consider using a full BeanWrapper.
|
||||
* consider using a full {@link BeanWrapper}.
|
||||
* <p>As of Spring Framework 5.3, this method honors generic type information
|
||||
* when matching properties in the source and target objects.
|
||||
* <p>The following table provides a non-exhaustive set of examples of source
|
||||
* and target property types that can be copied as well as source and target
|
||||
* property types that cannot be copied.
|
||||
* <table border="1">
|
||||
* <tr><th>source property type</th><th>target property type</th><th>copy supported</th></tr>
|
||||
* <tr><td>{@code Integer}</td><td>{@code Integer}</td><td>yes</td></tr>
|
||||
* <tr><td>{@code Integer}</td><td>{@code Number}</td><td>yes</td></tr>
|
||||
* <tr><td>{@code List<Integer>}</td><td>{@code List<Integer>}</td><td>yes</td></tr>
|
||||
* <tr><td>{@code List<?>}</td><td>{@code List<?>}</td><td>yes</td></tr>
|
||||
* <tr><td>{@code List<Integer>}</td><td>{@code List<?>}</td><td>yes</td></tr>
|
||||
* <tr><td>{@code List<Integer>}</td><td>{@code List<? extends Number>}</td><td>yes</td></tr>
|
||||
* <tr><td>{@code String}</td><td>{@code Integer}</td><td>no</td></tr>
|
||||
* <tr><td>{@code Number}</td><td>{@code Integer}</td><td>no</td></tr>
|
||||
* <tr><td>{@code List<Integer>}</td><td>{@code List<Long>}</td><td>no</td></tr>
|
||||
* <tr><td>{@code List<Integer>}</td><td>{@code List<Number>}</td><td>no</td></tr>
|
||||
* </table>
|
||||
* @param source the source bean
|
||||
* @param target the target bean
|
||||
* @throws BeansException if the copying failed
|
||||
@@ -708,7 +726,10 @@ public abstract class BeanUtils {
|
||||
* from each other, as long as the properties match. Any bean properties that the
|
||||
* source bean exposes but the target bean does not will silently be ignored.
|
||||
* <p>This is just a convenience method. For more complex transfer needs,
|
||||
* consider using a full BeanWrapper.
|
||||
* consider using a full {@link BeanWrapper}.
|
||||
* <p>As of Spring Framework 5.3, this method honors generic type information
|
||||
* when matching properties in the source and target objects. See the
|
||||
* documentation for {@link #copyProperties(Object, Object)} for details.
|
||||
* @param source the source bean
|
||||
* @param target the target bean
|
||||
* @param editable the class (or interface) to restrict property setting to
|
||||
@@ -726,7 +747,10 @@ public abstract class BeanUtils {
|
||||
* from each other, as long as the properties match. Any bean properties that the
|
||||
* source bean exposes but the target bean does not will silently be ignored.
|
||||
* <p>This is just a convenience method. For more complex transfer needs,
|
||||
* consider using a full BeanWrapper.
|
||||
* consider using a full {@link BeanWrapper}.
|
||||
* <p>As of Spring Framework 5.3, this method honors generic type information
|
||||
* when matching properties in the source and target objects. See the
|
||||
* documentation for {@link #copyProperties(Object, Object)} for details.
|
||||
* @param source the source bean
|
||||
* @param target the target bean
|
||||
* @param ignoreProperties array of property names to ignore
|
||||
@@ -743,7 +767,8 @@ public abstract class BeanUtils {
|
||||
* from each other, as long as the properties match. Any bean properties that the
|
||||
* source bean exposes but the target bean does not will silently be ignored.
|
||||
* <p>As of Spring Framework 5.3, this method honors generic type information
|
||||
* when matching properties in the source and target objects.
|
||||
* when matching properties in the source and target objects. See the
|
||||
* documentation for {@link #copyProperties(Object, Object)} for details.
|
||||
* @param source the source bean
|
||||
* @param target the target bean
|
||||
* @param editable the class (or interface) to restrict property setting to
|
||||
|
||||
+29
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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,6 +22,8 @@ import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.URL;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -286,9 +288,17 @@ public final class CachedIntrospectionResults {
|
||||
// This call is slow so we do it once.
|
||||
PropertyDescriptor[] pds = this.beanInfo.getPropertyDescriptors();
|
||||
for (PropertyDescriptor pd : pds) {
|
||||
if (Class.class == beanClass &&
|
||||
("classLoader".equals(pd.getName()) || "protectionDomain".equals(pd.getName()))) {
|
||||
// Ignore Class.getClassLoader() and getProtectionDomain() methods - nobody needs to bind to those
|
||||
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
|
||||
continue;
|
||||
}
|
||||
if (logger.isTraceEnabled()) {
|
||||
@@ -337,6 +347,10 @@ public final class CachedIntrospectionResults {
|
||||
// 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);
|
||||
Method readMethod = pd.getReadMethod();
|
||||
if (readMethod != null) {
|
||||
@@ -354,7 +368,7 @@ public final class CachedIntrospectionResults {
|
||||
|
||||
for (Method method : beanClass.getMethods()) {
|
||||
if (!this.propertyDescriptors.containsKey(method.getName()) &&
|
||||
!readMethodNames.contains((method.getName())) && isPlainAccessor(method)) {
|
||||
!readMethodNames.contains(method.getName()) && isPlainAccessor(method)) {
|
||||
this.propertyDescriptors.put(method.getName(),
|
||||
new GenericTypeAwarePropertyDescriptor(beanClass, method.getName(), method, null, null));
|
||||
readMethodNames.add(method.getName());
|
||||
@@ -363,8 +377,10 @@ public final class CachedIntrospectionResults {
|
||||
}
|
||||
|
||||
private boolean isPlainAccessor(Method method) {
|
||||
if (method.getParameterCount() > 0 || method.getReturnType() == void.class ||
|
||||
method.getDeclaringClass() == Object.class || Modifier.isStatic(method.getModifiers())) {
|
||||
if (Modifier.isStatic(method.getModifiers()) ||
|
||||
method.getDeclaringClass() == Object.class || method.getDeclaringClass() == Class.class ||
|
||||
method.getParameterCount() > 0 || method.getReturnType() == void.class ||
|
||||
isInvalidReadOnlyPropertyType(method.getReturnType())) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
@@ -377,6 +393,12 @@ 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;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 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,8 +23,9 @@ 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)
|
||||
* Serves as base interface for {@link BeanWrapper}.
|
||||
* (such as bean properties of an object or fields in an object).
|
||||
*
|
||||
* <p>Serves as base interface for {@link BeanWrapper}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Support package for beans-style handling of Java 5 annotations.
|
||||
* Support package for beans-style handling of annotations.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
|
||||
@@ -214,6 +214,7 @@ public interface BeanFactory {
|
||||
/**
|
||||
* Return a provider for the specified bean, allowing for lazy on-demand retrieval
|
||||
* of instances, including availability and uniqueness options.
|
||||
* <p>For matching a generic type, consider {@link #getBeanProvider(ResolvableType)}.
|
||||
* @param requiredType type the bean must match; can be an interface or superclass
|
||||
* @return a corresponding provider handle
|
||||
* @since 5.1
|
||||
@@ -223,13 +224,20 @@ public interface BeanFactory {
|
||||
|
||||
/**
|
||||
* Return a provider for the specified bean, allowing for lazy on-demand retrieval
|
||||
* of instances, including availability and uniqueness options.
|
||||
* @param requiredType type the bean must match; can be a generic type declaration.
|
||||
* Note that collection types are not supported here, in contrast to reflective
|
||||
* of instances, including availability and uniqueness options. This variant allows
|
||||
* for specifying a generic type to match, similar to reflective injection points
|
||||
* with generic type declarations in method/constructor parameters.
|
||||
* <p>Note that collections of beans are not supported here, in contrast to reflective
|
||||
* injection points. For programmatically retrieving a list of beans matching a
|
||||
* specific type, specify the actual bean type as an argument here and subsequently
|
||||
* use {@link ObjectProvider#orderedStream()} or its lazy streaming/iteration options.
|
||||
* <p>Also, generics matching is strict here, as per the Java assignment rules.
|
||||
* For lenient fallback matching with unchecked semantics (similar to the ´unchecked´
|
||||
* Java compiler warning), consider calling {@link #getBeanProvider(Class)} with the
|
||||
* raw type as a second step if no full generic match is
|
||||
* {@link ObjectProvider#getIfAvailable() available} with this variant.
|
||||
* @return a corresponding provider handle
|
||||
* @param requiredType type the bean must match; can be a generic type declaration
|
||||
* @since 5.1
|
||||
* @see ObjectProvider#iterator()
|
||||
* @see ObjectProvider#stream()
|
||||
|
||||
+23
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -353,9 +353,31 @@ public interface ListableBeanFactory extends BeanFactory {
|
||||
* @since 3.0
|
||||
* @see #getBeanNamesForAnnotation
|
||||
* @see #getBeansWithAnnotation
|
||||
* @see #getType(String)
|
||||
*/
|
||||
@Nullable
|
||||
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
|
||||
throws NoSuchBeanDefinitionException;
|
||||
|
||||
/**
|
||||
* Find an {@link Annotation} of {@code annotationType} on the specified bean,
|
||||
* traversing its interfaces and super classes if no annotation can be found on
|
||||
* the given class itself, as well as checking the bean's factory method (if any).
|
||||
* @param beanName the name of the bean to look for annotations on
|
||||
* @param annotationType the type of annotation to look for
|
||||
* (at class, interface or factory method level of the specified bean)
|
||||
* @param allowFactoryBeanInit whether a {@code FactoryBean} may get initialized
|
||||
* just for the purpose of determining its object type
|
||||
* @return the annotation of the given type if found, or {@code null} otherwise
|
||||
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
|
||||
* @since 5.3.14
|
||||
* @see #getBeanNamesForAnnotation
|
||||
* @see #getBeansWithAnnotation
|
||||
* @see #getType(String, boolean)
|
||||
*/
|
||||
@Nullable
|
||||
<A extends Annotation> A findAnnotationOnBean(
|
||||
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
|
||||
throws NoSuchBeanDefinitionException;
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -537,10 +537,10 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
* @param ann the Autowired annotation
|
||||
* @return whether the annotation indicates that a dependency is required
|
||||
*/
|
||||
@SuppressWarnings({"deprecation", "cast"})
|
||||
@SuppressWarnings("deprecation")
|
||||
protected boolean determineRequiredStatus(MergedAnnotation<?> ann) {
|
||||
return determineRequiredStatus(
|
||||
ann.asMap(mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType())));
|
||||
return determineRequiredStatus(ann.<AnnotationAttributes> asMap(
|
||||
mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -302,7 +302,7 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
beanDefinition.registerExternallyManagedInitMethod(methodIdentifier);
|
||||
checkedInitMethods.add(element);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Registered init method on class [" + this.targetClass.getName() + "]: " + element);
|
||||
logger.trace("Registered init method on class [" + this.targetClass.getName() + "]: " + methodIdentifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,7 +313,7 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier);
|
||||
checkedDestroyMethods.add(element);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Registered destroy method on class [" + this.targetClass.getName() + "]: " + element);
|
||||
logger.trace("Registered destroy method on class [" + this.targetClass.getName() + "]: " + methodIdentifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -44,7 +44,7 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
|
||||
* that enforces required JavaBean properties to have been configured.
|
||||
* Required bean properties are detected through a Java 5 annotation:
|
||||
* Required bean properties are detected through an annotation:
|
||||
* by default, Spring's {@link Required} annotation.
|
||||
*
|
||||
* <p>The motivation for the existence of this BeanPostProcessor is to allow
|
||||
|
||||
+7
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2022 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,8 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Strategy interface for resolving a value through evaluating it
|
||||
* as an expression, if applicable.
|
||||
* Strategy interface for resolving a value by evaluating it as an expression,
|
||||
* if applicable.
|
||||
*
|
||||
* <p>A raw {@link org.springframework.beans.factory.BeanFactory} does not
|
||||
* contain a default implementation of this strategy. However,
|
||||
@@ -36,12 +36,13 @@ public interface BeanExpressionResolver {
|
||||
/**
|
||||
* Evaluate the given value as an expression, if applicable;
|
||||
* return the value as-is otherwise.
|
||||
* @param value the value to check
|
||||
* @param evalContext the evaluation context
|
||||
* @param value the value to evaluate as an expression
|
||||
* @param beanExpressionContext the bean expression context to use when
|
||||
* evaluating the expression
|
||||
* @return the resolved value (potentially the given value as-is)
|
||||
* @throws BeansException if evaluation failed
|
||||
*/
|
||||
@Nullable
|
||||
Object evaluate(@Nullable String value, BeanExpressionContext evalContext) throws BeansException;
|
||||
Object evaluate(@Nullable String value, BeanExpressionContext beanExpressionContext) throws BeansException;
|
||||
|
||||
}
|
||||
|
||||
+2
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,9 +34,7 @@ import org.springframework.lang.Nullable;
|
||||
*
|
||||
* <p><b>NOTE:</b> This interface is a special purpose interface, mainly for
|
||||
* internal use within the framework. It is recommended to implement the plain
|
||||
* {@link BeanPostProcessor} interface as far as possible, or to derive from
|
||||
* {@link InstantiationAwareBeanPostProcessorAdapter} in order to be shielded
|
||||
* from extensions to this interface.
|
||||
* {@link BeanPostProcessor} interface as far as possible.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rod Johnson
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Support package for the Java 6 ServiceLoader facility.
|
||||
* Support package for the Java {@link java.util.ServiceLoader} facility.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -1844,7 +1844,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
throws Throwable {
|
||||
|
||||
boolean isInitializingBean = (bean instanceof InitializingBean);
|
||||
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
|
||||
if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
|
||||
}
|
||||
@@ -1868,7 +1868,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
String initMethodName = mbd.getInitMethodName();
|
||||
if (StringUtils.hasLength(initMethodName) &&
|
||||
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
|
||||
!mbd.isExternallyManagedInitMethod(initMethodName)) {
|
||||
!mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
|
||||
invokeCustomInitMethod(beanName, bean, mbd);
|
||||
}
|
||||
}
|
||||
@@ -1908,7 +1908,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
|
||||
}
|
||||
Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);
|
||||
Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod, bean.getClass());
|
||||
|
||||
if (System.getSecurityManager() != null) {
|
||||
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
|
||||
|
||||
+9
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -103,6 +103,14 @@ public abstract class AbstractBeanDefinitionReader implements BeanDefinitionRead
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the bean factory to register the bean definitions with.
|
||||
* <p>The factory is exposed through the BeanDefinitionRegistry interface,
|
||||
* encapsulating the methods that are relevant for bean definition handling.
|
||||
* @deprecated as of Spring Framework 5.3.15 in favor of {@link #getRegistry()},
|
||||
* to be removed in Spring Framework 6.0
|
||||
*/
|
||||
@Deprecated
|
||||
public final BeanDefinitionRegistry getBeanFactory() {
|
||||
return this.registry;
|
||||
}
|
||||
|
||||
+17
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,15 +22,15 @@ import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Simple interface for bean definition readers.
|
||||
* Specifies load methods with Resource and String location parameters.
|
||||
* Simple interface for bean definition readers that specifies load methods with
|
||||
* {@link Resource} and {@link String} location parameters.
|
||||
*
|
||||
* <p>Concrete bean definition readers can of course add additional
|
||||
* load and register methods for bean definitions, specific to
|
||||
* their bean definition format.
|
||||
*
|
||||
* <p>Note that a bean definition reader does not have to implement
|
||||
* this interface. It only serves as suggestion for bean definition
|
||||
* this interface. It only serves as a suggestion for bean definition
|
||||
* readers that want to follow standard naming conventions.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
@@ -41,14 +41,14 @@ public interface BeanDefinitionReader {
|
||||
|
||||
/**
|
||||
* Return the bean factory to register the bean definitions with.
|
||||
* <p>The factory is exposed through the BeanDefinitionRegistry interface,
|
||||
* <p>The factory is exposed through the {@link BeanDefinitionRegistry} interface,
|
||||
* encapsulating the methods that are relevant for bean definition handling.
|
||||
*/
|
||||
BeanDefinitionRegistry getRegistry();
|
||||
|
||||
/**
|
||||
* Return the resource loader to use for resource locations.
|
||||
* Can be checked for the <b>ResourcePatternResolver</b> interface and cast
|
||||
* Return the {@link ResourceLoader} to use for resource locations.
|
||||
* <p>Can be checked for the {@code ResourcePatternResolver} interface and cast
|
||||
* accordingly, for loading multiple resources for a given resource pattern.
|
||||
* <p>A {@code null} return value suggests that absolute resource loading
|
||||
* is not available for this bean definition reader.
|
||||
@@ -56,10 +56,10 @@ public interface BeanDefinitionReader {
|
||||
* from within a bean definition resource, for example via the "import"
|
||||
* tag in XML bean definitions. It is recommended, however, to apply
|
||||
* such imports relative to the defining resource; only explicit full
|
||||
* resource locations will trigger absolute resource loading.
|
||||
* resource locations will trigger absolute path based resource loading.
|
||||
* <p>There is also a {@code loadBeanDefinitions(String)} method available,
|
||||
* for loading bean definitions from a resource location (or location pattern).
|
||||
* This is a convenience to avoid explicit ResourceLoader handling.
|
||||
* This is a convenience to avoid explicit {@code ResourceLoader} handling.
|
||||
* @see #loadBeanDefinitions(String)
|
||||
* @see org.springframework.core.io.support.ResourcePatternResolver
|
||||
*/
|
||||
@@ -70,13 +70,13 @@ public interface BeanDefinitionReader {
|
||||
* Return the class loader to use for bean classes.
|
||||
* <p>{@code null} suggests to not load bean classes eagerly
|
||||
* but rather to just register bean definitions with class names,
|
||||
* with the corresponding Classes to be resolved later (or never).
|
||||
* with the corresponding classes to be resolved later (or never).
|
||||
*/
|
||||
@Nullable
|
||||
ClassLoader getBeanClassLoader();
|
||||
|
||||
/**
|
||||
* Return the BeanNameGenerator to use for anonymous beans
|
||||
* Return the {@link BeanNameGenerator} to use for anonymous beans
|
||||
* (without explicit bean name specified).
|
||||
*/
|
||||
BeanNameGenerator getBeanNameGenerator();
|
||||
@@ -101,9 +101,10 @@ public interface BeanDefinitionReader {
|
||||
/**
|
||||
* Load bean definitions from the specified resource location.
|
||||
* <p>The location can also be a location pattern, provided that the
|
||||
* ResourceLoader of this bean definition reader is a ResourcePatternResolver.
|
||||
* @param location the resource location, to be loaded with the ResourceLoader
|
||||
* (or ResourcePatternResolver) of this bean definition reader
|
||||
* {@link ResourceLoader} of this bean definition reader is a
|
||||
* {@code ResourcePatternResolver}.
|
||||
* @param location the resource location, to be loaded with the {@code ResourceLoader}
|
||||
* (or {@code ResourcePatternResolver}) of this bean definition reader
|
||||
* @return the number of bean definitions found
|
||||
* @throws BeanDefinitionStoreException in case of loading or parsing errors
|
||||
* @see #getResourceLoader()
|
||||
@@ -114,8 +115,8 @@ public interface BeanDefinitionReader {
|
||||
|
||||
/**
|
||||
* Load bean definitions from the specified resource locations.
|
||||
* @param locations the resource locations, to be loaded with the ResourceLoader
|
||||
* (or ResourcePatternResolver) of this bean definition reader
|
||||
* @param locations the resource locations, to be loaded with the {@code ResourceLoader}
|
||||
* (or {@code ResourcePatternResolver}) of this bean definition reader
|
||||
* @return the number of bean definitions found
|
||||
* @throws BeanDefinitionStoreException in case of loading or parsing errors
|
||||
*/
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -985,7 +985,7 @@ class ConstructorResolver {
|
||||
|
||||
|
||||
/**
|
||||
* Delegate for checking Java 6's {@link ConstructorProperties} annotation.
|
||||
* Delegate for checking Java's {@link ConstructorProperties} annotation.
|
||||
*/
|
||||
private static class ConstructorPropertiesChecker {
|
||||
|
||||
|
||||
+13
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -730,14 +730,23 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
|
||||
return findMergedAnnotationOnBean(beanName, annotationType)
|
||||
return findAnnotationOnBean(beanName, annotationType, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <A extends Annotation> A findAnnotationOnBean(
|
||||
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
|
||||
return findMergedAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit)
|
||||
.synthesize(MergedAnnotation::isPresent).orElse(null);
|
||||
}
|
||||
|
||||
private <A extends Annotation> MergedAnnotation<A> findMergedAnnotationOnBean(
|
||||
String beanName, Class<A> annotationType) {
|
||||
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit) {
|
||||
|
||||
Class<?> beanType = getType(beanName);
|
||||
Class<?> beanType = getType(beanName, allowFactoryBeanInit);
|
||||
if (beanType != null) {
|
||||
MergedAnnotation<A> annotation =
|
||||
MergedAnnotations.from(beanType, SearchStrategy.TYPE_HIERARCHY).get(annotationType);
|
||||
|
||||
+8
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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,6 +52,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Juergen Hoeller
|
||||
* @author Costin Leau
|
||||
* @author Stephane Nicoll
|
||||
* @author Sam Brannen
|
||||
* @since 2.0
|
||||
* @see AbstractBeanFactory
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
@@ -109,12 +110,12 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
this.beanName = beanName;
|
||||
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
|
||||
this.invokeDisposableBean = (bean instanceof DisposableBean &&
|
||||
!beanDefinition.isExternallyManagedDestroyMethod(DESTROY_METHOD_NAME));
|
||||
!beanDefinition.hasAnyExternallyManagedDestroyMethod(DESTROY_METHOD_NAME));
|
||||
|
||||
String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
|
||||
if (destroyMethodName != null &&
|
||||
!(this.invokeDisposableBean && DESTROY_METHOD_NAME.equals(destroyMethodName)) &&
|
||||
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
|
||||
!beanDefinition.hasAnyExternallyManagedDestroyMethod(destroyMethodName)) {
|
||||
|
||||
this.invokeAutoCloseable = (bean instanceof AutoCloseable && CLOSE_METHOD_NAME.equals(destroyMethodName));
|
||||
if (!this.invokeAutoCloseable) {
|
||||
@@ -138,7 +139,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
beanName + "' has a non-boolean parameter - not supported as destroy method");
|
||||
}
|
||||
}
|
||||
destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
|
||||
destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod, bean.getClass());
|
||||
}
|
||||
this.destroyMethod = destroyMethod;
|
||||
}
|
||||
@@ -252,9 +253,9 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
invokeCustomDestroyMethod(this.destroyMethod);
|
||||
}
|
||||
else if (this.destroyMethodName != null) {
|
||||
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
|
||||
if (methodToInvoke != null) {
|
||||
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
|
||||
Method destroyMethod = determineDestroyMethod(this.destroyMethodName);
|
||||
if (destroyMethod != null) {
|
||||
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(destroyMethod, this.bean.getClass()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 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,6 +17,7 @@
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
@@ -53,6 +54,20 @@ public class ManagedList<E> extends ArrayList<E> implements Mergeable, BeanMetad
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a new instance containing an arbitrary number of elements.
|
||||
* @param elements the elements to be contained in the list
|
||||
* @param <E> the {@code List}'s element type
|
||||
* @return a {@code List} containing the specified elements
|
||||
* @since 5.3.16
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E> ManagedList<E> of(E... elements) {
|
||||
ManagedList<E> list = new ManagedList<>();
|
||||
list.addAll(Arrays.asList(elements));
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the configuration source {@code Object} for this metadata element.
|
||||
* <p>The exact type of the object will depend on the configuration mechanism used.
|
||||
|
||||
+22
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.beans.factory.support;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.Mergeable;
|
||||
@@ -56,6 +57,26 @@ public class ManagedMap<K, V> extends LinkedHashMap<K, V> implements Mergeable,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a new instance containing keys and values extracted from the
|
||||
* given entries. The entries themselves are not stored in the map.
|
||||
* @param entries {@code Map.Entry}s containing the keys and values
|
||||
* from which the map is populated
|
||||
* @param <K> the {@code Map}'s key type
|
||||
* @param <V> the {@code Map}'s value type
|
||||
* @return a {@code Map} containing the specified mappings
|
||||
* @since 5.3.16
|
||||
*/
|
||||
@SafeVarargs
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <K,V> ManagedMap<K,V> ofEntries(Entry<? extends K, ? extends V>... entries) {
|
||||
ManagedMap<K,V > map = new ManagedMap<>();
|
||||
for (Entry<? extends K, ? extends V> entry : entries) {
|
||||
map.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the configuration source {@code Object} for this metadata element.
|
||||
* <p>The exact type of the object will depend on the configuration mechanism used.
|
||||
|
||||
+16
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -52,6 +53,20 @@ public class ManagedSet<E> extends LinkedHashSet<E> implements Mergeable, BeanMe
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a new instance containing an arbitrary number of elements.
|
||||
* @param elements the elements to be contained in the set
|
||||
* @param <E> the {@code Set}'s element type
|
||||
* @return a {@code Set} containing the specified elements
|
||||
* @since 5.3.16
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E> ManagedSet<E> of(E... elements) {
|
||||
ManagedSet<E> set = new ManagedSet<>();
|
||||
set.addAll(Arrays.asList(elements));
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the configuration source {@code Object} for this metadata element.
|
||||
* <p>The exact type of the object will depend on the configuration mechanism used.
|
||||
|
||||
+95
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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,6 +49,7 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @see GenericBeanDefinition
|
||||
* @see ChildBeanDefinition
|
||||
*/
|
||||
@@ -436,7 +437,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given method or field is an externally managed configuration member.
|
||||
* Determine if the given method or field is an externally managed configuration member.
|
||||
*/
|
||||
public boolean isExternallyManagedConfigMember(Member configMember) {
|
||||
synchronized (this.postProcessingLock) {
|
||||
@@ -446,7 +447,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all externally managed configuration methods and fields (as an immutable Set).
|
||||
* Get all externally managed configuration methods and fields (as an immutable Set).
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public Set<Member> getExternallyManagedConfigMembers() {
|
||||
@@ -458,7 +459,15 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an externally managed configuration initialization method.
|
||||
* Register an externally managed configuration initialization method —
|
||||
* for example, a method annotated with JSR-250's
|
||||
* {@link javax.annotation.PostConstruct} annotation.
|
||||
* <p>The supplied {@code initMethod} may be the
|
||||
* {@linkplain Method#getName() simple method name} for non-private methods or the
|
||||
* {@linkplain org.springframework.util.ClassUtils#getQualifiedMethodName(Method)
|
||||
* qualified method name} for {@code private} methods. A qualified name is
|
||||
* necessary for {@code private} methods in order to disambiguate between
|
||||
* multiple private methods with the same name within a class hierarchy.
|
||||
*/
|
||||
public void registerExternallyManagedInitMethod(String initMethod) {
|
||||
synchronized (this.postProcessingLock) {
|
||||
@@ -470,7 +479,10 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given method name indicates an externally managed initialization method.
|
||||
* Determine if the given method name indicates an externally managed
|
||||
* initialization method.
|
||||
* <p>See {@link #registerExternallyManagedInitMethod} for details
|
||||
* regarding the format for the supplied {@code initMethod}.
|
||||
*/
|
||||
public boolean isExternallyManagedInitMethod(String initMethod) {
|
||||
synchronized (this.postProcessingLock) {
|
||||
@@ -479,8 +491,40 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given method name indicates an externally managed
|
||||
* initialization method, regardless of method visibility.
|
||||
* <p>In contrast to {@link #isExternallyManagedInitMethod(String)}, this
|
||||
* method also returns {@code true} if there is a {@code private} externally
|
||||
* managed initialization method that has been
|
||||
* {@linkplain #registerExternallyManagedInitMethod(String) registered}
|
||||
* using a qualified method name instead of a simple method name.
|
||||
* @since 5.3.17
|
||||
*/
|
||||
boolean hasAnyExternallyManagedInitMethod(String initMethod) {
|
||||
synchronized (this.postProcessingLock) {
|
||||
if (isExternallyManagedInitMethod(initMethod)) {
|
||||
return true;
|
||||
}
|
||||
if (this.externallyManagedInitMethods != null) {
|
||||
for (String candidate : this.externallyManagedInitMethods) {
|
||||
int indexOfDot = candidate.lastIndexOf('.');
|
||||
if (indexOfDot >= 0) {
|
||||
String methodName = candidate.substring(indexOfDot + 1);
|
||||
if (methodName.equals(initMethod)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all externally managed initialization methods (as an immutable Set).
|
||||
* <p>See {@link #registerExternallyManagedInitMethod} for details
|
||||
* regarding the format for the initialization methods in the returned set.
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public Set<String> getExternallyManagedInitMethods() {
|
||||
@@ -492,7 +536,15 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an externally managed configuration destruction method.
|
||||
* Register an externally managed configuration destruction method —
|
||||
* for example, a method annotated with JSR-250's
|
||||
* {@link javax.annotation.PreDestroy} annotation.
|
||||
* <p>The supplied {@code destroyMethod} may be the
|
||||
* {@linkplain Method#getName() simple method name} for non-private methods or the
|
||||
* {@linkplain org.springframework.util.ClassUtils#getQualifiedMethodName(Method)
|
||||
* qualified method name} for {@code private} methods. A qualified name is
|
||||
* necessary for {@code private} methods in order to disambiguate between
|
||||
* multiple private methods with the same name within a class hierarchy.
|
||||
*/
|
||||
public void registerExternallyManagedDestroyMethod(String destroyMethod) {
|
||||
synchronized (this.postProcessingLock) {
|
||||
@@ -504,7 +556,10 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given method name indicates an externally managed destruction method.
|
||||
* Determine if the given method name indicates an externally managed
|
||||
* destruction method.
|
||||
* <p>See {@link #registerExternallyManagedDestroyMethod} for details
|
||||
* regarding the format for the supplied {@code destroyMethod}.
|
||||
*/
|
||||
public boolean isExternallyManagedDestroyMethod(String destroyMethod) {
|
||||
synchronized (this.postProcessingLock) {
|
||||
@@ -514,7 +569,39 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all externally managed destruction methods (as an immutable Set).
|
||||
* Determine if the given method name indicates an externally managed
|
||||
* destruction method, regardless of method visibility.
|
||||
* <p>In contrast to {@link #isExternallyManagedDestroyMethod(String)}, this
|
||||
* method also returns {@code true} if there is a {@code private} externally
|
||||
* managed destruction method that has been
|
||||
* {@linkplain #registerExternallyManagedDestroyMethod(String) registered}
|
||||
* using a qualified method name instead of a simple method name.
|
||||
* @since 5.3.17
|
||||
*/
|
||||
boolean hasAnyExternallyManagedDestroyMethod(String destroyMethod) {
|
||||
synchronized (this.postProcessingLock) {
|
||||
if (isExternallyManagedDestroyMethod(destroyMethod)) {
|
||||
return true;
|
||||
}
|
||||
if (this.externallyManagedDestroyMethods != null) {
|
||||
for (String candidate : this.externallyManagedDestroyMethods) {
|
||||
int indexOfDot = candidate.lastIndexOf('.');
|
||||
if (indexOfDot >= 0) {
|
||||
String methodName = candidate.substring(indexOfDot + 1);
|
||||
if (methodName.equals(destroyMethod)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all externally managed destruction methods (as an immutable Set).
|
||||
* <p>See {@link #registerExternallyManagedDestroyMethod} for details
|
||||
* regarding the format for the destruction methods in the returned set.
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public Set<String> getExternallyManagedDestroyMethods() {
|
||||
|
||||
+11
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -459,7 +459,16 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
|
||||
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
|
||||
Class<?> beanType = getType(beanName);
|
||||
return findAnnotationOnBean(beanName, annotationType, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <A extends Annotation> A findAnnotationOnBean(
|
||||
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
|
||||
Class<?> beanType = getType(beanName, allowFactoryBeanInit);
|
||||
return (beanType != null ? AnnotatedElementUtils.findMergedAnnotation(beanType, annotationType) : null);
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2022 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,6 +43,7 @@ import org.springframework.core.io.ContextResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceEditor;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.WritableResource;
|
||||
import org.springframework.core.io.support.ResourceArrayPropertyEditor;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
|
||||
@@ -102,6 +103,7 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
|
||||
ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
|
||||
doRegisterEditor(registry, Resource.class, baseEditor);
|
||||
doRegisterEditor(registry, ContextResource.class, baseEditor);
|
||||
doRegisterEditor(registry, WritableResource.class, baseEditor);
|
||||
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
|
||||
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
|
||||
doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,7 +39,7 @@ inline fun <reified T : Any> ListableBeanFactory.getBeansOfType(includeNonSingle
|
||||
|
||||
/**
|
||||
* Extension for [ListableBeanFactory.getBeanNamesForAnnotation] providing a
|
||||
* `getBeansOfType<Foo>()` variant.
|
||||
* `getBeanNamesForAnnotation<Foo>()` variant.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @since 5.0
|
||||
@@ -64,6 +64,6 @@ inline fun <reified T : Annotation> ListableBeanFactory.getBeansWithAnnotation()
|
||||
* @author Sebastien Deleuze
|
||||
* @since 5.0
|
||||
*/
|
||||
inline fun <reified T : Annotation> ListableBeanFactory.findAnnotationOnBean(beanName:String): Annotation? =
|
||||
inline fun <reified T : Annotation> ListableBeanFactory.findAnnotationOnBean(beanName:String): T? =
|
||||
findAnnotationOnBean(beanName, T::class.java)
|
||||
|
||||
|
||||
+4
-4
@@ -43,13 +43,13 @@ public abstract class AbstractPropertyValuesTests {
|
||||
m.put("forname", "Tony");
|
||||
m.put("surname", "Blair");
|
||||
m.put("age", "50");
|
||||
for (int i = 0; i < ps.length; i++) {
|
||||
Object val = m.get(ps[i].getName());
|
||||
for (PropertyValue element : ps) {
|
||||
Object val = m.get(element.getName());
|
||||
assertThat(val != null).as("Can't have unexpected value").isTrue();
|
||||
boolean condition = val instanceof String;
|
||||
assertThat(condition).as("Val i string").isTrue();
|
||||
assertThat(val.equals(ps[i].getValue())).as("val matches expected").isTrue();
|
||||
m.remove(ps[i].getName());
|
||||
assertThat(val.equals(element.getValue())).as("val matches expected").isTrue();
|
||||
m.remove(element.getName());
|
||||
}
|
||||
assertThat(m.size() == 0).as("Map size is 0").isTrue();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -203,8 +203,25 @@ class BeanUtilsTests {
|
||||
assertThat(tb2.getTouchy().equals(tb.getTouchy())).as("Touchy copied").isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code Integer} can be copied to {@code Number}.
|
||||
*/
|
||||
@Test
|
||||
void copyPropertiesHonorsGenericTypeMatches() {
|
||||
void copyPropertiesFromSubTypeToSuperType() {
|
||||
IntegerHolder integerHolder = new IntegerHolder();
|
||||
integerHolder.setNumber(42);
|
||||
NumberHolder numberHolder = new NumberHolder();
|
||||
|
||||
BeanUtils.copyProperties(integerHolder, numberHolder);
|
||||
assertThat(integerHolder.getNumber()).isEqualTo(42);
|
||||
assertThat(numberHolder.getNumber()).isEqualTo(42);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code List<Integer>} can be copied to {@code List<Integer>}.
|
||||
*/
|
||||
@Test
|
||||
void copyPropertiesHonorsGenericTypeMatchesFromIntegerToInteger() {
|
||||
IntegerListHolder1 integerListHolder1 = new IntegerListHolder1();
|
||||
integerListHolder1.getList().add(42);
|
||||
IntegerListHolder2 integerListHolder2 = new IntegerListHolder2();
|
||||
@@ -214,6 +231,68 @@ class BeanUtilsTests {
|
||||
assertThat(integerListHolder2.getList()).containsOnly(42);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code List<?>} can be copied to {@code List<?>}.
|
||||
*/
|
||||
@Test
|
||||
void copyPropertiesHonorsGenericTypeMatchesFromWildcardToWildcard() {
|
||||
List<?> list = Arrays.asList("foo", 42);
|
||||
WildcardListHolder1 wildcardListHolder1 = new WildcardListHolder1();
|
||||
wildcardListHolder1.setList(list);
|
||||
WildcardListHolder2 wildcardListHolder2 = new WildcardListHolder2();
|
||||
assertThat(wildcardListHolder2.getList()).isEmpty();
|
||||
|
||||
BeanUtils.copyProperties(wildcardListHolder1, wildcardListHolder2);
|
||||
assertThat(wildcardListHolder1.getList()).isEqualTo(list);
|
||||
assertThat(wildcardListHolder2.getList()).isEqualTo(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code List<Integer>} can be copied to {@code List<?>}.
|
||||
*/
|
||||
@Test
|
||||
void copyPropertiesHonorsGenericTypeMatchesFromIntegerToWildcard() {
|
||||
IntegerListHolder1 integerListHolder1 = new IntegerListHolder1();
|
||||
integerListHolder1.getList().add(42);
|
||||
WildcardListHolder2 wildcardListHolder2 = new WildcardListHolder2();
|
||||
|
||||
BeanUtils.copyProperties(integerListHolder1, wildcardListHolder2);
|
||||
assertThat(integerListHolder1.getList()).containsOnly(42);
|
||||
assertThat(wildcardListHolder2.getList()).isEqualTo(Arrays.asList(42));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code List<Integer>} can be copied to {@code List<? extends Number>}.
|
||||
*/
|
||||
@Test
|
||||
void copyPropertiesHonorsGenericTypeMatchesForUpperBoundedWildcard() {
|
||||
IntegerListHolder1 integerListHolder1 = new IntegerListHolder1();
|
||||
integerListHolder1.getList().add(42);
|
||||
NumberUpperBoundedWildcardListHolder numberListHolder = new NumberUpperBoundedWildcardListHolder();
|
||||
|
||||
BeanUtils.copyProperties(integerListHolder1, numberListHolder);
|
||||
assertThat(integerListHolder1.getList()).containsOnly(42);
|
||||
assertThat(numberListHolder.getList()).hasSize(1);
|
||||
assertThat(numberListHolder.getList().contains(Integer.valueOf(42))).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code Number} can NOT be copied to {@code Integer}.
|
||||
*/
|
||||
@Test
|
||||
void copyPropertiesDoesNotCopyeFromSuperTypeToSubType() {
|
||||
NumberHolder numberHolder = new NumberHolder();
|
||||
numberHolder.setNumber(Integer.valueOf(42));
|
||||
IntegerHolder integerHolder = new IntegerHolder();
|
||||
|
||||
BeanUtils.copyProperties(numberHolder, integerHolder);
|
||||
assertThat(numberHolder.getNumber()).isEqualTo(42);
|
||||
assertThat(integerHolder.getNumber()).isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code List<Integer>} can NOT be copied to {@code List<Long>}.
|
||||
*/
|
||||
@Test
|
||||
void copyPropertiesDoesNotHonorGenericTypeMismatches() {
|
||||
IntegerListHolder1 integerListHolder = new IntegerListHolder1();
|
||||
@@ -225,6 +304,20 @@ class BeanUtilsTests {
|
||||
assertThat(longListHolder.getList()).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code List<Integer>} can NOT be copied to {@code List<Number>}.
|
||||
*/
|
||||
@Test
|
||||
void copyPropertiesDoesNotHonorGenericTypeMismatchesFromSubTypeToSuperType() {
|
||||
IntegerListHolder1 integerListHolder = new IntegerListHolder1();
|
||||
integerListHolder.getList().add(42);
|
||||
NumberListHolder numberListHolder = new NumberListHolder();
|
||||
|
||||
BeanUtils.copyProperties(integerListHolder, numberListHolder);
|
||||
assertThat(integerListHolder.getList()).containsOnly(42);
|
||||
assertThat(numberListHolder.getList()).isEmpty();
|
||||
}
|
||||
|
||||
@Test // gh-26531
|
||||
void copyPropertiesIgnoresGenericsIfSourceOrTargetHasUnresolvableGenerics() throws Exception {
|
||||
Order original = new Order("test", Arrays.asList("foo", "bar"));
|
||||
@@ -413,6 +506,90 @@ class BeanUtilsTests {
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class NumberHolder {
|
||||
|
||||
private Number number;
|
||||
|
||||
public Number getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public void setNumber(Number number) {
|
||||
this.number = number;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class IntegerHolder {
|
||||
|
||||
private Integer number;
|
||||
|
||||
public Integer getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public void setNumber(Integer number) {
|
||||
this.number = number;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class WildcardListHolder1 {
|
||||
|
||||
private List<?> list = new ArrayList<>();
|
||||
|
||||
public List<?> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
public void setList(List<?> list) {
|
||||
this.list = list;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class WildcardListHolder2 {
|
||||
|
||||
private List<?> list = new ArrayList<>();
|
||||
|
||||
public List<?> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
public void setList(List<?> list) {
|
||||
this.list = list;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class NumberUpperBoundedWildcardListHolder {
|
||||
|
||||
private List<? extends Number> list = new ArrayList<>();
|
||||
|
||||
public List<? extends Number> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
public void setList(List<? extends Number> list) {
|
||||
this.list = list;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class NumberListHolder {
|
||||
|
||||
private List<Number> list = new ArrayList<>();
|
||||
|
||||
public List<Number> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
public void setList(List<Number> list) {
|
||||
this.list = list;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class IntegerListHolder1 {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -46,7 +46,7 @@ public class BeanWrapperEnumTests {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("customEnum", null);
|
||||
assertThat(gb.getCustomEnum()).isEqualTo(null);
|
||||
assertThat(gb.getCustomEnum()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -54,7 +54,7 @@ public class BeanWrapperEnumTests {
|
||||
GenericBean<?> gb = new GenericBean<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("customEnum", "");
|
||||
assertThat(gb.getCustomEnum()).isEqualTo(null);
|
||||
assertThat(gb.getCustomEnum()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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,6 +23,9 @@ import java.util.Optional;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.core.OverridingClassLoader;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
@@ -105,7 +108,7 @@ class BeanWrapperTests extends AbstractPropertyAccessorTests {
|
||||
.satisfies(ex -> assertThat(ex.getPossibleMatches()).containsExactly("age"));
|
||||
}
|
||||
|
||||
@Test // Can't be shared; there is no such thing as a read-only field
|
||||
@Test // Can't be shared; there is no such thing as a read-only field
|
||||
void setReadOnlyMapProperty() {
|
||||
TypedReadOnlyMap map = new TypedReadOnlyMap(Collections.singletonMap("key", new TestBean()));
|
||||
TypedReadOnlyMapClient target = new TypedReadOnlyMapClient();
|
||||
@@ -151,18 +154,58 @@ class BeanWrapperTests extends AbstractPropertyAccessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void propertyDescriptors() {
|
||||
void propertyDescriptors() throws Exception {
|
||||
TestBean target = new TestBean();
|
||||
target.setSpouse(new TestBean());
|
||||
BeanWrapper accessor = createAccessor(target);
|
||||
accessor.setPropertyValue("name", "a");
|
||||
accessor.setPropertyValue("spouse.name", "b");
|
||||
|
||||
assertThat(target.getName()).isEqualTo("a");
|
||||
assertThat(target.getSpouse().getName()).isEqualTo("b");
|
||||
assertThat(accessor.getPropertyValue("name")).isEqualTo("a");
|
||||
assertThat(accessor.getPropertyValue("spouse.name")).isEqualTo("b");
|
||||
assertThat(accessor.getPropertyDescriptor("name").getPropertyType()).isEqualTo(String.class);
|
||||
assertThat(accessor.getPropertyDescriptor("spouse.name").getPropertyType()).isEqualTo(String.class);
|
||||
|
||||
assertThat(accessor.isReadableProperty("class.package")).isFalse();
|
||||
assertThat(accessor.isReadableProperty("class.module")).isFalse();
|
||||
assertThat(accessor.isReadableProperty("class.classLoader")).isFalse();
|
||||
assertThat(accessor.isReadableProperty("class.name")).isTrue();
|
||||
assertThat(accessor.isReadableProperty("class.simpleName")).isTrue();
|
||||
assertThat(accessor.getPropertyValue("class.name")).isEqualTo(TestBean.class.getName());
|
||||
assertThat(accessor.getPropertyValue("class.simpleName")).isEqualTo(TestBean.class.getSimpleName());
|
||||
assertThat(accessor.getPropertyDescriptor("class.name").getPropertyType()).isEqualTo(String.class);
|
||||
assertThat(accessor.getPropertyDescriptor("class.simpleName").getPropertyType()).isEqualTo(String.class);
|
||||
|
||||
accessor = createAccessor(new DefaultResourceLoader());
|
||||
|
||||
assertThat(accessor.isReadableProperty("class.package")).isFalse();
|
||||
assertThat(accessor.isReadableProperty("class.module")).isFalse();
|
||||
assertThat(accessor.isReadableProperty("class.classLoader")).isFalse();
|
||||
assertThat(accessor.isReadableProperty("class.name")).isTrue();
|
||||
assertThat(accessor.isReadableProperty("class.simpleName")).isTrue();
|
||||
assertThat(accessor.isReadableProperty("classLoader")).isTrue();
|
||||
assertThat(accessor.isWritableProperty("classLoader")).isTrue();
|
||||
OverridingClassLoader ocl = new OverridingClassLoader(getClass().getClassLoader());
|
||||
accessor.setPropertyValue("classLoader", ocl);
|
||||
assertThat(accessor.getPropertyValue("classLoader")).isSameAs(ocl);
|
||||
|
||||
accessor = createAccessor(new UrlResource("https://spring.io"));
|
||||
|
||||
assertThat(accessor.isReadableProperty("class.package")).isFalse();
|
||||
assertThat(accessor.isReadableProperty("class.module")).isFalse();
|
||||
assertThat(accessor.isReadableProperty("class.classLoader")).isFalse();
|
||||
assertThat(accessor.isReadableProperty("class.name")).isTrue();
|
||||
assertThat(accessor.isReadableProperty("class.simpleName")).isTrue();
|
||||
assertThat(accessor.isReadableProperty("URL.protocol")).isTrue();
|
||||
assertThat(accessor.isReadableProperty("URL.host")).isTrue();
|
||||
assertThat(accessor.isReadableProperty("URL.port")).isTrue();
|
||||
assertThat(accessor.isReadableProperty("URL.file")).isTrue();
|
||||
assertThat(accessor.isReadableProperty("URL.content")).isFalse();
|
||||
assertThat(accessor.isReadableProperty("inputStream")).isFalse();
|
||||
assertThat(accessor.isReadableProperty("filename")).isTrue();
|
||||
assertThat(accessor.isReadableProperty("description")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
@@ -483,6 +483,7 @@ public class BeanFactoryUtilsTests {
|
||||
return TestBean.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestBean getObject() {
|
||||
// We don't really care if the actual instance is a singleton or prototype
|
||||
// for the tests that use this factory.
|
||||
|
||||
+22
-31
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -48,8 +48,6 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.NotWritablePropertyException;
|
||||
import org.springframework.beans.PropertyEditorRegistrar;
|
||||
import org.springframework.beans.PropertyEditorRegistry;
|
||||
import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.TypeMismatchException;
|
||||
@@ -84,7 +82,6 @@ import org.springframework.beans.testfixture.beans.factory.DummyFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.core.io.Resource;
|
||||
@@ -433,7 +430,7 @@ class DefaultListableBeanFactoryTests {
|
||||
assertThat(lbf.isTypeMatch("x1", Object.class)).isTrue();
|
||||
assertThat(lbf.isTypeMatch("&x1", Object.class)).isFalse();
|
||||
assertThat(lbf.getType("x1")).isEqualTo(TestBean.class);
|
||||
assertThat(lbf.getType("&x1")).isEqualTo(null);
|
||||
assertThat(lbf.getType("&x1")).isNull();
|
||||
assertThat(TestBeanFactory.initialized).isFalse();
|
||||
|
||||
lbf.registerAlias("x1", "x2");
|
||||
@@ -990,16 +987,13 @@ class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
void customConverter() {
|
||||
GenericConversionService conversionService = new DefaultConversionService();
|
||||
conversionService.addConverter(new Converter<String, Float>() {
|
||||
@Override
|
||||
public Float convert(String source) {
|
||||
try {
|
||||
NumberFormat nf = NumberFormat.getInstance(Locale.GERMAN);
|
||||
return nf.parse(source).floatValue();
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
throw new IllegalArgumentException(ex);
|
||||
}
|
||||
conversionService.addConverter(String.class, Float.class, source -> {
|
||||
try {
|
||||
NumberFormat nf = NumberFormat.getInstance(Locale.GERMAN);
|
||||
return nf.parse(source).floatValue();
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
throw new IllegalArgumentException(ex);
|
||||
}
|
||||
});
|
||||
lbf.setConversionService(conversionService);
|
||||
@@ -1014,12 +1008,9 @@ class DefaultListableBeanFactoryTests {
|
||||
|
||||
@Test
|
||||
void customEditorWithBeanReference() {
|
||||
lbf.addPropertyEditorRegistrar(new PropertyEditorRegistrar() {
|
||||
@Override
|
||||
public void registerCustomEditors(PropertyEditorRegistry registry) {
|
||||
NumberFormat nf = NumberFormat.getInstance(Locale.GERMAN);
|
||||
registry.registerCustomEditor(Float.class, new CustomNumberEditor(Float.class, nf, true));
|
||||
}
|
||||
lbf.addPropertyEditorRegistrar(registry -> {
|
||||
NumberFormat nf = NumberFormat.getInstance(Locale.GERMAN);
|
||||
registry.registerCustomEditor(Float.class, new CustomNumberEditor(Float.class, nf, true));
|
||||
});
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("myFloat", new RuntimeBeanReference("myFloat"));
|
||||
@@ -2307,9 +2298,7 @@ class DefaultListableBeanFactoryTests {
|
||||
|
||||
@Test
|
||||
void prototypeWithArrayConversionForConstructor() {
|
||||
List<String> list = new ManagedList<>();
|
||||
list.add("myName");
|
||||
list.add("myBeanName");
|
||||
List<String> list = ManagedList.of("myName", "myBeanName");
|
||||
RootBeanDefinition bd = new RootBeanDefinition(DerivedTestBean.class);
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
bd.getConstructorArgumentValues().addGenericArgumentValue(list);
|
||||
@@ -2325,9 +2314,7 @@ class DefaultListableBeanFactoryTests {
|
||||
|
||||
@Test
|
||||
void prototypeWithArrayConversionForFactoryMethod() {
|
||||
List<String> list = new ManagedList<>();
|
||||
list.add("myName");
|
||||
list.add("myBeanName");
|
||||
List<String> list = ManagedList.of("myName", "myBeanName");
|
||||
RootBeanDefinition bd = new RootBeanDefinition(DerivedTestBean.class);
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
bd.setFactoryMethodName("create");
|
||||
@@ -2622,8 +2609,8 @@ class DefaultListableBeanFactoryTests {
|
||||
void containsBeanReturnsTrueEvenForAbstractBeanDefinition() {
|
||||
lbf.registerBeanDefinition("abs", BeanDefinitionBuilder
|
||||
.rootBeanDefinition(TestBean.class).setAbstract(true).getBeanDefinition());
|
||||
assertThat(lbf.containsBean("abs")).isEqualTo(true);
|
||||
assertThat(lbf.containsBean("bogus")).isEqualTo(false);
|
||||
assertThat(lbf.containsBean("abs")).isTrue();
|
||||
assertThat(lbf.containsBean("bogus")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -2718,8 +2705,12 @@ class DefaultListableBeanFactoryTests {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
ConstructorDependency that = (ConstructorDependency) o;
|
||||
return spouseAge == that.spouseAge &&
|
||||
Objects.equals(spouse, that.spouse) &&
|
||||
|
||||
+2
-6
@@ -22,7 +22,6 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -3660,11 +3659,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T createMock(Class<T> toMock) {
|
||||
return (T) Proxy.newProxyInstance(AutowiredAnnotationBeanPostProcessorTests.class.getClassLoader(), new Class<?>[] {toMock},
|
||||
new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
throw new UnsupportedOperationException("mocked!");
|
||||
}
|
||||
(InvocationHandler) (proxy, method, args) -> {
|
||||
throw new UnsupportedOperationException("mocked!");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+1
-7
@@ -29,7 +29,6 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.PropertyEditorRegistrar;
|
||||
import org.springframework.beans.PropertyEditorRegistry;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.propertyeditors.CustomDateEditor;
|
||||
@@ -50,12 +49,7 @@ public class CustomEditorConfigurerTests {
|
||||
CustomEditorConfigurer cec = new CustomEditorConfigurer();
|
||||
final DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.GERMAN);
|
||||
cec.setPropertyEditorRegistrars(new PropertyEditorRegistrar[] {
|
||||
new PropertyEditorRegistrar() {
|
||||
@Override
|
||||
public void registerCustomEditors(PropertyEditorRegistry registry) {
|
||||
registry.registerCustomEditor(Date.class, new CustomDateEditor(df, true));
|
||||
}
|
||||
}});
|
||||
registry -> registry.registerCustomEditor(Date.class, new CustomDateEditor(df, true))});
|
||||
cec.postProcessBeanFactory(bf);
|
||||
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
|
||||
+5
-5
@@ -113,7 +113,7 @@ public class MethodInvokingFactoryBeanTests {
|
||||
mcfb = new MethodInvokingFactoryBean();
|
||||
mcfb.setTargetClass(TestClass1.class);
|
||||
mcfb.setTargetMethod("supertypes");
|
||||
mcfb.setArguments(new ArrayList<>(), new ArrayList<Object>(), "hello");
|
||||
mcfb.setArguments(new ArrayList<>(), new ArrayList<>(), "hello");
|
||||
mcfb.afterPropertiesSet();
|
||||
mcfb.getObjectType();
|
||||
|
||||
@@ -184,7 +184,7 @@ public class MethodInvokingFactoryBeanTests {
|
||||
mcfb = new MethodInvokingFactoryBean();
|
||||
mcfb.setTargetClass(TestClass1.class);
|
||||
mcfb.setTargetMethod("supertypes");
|
||||
mcfb.setArguments(new ArrayList<>(), new ArrayList<Object>(), "hello");
|
||||
mcfb.setArguments(new ArrayList<>(), new ArrayList<>(), "hello");
|
||||
// should pass
|
||||
mcfb.afterPropertiesSet();
|
||||
}
|
||||
@@ -194,7 +194,7 @@ public class MethodInvokingFactoryBeanTests {
|
||||
MethodInvokingFactoryBean mcfb = new MethodInvokingFactoryBean();
|
||||
mcfb.setTargetClass(TestClass1.class);
|
||||
mcfb.setTargetMethod("supertypes");
|
||||
mcfb.setArguments(new ArrayList<>(), new ArrayList<Object>(), "hello", "bogus");
|
||||
mcfb.setArguments(new ArrayList<>(), new ArrayList<>(), "hello", "bogus");
|
||||
assertThatExceptionOfType(NoSuchMethodException.class).as(
|
||||
"Matched method with wrong number of args").isThrownBy(
|
||||
mcfb::afterPropertiesSet);
|
||||
@@ -210,14 +210,14 @@ public class MethodInvokingFactoryBeanTests {
|
||||
mcfb = new MethodInvokingFactoryBean();
|
||||
mcfb.setTargetClass(TestClass1.class);
|
||||
mcfb.setTargetMethod("supertypes2");
|
||||
mcfb.setArguments(new ArrayList<>(), new ArrayList<Object>(), "hello", "bogus");
|
||||
mcfb.setArguments(new ArrayList<>(), new ArrayList<>(), "hello", "bogus");
|
||||
mcfb.afterPropertiesSet();
|
||||
assertThat(mcfb.getObject()).isEqualTo("hello");
|
||||
|
||||
mcfb = new MethodInvokingFactoryBean();
|
||||
mcfb.setTargetClass(TestClass1.class);
|
||||
mcfb.setTargetMethod("supertypes2");
|
||||
mcfb.setArguments(new ArrayList<>(), new ArrayList<Object>(), new Object());
|
||||
mcfb.setArguments(new ArrayList<>(), new ArrayList<>(), new Object());
|
||||
assertThatExceptionOfType(NoSuchMethodException.class).as(
|
||||
"Matched method when shouldn't have matched").isThrownBy(
|
||||
mcfb::afterPropertiesSet);
|
||||
|
||||
+13
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -111,7 +112,7 @@ public class PropertyResourceConfigurerTests {
|
||||
|
||||
assertThat(tb1.getAge()).isEqualTo(99);
|
||||
assertThat(tb2.getAge()).isEqualTo(99);
|
||||
assertThat(tb1.getName()).isEqualTo(null);
|
||||
assertThat(tb1.getName()).isNull();
|
||||
assertThat(tb2.getName()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@@ -310,7 +311,7 @@ public class PropertyResourceConfigurerTests {
|
||||
TestBean tb2 = (TestBean) factory.getBean("tb2");
|
||||
assertThat(tb1.getAge()).isEqualTo(99);
|
||||
assertThat(tb2.getAge()).isEqualTo(99);
|
||||
assertThat(tb1.getName()).isEqualTo(null);
|
||||
assertThat(tb1.getName()).isNull();
|
||||
assertThat(tb2.getName()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@@ -357,22 +358,18 @@ public class PropertyResourceConfigurerTests {
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("stringArray", new String[] {"${os.name}", "${age}"});
|
||||
|
||||
List<Object> friends = new ManagedList<>();
|
||||
friends.add("na${age}me");
|
||||
friends.add(new RuntimeBeanReference("${ref}"));
|
||||
List<Object> friends = ManagedList.of("na${age}me", new RuntimeBeanReference("${ref}"));
|
||||
pvs.add("friends", friends);
|
||||
|
||||
Set<Object> someSet = new ManagedSet<>();
|
||||
someSet.add("na${age}me");
|
||||
someSet.add(new RuntimeBeanReference("${ref}"));
|
||||
someSet.add(new TypedStringValue("${age}", Integer.class));
|
||||
Set<Object> someSet = ManagedSet.of("na${age}me",
|
||||
new RuntimeBeanReference("${ref}"), new TypedStringValue("${age}", Integer.class));
|
||||
pvs.add("someSet", someSet);
|
||||
|
||||
Map<Object, Object> someMap = new ManagedMap<>();
|
||||
someMap.put(new TypedStringValue("key${age}"), new TypedStringValue("${age}"));
|
||||
someMap.put(new TypedStringValue("key${age}ref"), new RuntimeBeanReference("${ref}"));
|
||||
someMap.put("key1", new RuntimeBeanReference("${ref}"));
|
||||
someMap.put("key2", "${age}name");
|
||||
Map<Object, Object> someMap = ManagedMap.ofEntries(
|
||||
new SimpleEntry<>(new TypedStringValue("key${age}"), new TypedStringValue("${age}")),
|
||||
new SimpleEntry<>(new TypedStringValue("key${age}ref"), new RuntimeBeanReference("${ref}")),
|
||||
new SimpleEntry<>("key1", new RuntimeBeanReference("${ref}")),
|
||||
new SimpleEntry<>("key2", "${age}name"));
|
||||
MutablePropertyValues innerPvs = new MutablePropertyValues();
|
||||
innerPvs.add("country", "${os.name}");
|
||||
RootBeanDefinition innerBd = new RootBeanDefinition(TestBean.class);
|
||||
@@ -423,7 +420,7 @@ public class PropertyResourceConfigurerTests {
|
||||
TestBean inner1 = (TestBean) tb2.getSomeMap().get("key3");
|
||||
TestBean inner2 = (TestBean) tb2.getSomeMap().get("mykey4");
|
||||
assertThat(inner1.getAge()).isEqualTo(0);
|
||||
assertThat(inner1.getName()).isEqualTo(null);
|
||||
assertThat(inner1.getName()).isNull();
|
||||
assertThat(inner1.getCountry()).isEqualTo(System.getProperty("os.name"));
|
||||
assertThat(inner2.getAge()).isEqualTo(98);
|
||||
assertThat(inner2.getName()).isEqualTo("namemyvarmyvar${");
|
||||
|
||||
+4
-20
@@ -17,7 +17,6 @@
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
@@ -34,8 +33,6 @@ import java.util.stream.Collectors;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.beans.PropertyEditorRegistrar;
|
||||
import org.springframework.beans.PropertyEditorRegistry;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
@@ -409,12 +406,7 @@ class BeanFactoryGenericsTests {
|
||||
@Test
|
||||
void testGenericMapWithCollectionValueConstructor() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.addPropertyEditorRegistrar(new PropertyEditorRegistrar() {
|
||||
@Override
|
||||
public void registerCustomEditors(PropertyEditorRegistry registry) {
|
||||
registry.registerCustomEditor(Number.class, new CustomNumberEditor(Integer.class, false));
|
||||
}
|
||||
});
|
||||
bf.addPropertyEditorRegistrar(registry -> registry.registerCustomEditor(Number.class, new CustomNumberEditor(Integer.class, false)));
|
||||
RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class);
|
||||
|
||||
Map<String, AbstractCollection<?>> input = new HashMap<>();
|
||||
@@ -568,12 +560,7 @@ class BeanFactoryGenericsTests {
|
||||
@Test
|
||||
void testGenericMapWithCollectionValueFactoryMethod() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.addPropertyEditorRegistrar(new PropertyEditorRegistrar() {
|
||||
@Override
|
||||
public void registerCustomEditors(PropertyEditorRegistry registry) {
|
||||
registry.registerCustomEditor(Number.class, new CustomNumberEditor(Integer.class, false));
|
||||
}
|
||||
});
|
||||
bf.addPropertyEditorRegistrar(registry -> registry.registerCustomEditor(Number.class, new CustomNumberEditor(Integer.class, false)));
|
||||
RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class);
|
||||
rbd.setFactoryMethodName("createInstance");
|
||||
|
||||
@@ -1010,11 +997,8 @@ class BeanFactoryGenericsTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T createMock(Class<T> toMock) {
|
||||
return (T) Proxy.newProxyInstance(BeanFactoryGenericsTests.class.getClassLoader(), new Class<?>[] {toMock},
|
||||
new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
throw new UnsupportedOperationException("mocked!");
|
||||
}
|
||||
(InvocationHandler) (proxy, method, args) -> {
|
||||
throw new UnsupportedOperationException("mocked!");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+1
-8
@@ -18,8 +18,6 @@ package org.springframework.beans.factory.support;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.testfixture.beans.DerivedTestBean;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
|
||||
@@ -40,12 +38,7 @@ public class DefaultSingletonBeanRegistryTests {
|
||||
beanRegistry.registerSingleton("tb", tb);
|
||||
assertThat(beanRegistry.getSingleton("tb")).isSameAs(tb);
|
||||
|
||||
TestBean tb2 = (TestBean) beanRegistry.getSingleton("tb2", new ObjectFactory<Object>() {
|
||||
@Override
|
||||
public Object getObject() throws BeansException {
|
||||
return new TestBean();
|
||||
}
|
||||
});
|
||||
TestBean tb2 = (TestBean) beanRegistry.getSingleton("tb2", () -> new TestBean());
|
||||
assertThat(beanRegistry.getSingleton("tb2")).isSameAs(tb2);
|
||||
|
||||
assertThat(beanRegistry.getSingleton("tb")).isSameAs(tb);
|
||||
|
||||
+8
-18
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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,11 +34,8 @@ public class ManagedListTests {
|
||||
|
||||
@Test
|
||||
public void mergeSunnyDay() {
|
||||
ManagedList parent = new ManagedList();
|
||||
parent.add("one");
|
||||
parent.add("two");
|
||||
ManagedList child = new ManagedList();
|
||||
child.add("three");
|
||||
ManagedList parent = ManagedList.of("one", "two");
|
||||
ManagedList child = ManagedList.of("three");
|
||||
child.setMergeEnabled(true);
|
||||
List mergedList = child.merge(parent);
|
||||
assertThat(mergedList.size()).as("merge() obviously did not work.").isEqualTo(3);
|
||||
@@ -46,8 +43,7 @@ public class ManagedListTests {
|
||||
|
||||
@Test
|
||||
public void mergeWithNullParent() {
|
||||
ManagedList child = new ManagedList();
|
||||
child.add("one");
|
||||
ManagedList child = ManagedList.of("one");
|
||||
child.setMergeEnabled(true);
|
||||
assertThat(child.merge(null)).isSameAs(child);
|
||||
}
|
||||
@@ -61,8 +57,7 @@ public class ManagedListTests {
|
||||
|
||||
@Test
|
||||
public void mergeWithNonCompatibleParentType() {
|
||||
ManagedList child = new ManagedList();
|
||||
child.add("one");
|
||||
ManagedList child = ManagedList.of("one");
|
||||
child.setMergeEnabled(true);
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
child.merge("hello"));
|
||||
@@ -70,9 +65,7 @@ public class ManagedListTests {
|
||||
|
||||
@Test
|
||||
public void mergeEmptyChild() {
|
||||
ManagedList parent = new ManagedList();
|
||||
parent.add("one");
|
||||
parent.add("two");
|
||||
ManagedList parent = ManagedList.of("one", "two");
|
||||
ManagedList child = new ManagedList();
|
||||
child.setMergeEnabled(true);
|
||||
List mergedList = child.merge(parent);
|
||||
@@ -82,11 +75,8 @@ public class ManagedListTests {
|
||||
@Test
|
||||
public void mergeChildValuesOverrideTheParents() {
|
||||
// doesn't make much sense in the context of a list...
|
||||
ManagedList parent = new ManagedList();
|
||||
parent.add("one");
|
||||
parent.add("two");
|
||||
ManagedList child = new ManagedList();
|
||||
child.add("one");
|
||||
ManagedList parent = ManagedList.of("one", "two");
|
||||
ManagedList child = ManagedList.of("one");
|
||||
child.setMergeEnabled(true);
|
||||
List mergedList = child.merge(parent);
|
||||
assertThat(mergedList.size()).as("merge() obviously did not work.").isEqualTo(3);
|
||||
|
||||
+10
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -34,11 +35,9 @@ public class ManagedMapTests {
|
||||
|
||||
@Test
|
||||
public void mergeSunnyDay() {
|
||||
ManagedMap parent = new ManagedMap();
|
||||
parent.put("one", "one");
|
||||
parent.put("two", "two");
|
||||
ManagedMap child = new ManagedMap();
|
||||
child.put("three", "three");
|
||||
ManagedMap parent = ManagedMap.ofEntries(new SimpleEntry<>("one", "one"),
|
||||
new SimpleEntry<>("two", "two"));
|
||||
ManagedMap child = ManagedMap.ofEntries(new SimpleEntry<>("tree", "three"));
|
||||
child.setMergeEnabled(true);
|
||||
Map mergedMap = (Map) child.merge(parent);
|
||||
assertThat(mergedMap.size()).as("merge() obviously did not work.").isEqualTo(3);
|
||||
@@ -67,9 +66,8 @@ public class ManagedMapTests {
|
||||
|
||||
@Test
|
||||
public void mergeEmptyChild() {
|
||||
ManagedMap parent = new ManagedMap();
|
||||
parent.put("one", "one");
|
||||
parent.put("two", "two");
|
||||
ManagedMap parent = ManagedMap.ofEntries(new SimpleEntry<>("one", "one"),
|
||||
new SimpleEntry<>("two", "two"));
|
||||
ManagedMap child = new ManagedMap();
|
||||
child.setMergeEnabled(true);
|
||||
Map mergedMap = (Map) child.merge(parent);
|
||||
@@ -78,11 +76,9 @@ public class ManagedMapTests {
|
||||
|
||||
@Test
|
||||
public void mergeChildValuesOverrideTheParents() {
|
||||
ManagedMap parent = new ManagedMap();
|
||||
parent.put("one", "one");
|
||||
parent.put("two", "two");
|
||||
ManagedMap child = new ManagedMap();
|
||||
child.put("one", "fork");
|
||||
ManagedMap parent = ManagedMap.ofEntries(new SimpleEntry<>("one", "one"),
|
||||
new SimpleEntry<>("two", "two"));
|
||||
ManagedMap child = ManagedMap.ofEntries(new SimpleEntry<>("one", "fork"));
|
||||
child.setMergeEnabled(true);
|
||||
Map mergedMap = (Map) child.merge(parent);
|
||||
// child value for 'one' must override parent value...
|
||||
|
||||
+8
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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,10 +34,8 @@ public class ManagedSetTests {
|
||||
|
||||
@Test
|
||||
public void mergeSunnyDay() {
|
||||
ManagedSet parent = new ManagedSet();
|
||||
parent.add("one");
|
||||
parent.add("two");
|
||||
ManagedSet child = new ManagedSet();
|
||||
ManagedSet parent = ManagedSet.of("one", "two");
|
||||
ManagedSet child = ManagedSet.of("three");
|
||||
child.add("three");
|
||||
child.setMergeEnabled(true);
|
||||
Set mergedSet = child.merge(parent);
|
||||
@@ -46,8 +44,7 @@ public class ManagedSetTests {
|
||||
|
||||
@Test
|
||||
public void mergeWithNullParent() {
|
||||
ManagedSet child = new ManagedSet();
|
||||
child.add("one");
|
||||
ManagedSet child = ManagedSet.of("one");
|
||||
child.setMergeEnabled(true);
|
||||
assertThat(child.merge(null)).isSameAs(child);
|
||||
}
|
||||
@@ -60,8 +57,7 @@ public class ManagedSetTests {
|
||||
|
||||
@Test
|
||||
public void mergeWithNonCompatibleParentType() {
|
||||
ManagedSet child = new ManagedSet();
|
||||
child.add("one");
|
||||
ManagedSet child = ManagedSet.of("one");
|
||||
child.setMergeEnabled(true);
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
child.merge("hello"));
|
||||
@@ -69,9 +65,7 @@ public class ManagedSetTests {
|
||||
|
||||
@Test
|
||||
public void mergeEmptyChild() {
|
||||
ManagedSet parent = new ManagedSet();
|
||||
parent.add("one");
|
||||
parent.add("two");
|
||||
ManagedSet parent = ManagedSet.of("one", "two");
|
||||
ManagedSet child = new ManagedSet();
|
||||
child.setMergeEnabled(true);
|
||||
Set mergedSet = child.merge(parent);
|
||||
@@ -81,11 +75,8 @@ public class ManagedSetTests {
|
||||
@Test
|
||||
public void mergeChildValuesOverrideTheParents() {
|
||||
// asserts that the set contract is not violated during a merge() operation...
|
||||
ManagedSet parent = new ManagedSet();
|
||||
parent.add("one");
|
||||
parent.add("two");
|
||||
ManagedSet child = new ManagedSet();
|
||||
child.add("one");
|
||||
ManagedSet parent = ManagedSet.of("one", "two");
|
||||
ManagedSet child = ManagedSet.of("one");
|
||||
child.setMergeEnabled(true);
|
||||
Set mergedSet = child.merge(parent);
|
||||
assertThat(mergedSet.size()).as("merge() obviously did not work.").isEqualTo(2);
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -449,7 +449,7 @@ public class CallbacksSecurityTests {
|
||||
public Object run() {
|
||||
// sanity check
|
||||
assertThat(getCurrentSubjectName()).isEqualTo("user1");
|
||||
assertThat(NonPrivilegedBean.destroyed).isEqualTo(false);
|
||||
assertThat(NonPrivilegedBean.destroyed).isFalse();
|
||||
|
||||
beanFactory.getBean("trusted-spring-callbacks");
|
||||
beanFactory.getBean("trusted-custom-init-destroy");
|
||||
@@ -465,7 +465,7 @@ public class CallbacksSecurityTests {
|
||||
beanFactory.getBean("trusted-working-property-injection");
|
||||
|
||||
beanFactory.destroySingletons();
|
||||
assertThat(NonPrivilegedBean.destroyed).isEqualTo(true);
|
||||
assertThat(NonPrivilegedBean.destroyed).isTrue();
|
||||
return null;
|
||||
}
|
||||
}, provider.getAccessControlContext());
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -100,17 +100,17 @@ public class FactoryMethodTests {
|
||||
|
||||
FactoryMethods fm = (FactoryMethods) xbf.getBean("fullWithNull");
|
||||
assertThat(fm.getNum()).isEqualTo(27);
|
||||
assertThat(fm.getName()).isEqualTo(null);
|
||||
assertThat(fm.getName()).isNull();
|
||||
assertThat(fm.getTestBean().getName()).isEqualTo("Juergen");
|
||||
|
||||
fm = (FactoryMethods) xbf.getBean("fullWithGenericNull");
|
||||
assertThat(fm.getNum()).isEqualTo(27);
|
||||
assertThat(fm.getName()).isEqualTo(null);
|
||||
assertThat(fm.getName()).isNull();
|
||||
assertThat(fm.getTestBean().getName()).isEqualTo("Juergen");
|
||||
|
||||
fm = (FactoryMethods) xbf.getBean("fullWithNamedNull");
|
||||
assertThat(fm.getNum()).isEqualTo(27);
|
||||
assertThat(fm.getName()).isEqualTo(null);
|
||||
assertThat(fm.getName()).isNull();
|
||||
assertThat(fm.getTestBean().getName()).isEqualTo("Juergen");
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -342,7 +342,7 @@ public class UtilNamespaceHandlerTests {
|
||||
public void testLoadProperties() {
|
||||
Properties props = (Properties) this.beanFactory.getBean("myProperties");
|
||||
assertThat(props.get("foo")).as("Incorrect property value").isEqualTo("bar");
|
||||
assertThat(props.get("foo2")).as("Incorrect property value").isEqualTo(null);
|
||||
assertThat(props.get("foo2")).as("Incorrect property value").isNull();
|
||||
Properties props2 = (Properties) this.beanFactory.getBean("myProperties");
|
||||
assertThat(props == props2).isTrue();
|
||||
}
|
||||
@@ -351,17 +351,17 @@ public class UtilNamespaceHandlerTests {
|
||||
public void testScopedProperties() {
|
||||
Properties props = (Properties) this.beanFactory.getBean("myScopedProperties");
|
||||
assertThat(props.get("foo")).as("Incorrect property value").isEqualTo("bar");
|
||||
assertThat(props.get("foo2")).as("Incorrect property value").isEqualTo(null);
|
||||
assertThat(props.get("foo2")).as("Incorrect property value").isNull();
|
||||
Properties props2 = (Properties) this.beanFactory.getBean("myScopedProperties");
|
||||
assertThat(props.get("foo")).as("Incorrect property value").isEqualTo("bar");
|
||||
assertThat(props.get("foo2")).as("Incorrect property value").isEqualTo(null);
|
||||
assertThat(props.get("foo2")).as("Incorrect property value").isNull();
|
||||
assertThat(props != props2).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalProperties() {
|
||||
Properties props = (Properties) this.beanFactory.getBean("myLocalProperties");
|
||||
assertThat(props.get("foo")).as("Incorrect property value").isEqualTo(null);
|
||||
assertThat(props.get("foo")).as("Incorrect property value").isNull();
|
||||
assertThat(props.get("foo2")).as("Incorrect property value").isEqualTo("bar2");
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -283,7 +283,7 @@ public class XmlBeanCollectionTests {
|
||||
Iterator it = hasMap.getSet().iterator();
|
||||
assertThat(it.next()).isEqualTo("bar");
|
||||
assertThat(it.next()).isEqualTo(jenny);
|
||||
assertThat(it.next()).isEqualTo(null);
|
||||
assertThat(it.next()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -181,7 +181,7 @@ public class XmlListableBeanFactoryTests extends AbstractListableBeanFactoryTest
|
||||
assertThat(beanNames.contains("aliasWithoutId3")).isFalse();
|
||||
|
||||
TestBean tb4 = (TestBean) getBeanFactory().getBean(TestBean.class.getName() + "#0");
|
||||
assertThat(tb4.getName()).isEqualTo(null);
|
||||
assertThat(tb4.getName()).isNull();
|
||||
|
||||
Map drs = getListableBeanFactory().getBeansOfType(DummyReferencer.class, false, false);
|
||||
assertThat(drs.size()).isEqualTo(5);
|
||||
|
||||
+5
-1
@@ -16,9 +16,11 @@
|
||||
|
||||
package org.springframework.beans.factory
|
||||
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.reflect.full.createInstance
|
||||
|
||||
/**
|
||||
* Mock object based tests for ListableBeanFactory Kotlin extensions
|
||||
@@ -77,10 +79,12 @@ class ListableBeanFactoryExtensionsTests {
|
||||
verify { lbf.getBeansWithAnnotation(Bar::class.java) }
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_VARIABLE")
|
||||
@Test
|
||||
fun `findAnnotationOnBean with String and reified type parameters`() {
|
||||
val name = "bar"
|
||||
lbf.findAnnotationOnBean<Bar>(name)
|
||||
every { lbf.findAnnotationOnBean(name, Bar::class.java) } returns Bar::class.createInstance()
|
||||
val annotation: Bar? = lbf.findAnnotationOnBean(name)
|
||||
verify { lbf.findAnnotationOnBean(name, Bar::class.java) }
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -40,8 +40,9 @@ public class MustBeInitialized implements InitializingBean {
|
||||
* managed the bean's lifecycle correctly
|
||||
*/
|
||||
public void businessMethod() {
|
||||
if (!this.inited)
|
||||
if (!this.inited) {
|
||||
throw new RuntimeException("Factory didn't call afterPropertiesSet() on MustBeInitialized object");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-3
@@ -39,12 +39,18 @@ public class Pet {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Pet pet = (Pet) o;
|
||||
|
||||
if (name != null ? !name.equals(pet.name) : pet.name != null) return false;
|
||||
if (name != null ? !name.equals(pet.name) : pet.name != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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,6 +22,7 @@ import javax.lang.model.element.Element;
|
||||
|
||||
/**
|
||||
* Provide the list of stereotypes that match an {@link Element}.
|
||||
*
|
||||
* <p>If an element has one or more stereotypes, it is referenced in the index
|
||||
* of candidate components and each stereotype can be queried individually.
|
||||
*
|
||||
|
||||
+9
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,6 @@ import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.cache.annotation.AbstractCachingConfiguration;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.interceptor.CacheResolver;
|
||||
import org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource;
|
||||
import org.springframework.cache.jcache.interceptor.JCacheOperationSource;
|
||||
@@ -46,11 +45,14 @@ public abstract class AbstractJCacheConfiguration extends AbstractCachingConfigu
|
||||
|
||||
|
||||
@Override
|
||||
protected void useCachingConfigurer(CachingConfigurer config) {
|
||||
super.useCachingConfigurer(config);
|
||||
if (config instanceof JCacheConfigurer) {
|
||||
this.exceptionCacheResolver = ((JCacheConfigurer) config)::exceptionCacheResolver;
|
||||
}
|
||||
protected void useCachingConfigurer(CachingConfigurerSupplier cachingConfigurerSupplier) {
|
||||
super.useCachingConfigurer(cachingConfigurerSupplier);
|
||||
this.exceptionCacheResolver = cachingConfigurerSupplier.adapt(config -> {
|
||||
if (config instanceof JCacheConfigurer) {
|
||||
return ((JCacheConfigurer) config).exceptionCacheResolver();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Bean(name = "jCacheOperationSource")
|
||||
|
||||
Vendored
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,8 +26,7 @@ import org.springframework.lang.Nullable;
|
||||
* <p>To be implemented by classes annotated with
|
||||
* {@link org.springframework.cache.annotation.EnableCaching} that wish
|
||||
* or need to specify explicitly how exception caches are resolved for
|
||||
* annotation-driven cache management. Consider extending {@link JCacheConfigurerSupport},
|
||||
* which provides a stub implementation of all interface methods.
|
||||
* annotation-driven cache management.
|
||||
*
|
||||
* <p>See {@link org.springframework.cache.annotation.EnableCaching} for
|
||||
* general examples and context; see {@link #exceptionCacheResolver()} for
|
||||
@@ -36,7 +35,6 @@ import org.springframework.lang.Nullable;
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.1
|
||||
* @see CachingConfigurer
|
||||
* @see JCacheConfigurerSupport
|
||||
* @see org.springframework.cache.annotation.EnableCaching
|
||||
*/
|
||||
public interface JCacheConfigurer extends CachingConfigurer {
|
||||
@@ -60,6 +58,8 @@ public interface JCacheConfigurer extends CachingConfigurer {
|
||||
* See {@link org.springframework.cache.annotation.EnableCaching} for more complete examples.
|
||||
*/
|
||||
@Nullable
|
||||
CacheResolver exceptionCacheResolver();
|
||||
default CacheResolver exceptionCacheResolver() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -79,7 +79,7 @@ public abstract class AbstractFallbackJCacheOperationSource implements JCacheOpe
|
||||
|
||||
@Nullable
|
||||
private JCacheOperation<?> computeCacheOperation(Method method, @Nullable Class<?> targetClass) {
|
||||
// Don't allow no-public methods as required.
|
||||
// Don't allow non-public methods, as configured.
|
||||
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user