mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
361 Commits
main
...
v4.3.5.RELEASE
| Author | SHA1 | Date | |
|---|---|---|---|
| d3fa0733d5 | |||
| e2d6e709c3 | |||
| bd7fee5a77 | |||
| 709d4ba6e7 | |||
| 8d55c7d60a | |||
| 9cb4de8b5e | |||
| 8662c61a17 | |||
| 935671ae32 | |||
| a5ce965d22 | |||
| 1e58c80fe7 | |||
| a92ae4ba30 | |||
| b5f2e56e38 | |||
| 594f4d56b8 | |||
| 2d83ca61e7 | |||
| 307e37a69f | |||
| 8310eb3b1f | |||
| b9c4f1fa95 | |||
| faab4f9e28 | |||
| 271b0abc45 | |||
| f0c3d50408 | |||
| f0fdff1f07 | |||
| d15df3489e | |||
| f3cc4ab09d | |||
| 442d8a68a6 | |||
| 934fffec68 | |||
| 8190e7838f | |||
| 4571975414 | |||
| 5115c61b03 | |||
| 54c7a9ee95 | |||
| 0296c7c5b6 | |||
| 84d8135cbb | |||
| dd3c370bca | |||
| 4e41f74925 | |||
| c6663f59b8 | |||
| ced7503d95 | |||
| 04af30daed | |||
| 5ccc8e341c | |||
| 71977e8f9d | |||
| 5e774e0b44 | |||
| e16d753439 | |||
| b14d189db9 | |||
| 14de29c031 | |||
| b59455b63c | |||
| 1a6dc86fed | |||
| 35b0c8b577 | |||
| 75034c3710 | |||
| 305cea28c5 | |||
| 69ba85b051 | |||
| 5700d65a53 | |||
| e707c40e0b | |||
| 9d37472f23 | |||
| eb97335c6f | |||
| 0028b29760 | |||
| 1ded1e38e8 | |||
| 149acdae7d | |||
| 5fee5f39ea | |||
| f16d453805 | |||
| 2b0293578f | |||
| 66aeeedaef | |||
| af41dd1ed6 | |||
| 17f7f1fc15 | |||
| cbc512f3be | |||
| 7ac9f92bc2 | |||
| a7ba63d425 | |||
| 5ca10b1d67 | |||
| f22a4a4e80 | |||
| b53ee13662 | |||
| 8de100b116 | |||
| ac30bcb0eb | |||
| 872d6ef55a | |||
| dd3b9c7c35 | |||
| 9755ae3cbe | |||
| bc29fb5a09 | |||
| 646a574b9c | |||
| 8f19650fd7 | |||
| f08980967b | |||
| 5285f5300a | |||
| 1608d0596d | |||
| 62631bfe33 | |||
| 7ffed858f0 | |||
| 3a1334e0d4 | |||
| 37f4f43726 | |||
| db1a84ede1 | |||
| 3d2e4c338c | |||
| b42d731fc8 | |||
| fd7045adac | |||
| e26d3505f7 | |||
| fe0249bf8f | |||
| 2ac682e125 | |||
| 9be1710dca | |||
| 7e7504f5ea | |||
| e83c11667f | |||
| 05547979de | |||
| 9e67ba83a5 | |||
| 2bb3522bbb | |||
| 8f4ec35697 | |||
| 17863dfbda | |||
| 56bb20d489 | |||
| 5baf32cd81 | |||
| 38cd1ecff4 | |||
| 77e00f1926 | |||
| ade139f2d0 | |||
| 653f35a3d8 | |||
| baa7aecf60 | |||
| d859826be6 | |||
| d759c96a98 | |||
| 7cbab0efe3 | |||
| b6b536682e | |||
| edf1df33cc | |||
| bf0df54136 | |||
| 7e80d2de79 | |||
| 144f687ee9 | |||
| 0ee8322947 | |||
| 997fb5fb48 | |||
| 2b459881bd | |||
| e18e7eca47 | |||
| 1c80d2ac2f | |||
| 62918ca779 | |||
| 3cca57a801 | |||
| 5578a2e46d | |||
| fe19cfde28 | |||
| fbad637235 | |||
| 01e9307fb7 | |||
| 5697cb6c95 | |||
| 05ff83f95a | |||
| 1e3012cb49 | |||
| 45b8cf350e | |||
| 2c2c6f8e02 | |||
| 4e3a6b9404 | |||
| 76bbccb4dc | |||
| 1c4433555a | |||
| faaced1d86 | |||
| 1a1d17e13a | |||
| 4254b6d0e2 | |||
| a211c2a955 | |||
| 196200bcc0 | |||
| c062835702 | |||
| 664ef756c2 | |||
| 9de28d640e | |||
| adb9dc7ede | |||
| f9fcd24315 | |||
| 6d95b999ad | |||
| 6731e52280 | |||
| 970358b2af | |||
| 3d68950037 | |||
| d50b2a4804 | |||
| 29a946163b | |||
| 9472025da7 | |||
| f5cd5387da | |||
| 7a8bf8e9a5 | |||
| f5ecdda400 | |||
| c2031aa651 | |||
| 8751c9931e | |||
| adbf9922f4 | |||
| b3a1e5f9e9 | |||
| 22f70f9ac9 | |||
| d2079f32d8 | |||
| f2ac416f66 | |||
| 642fbfba9f | |||
| c98cdd4f4c | |||
| d04567b99c | |||
| f2e1e1b890 | |||
| 6c764f6b8a | |||
| 49929f1e56 | |||
| acdf139137 | |||
| 3346c594e4 | |||
| 0bb2cfe440 | |||
| 11573b4ea4 | |||
| 5934959b62 | |||
| 81f6c22e51 | |||
| 78a8245f4a | |||
| 049861afb4 | |||
| 3df7083f69 | |||
| ca17edd5ac | |||
| c26bf871b7 | |||
| 15d3e8c3e1 | |||
| 66b370e103 | |||
| 2bbfbb1d50 | |||
| ace25d4987 | |||
| 59cb9a4e60 | |||
| 0dce570157 | |||
| 7ddaf49eb2 | |||
| e947363a11 | |||
| 5dbfe48d24 | |||
| 07d5f8b123 | |||
| be99603f1b | |||
| 54db496815 | |||
| fbe7ddb640 | |||
| 55c37d2a57 | |||
| 4b445531f5 | |||
| 12afc263a4 | |||
| 040d131284 | |||
| 73bbe0849a | |||
| 09a0615df0 | |||
| 669d5815c9 | |||
| bd24b97bd3 | |||
| db196ce5d8 | |||
| 4396b211ce | |||
| 367949e914 | |||
| ae2bbe7f19 | |||
| 819e14f91b | |||
| fcf3ccba98 | |||
| 558a10b54f | |||
| 43c60a02f7 | |||
| 6501bc5d32 | |||
| f3dae0c9ad | |||
| dc2cafc888 | |||
| 49fc4923be | |||
| efb5f17a60 | |||
| 086e764845 | |||
| c30290b43c | |||
| d26421fe3b | |||
| 37670924f6 | |||
| ee5143b54b | |||
| acbb2544bf | |||
| d8f7347000 | |||
| 3b91dec462 | |||
| 05f74b4218 | |||
| 8e98177fb3 | |||
| 815a3ad0de | |||
| 5075dd4dfa | |||
| ca09dcbe89 | |||
| 198a74d793 | |||
| fe404628e9 | |||
| 5a004c3b2a | |||
| 430180aa96 | |||
| e828be96f0 | |||
| 52447efb97 | |||
| d09b0fe83a | |||
| 798d8668a4 | |||
| 2a82b8fed9 | |||
| 696f687419 | |||
| 9b91b9db8c | |||
| 026473280b | |||
| a7849b2861 | |||
| 74bf659c56 | |||
| c2feedb7a2 | |||
| 0735e9ba98 | |||
| ab686732d0 | |||
| 6d86437369 | |||
| 184285ab27 | |||
| 1e8065d040 | |||
| f735d12247 | |||
| 7135bc2dc2 | |||
| 9044706796 | |||
| 5f68da3153 | |||
| 5222489a01 | |||
| 27f830f345 | |||
| 8d7db8e450 | |||
| da56758054 | |||
| 66dcc4b6db | |||
| 6eab5622c7 | |||
| af53f3d6cf | |||
| 188e5327ee | |||
| 1932a9d729 | |||
| c926ec477a | |||
| 7b11fa18a1 | |||
| e6cefdca25 | |||
| fbeff475b3 | |||
| d057099c17 | |||
| 411700d7e6 | |||
| b4e9d918f2 | |||
| 2756c364d2 | |||
| 43faabd4cc | |||
| a4a71a8904 | |||
| e23ac031ff | |||
| 79a56967a1 | |||
| 0bc0453700 | |||
| 35e247aa26 | |||
| 67ba187b6f | |||
| 67f0b1986c | |||
| 60e0177d00 | |||
| 4543a28e51 | |||
| aade2d1ec9 | |||
| 4627545a3b | |||
| e2ba7c9b8c | |||
| 6f5596ac5c | |||
| 7d1c2f191a | |||
| 4ada571384 | |||
| ad8ebbaa05 | |||
| 4854989db4 | |||
| 7c5050cf80 | |||
| 14ae8be547 | |||
| ff878ea9dc | |||
| 7021a4be44 | |||
| 5c4737c3d0 | |||
| fbf3807af1 | |||
| 703c37ec88 | |||
| 96440878bb | |||
| b5c11ffb1c | |||
| 7f5b323d50 | |||
| 67176e2b75 | |||
| 79f3cf3263 | |||
| 9ee1dc79fd | |||
| 9e2c34dfa6 | |||
| cc93c2a559 | |||
| 15c7044c4d | |||
| 0ef80d3579 | |||
| 95c2e0a996 | |||
| da3e8611e1 | |||
| 64595597f3 | |||
| 82f2983cd4 | |||
| 9451177c35 | |||
| 9ed087d5da | |||
| 77f22e9674 | |||
| 8ccfdbbcf9 | |||
| 5a92aa4e06 | |||
| 7b1010cf61 | |||
| 45b2f5bac4 | |||
| 36e1c82ef5 | |||
| 503d65d570 | |||
| fe17f8da41 | |||
| b583aa1579 | |||
| e0d81b97bb | |||
| 90752f9d87 | |||
| 3663aa675a | |||
| 1ca4b81856 | |||
| 4e7e06f549 | |||
| b2f0bdb0f4 | |||
| d98bd34200 | |||
| 940bdd878e | |||
| df556333a8 | |||
| 116f05eda6 | |||
| b187bbeca3 | |||
| 479a83b628 | |||
| 1c18100143 | |||
| 5d3c0f33f6 | |||
| afe106e254 | |||
| 69dd40ec89 | |||
| dee50d5e28 | |||
| 9e93403857 | |||
| 12bff6b3a0 | |||
| 70e666b4a3 | |||
| 29f980ec72 | |||
| 1d39d762f0 | |||
| 4d6d5e0ddd | |||
| 4ea5f070a4 | |||
| da59b4da9b | |||
| 0065a160cc | |||
| 52f46c7fea | |||
| f0a826ec0c | |||
| 5c3c0f73c1 | |||
| be0b71ce31 | |||
| f85d48dd31 | |||
| a1b58ee601 | |||
| e30429051d | |||
| 942ead75e2 | |||
| 453688f6df | |||
| 7d7a161102 | |||
| aaa223ae66 | |||
| d11c624fb0 | |||
| 275e51b19d | |||
| ab62edeeaa | |||
| 813108a928 | |||
| 3c14911401 | |||
| 4337f14627 | |||
| 92d78c10a2 | |||
| 16d5ba9b3a | |||
| 52065a736b | |||
| 11cb109114 | |||
| d7eadd41d6 |
+4
-5
@@ -88,15 +88,14 @@ present in the framework.
|
||||
1. Preserve existing formatting; i.e. do not reformat code for its own sake
|
||||
1. Search the codebase using `git grep` and other tools to discover common
|
||||
naming conventions, etc.
|
||||
1. Latin-1 (ISO-8859-1) encoding for Java sources; use `native2ascii` to convert
|
||||
if necessary
|
||||
1. UTF-8 encoding for Java sources
|
||||
|
||||
|
||||
### Add Apache license header to all new classes
|
||||
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -124,11 +123,11 @@ modified a file in 2015 whose header still reads:
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
```
|
||||
|
||||
Then be sure to update it to 2015 accordingly:
|
||||
Then be sure to update it to 2016 accordingly:
|
||||
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
```
|
||||
|
||||
### Use @since tags for newly-added public API types and methods
|
||||
|
||||
+46
-51
@@ -32,51 +32,52 @@ configure(allprojects) { project ->
|
||||
version = qualifyVersionIfNecessary(version)
|
||||
|
||||
ext.aspectjVersion = "1.8.9"
|
||||
ext.caffeineVersion = "2.3.1"
|
||||
ext.caffeineVersion = "2.3.5"
|
||||
ext.eclipselinkVersion = "2.4.2"
|
||||
ext.ehcacheVersion = "2.10.2"
|
||||
ext.ehcacheVersion = "2.10.3"
|
||||
ext.ehcachejcacheVersion = "1.0.1"
|
||||
ext.ehcache3Version = "3.1.0"
|
||||
ext.ehcache3Version = "3.1.3"
|
||||
ext.ejbVersion = "3.0"
|
||||
ext.fileuploadVersion = "1.3.2"
|
||||
ext.freemarkerVersion = "2.3.23"
|
||||
ext.groovyVersion = "2.4.7"
|
||||
ext.gsonVersion = "2.7"
|
||||
ext.guavaVersion = "19.0"
|
||||
ext.gsonVersion = "2.8.0"
|
||||
ext.guavaVersion = "20.0"
|
||||
ext.hamcrestVersion = "1.3"
|
||||
ext.hibernate3Version = "3.6.10.Final"
|
||||
ext.hibernate4Version = "4.3.11.Final"
|
||||
ext.hibernate5Version = "5.2.1.Final"
|
||||
ext.hibernate5Version = "5.2.6.Final"
|
||||
ext.hibval4Version = "4.3.2.Final"
|
||||
ext.hibval5Version = "5.2.4.Final"
|
||||
ext.hsqldbVersion = "2.3.4"
|
||||
ext.httpasyncVersion = "4.1.2"
|
||||
ext.httpclientVersion = "4.5.2"
|
||||
ext.jackson2Version = "2.8.0.rc2"
|
||||
ext.jackson2Version = "2.8.5"
|
||||
ext.jasperreportsVersion = "6.2.1" // our tests fail with JR-internal NPEs against 6.2.2 and higher
|
||||
ext.javamailVersion = "1.5.5"
|
||||
ext.jettyVersion = "9.3.10.v20160621"
|
||||
ext.jodaVersion = "2.9.4"
|
||||
ext.jrubyVersion = "1.7.25" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory)
|
||||
ext.javamailVersion = "1.5.6"
|
||||
ext.jettyVersion = "9.3.14.v20161028"
|
||||
ext.jetty94Version = "9.4.0.v20161208" // for spring-websocket support
|
||||
ext.jodaVersion = "2.9.6"
|
||||
ext.jrubyVersion = "1.7.26" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory)
|
||||
ext.jtaVersion = "1.2"
|
||||
ext.junitVersion = "4.12"
|
||||
ext.log4jVersion = "1.2.17"
|
||||
ext.nettyVersion = "4.1.1.Final"
|
||||
ext.nettyVersion = "4.1.6.Final"
|
||||
ext.okhttpVersion = "2.7.5"
|
||||
ext.okhttp3Version = "3.3.1"
|
||||
ext.okhttp3Version = "3.5.0"
|
||||
ext.openjpaVersion = "2.4.1"
|
||||
ext.poiVersion = "3.14"
|
||||
ext.reactorVersion = "2.0.8.RELEASE"
|
||||
ext.romeVersion = "1.6.0"
|
||||
ext.romeVersion = "1.7.0"
|
||||
ext.slf4jVersion = "1.7.21"
|
||||
ext.snakeyamlVersion = "1.17"
|
||||
ext.snifferVersion = "1.15"
|
||||
ext.testngVersion = "6.9.10"
|
||||
ext.tiles2Version = "2.2.2"
|
||||
ext.tiles3Version = "3.0.5"
|
||||
ext.tomcatVersion = "8.5.3"
|
||||
ext.tiles3Version = "3.0.7"
|
||||
ext.tomcatVersion = "8.5.9"
|
||||
ext.tyrusVersion = "1.3.5" // constrained by WebLogic 12.1.3 support
|
||||
ext.undertowVersion = "1.4.0.CR2"
|
||||
ext.undertowVersion = "1.3.25.Final"
|
||||
ext.xmlunitVersion = "1.6"
|
||||
ext.xstreamVersion = "1.4.9"
|
||||
|
||||
@@ -110,11 +111,13 @@ configure(allprojects) { project ->
|
||||
compileJava {
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
compileTestJava {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
options.encoding = 'UTF-8'
|
||||
options.compilerArgs += "-parameters"
|
||||
}
|
||||
|
||||
@@ -199,10 +202,10 @@ configure(allprojects) { project ->
|
||||
"http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
|
||||
"http://ehcache.org/apidocs/${ehcacheVersion}",
|
||||
"http://ehcache.org/apidocs/${ehcache3Version}",
|
||||
"http://quartz-scheduler.org/api/2.2.0/",
|
||||
"http://fasterxml.github.io/jackson-core/javadoc/2.7/",
|
||||
"http://fasterxml.github.io/jackson-databind/javadoc/2.7/",
|
||||
"http://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.7/",
|
||||
"http://quartz-scheduler.org/api/2.2.1/",
|
||||
"http://fasterxml.github.io/jackson-core/javadoc/2.8/",
|
||||
"http://fasterxml.github.io/jackson-databind/javadoc/2.8/",
|
||||
"http://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.8/",
|
||||
"http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/"
|
||||
] as String[]
|
||||
}
|
||||
@@ -351,11 +354,11 @@ project("spring-core") {
|
||||
compile("commons-logging:commons-logging:1.2")
|
||||
optional("commons-codec:commons-codec:1.10")
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("net.sf.jopt-simple:jopt-simple:5.0.2")
|
||||
optional("net.sf.jopt-simple:jopt-simple:5.0.3")
|
||||
optional("log4j:log4j:${log4jVersion}")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
|
||||
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
|
||||
testCompile("com.fasterxml.woodstox:woodstox-core:5.0.2") {
|
||||
testCompile("com.fasterxml.woodstox:woodstox-core:5.0.3") {
|
||||
exclude group: "stax", module: "stax-api"
|
||||
}
|
||||
}
|
||||
@@ -477,7 +480,7 @@ project("spring-context") {
|
||||
optional("javax.inject:javax.inject:1")
|
||||
optional("javax.ejb:ejb-api:${ejbVersion}")
|
||||
optional("javax.enterprise.concurrent:javax.enterprise.concurrent-api:1.0")
|
||||
optional("javax.money:money-api:1.0")
|
||||
optional("javax.money:money-api:1.0.1")
|
||||
optional("org.eclipse.persistence:javax.persistence:2.0.0")
|
||||
optional("javax.validation:validation-api:1.0.0.GA")
|
||||
optional("org.hibernate:hibernate-validator:${hibval4Version}")
|
||||
@@ -556,13 +559,6 @@ project("spring-oxm") {
|
||||
description = "Spring Object/XML Marshalling"
|
||||
apply from: "oxm.gradle"
|
||||
|
||||
compileTestJava {
|
||||
// necessary to avoid java.lang.VerifyError on jibx compilation
|
||||
// see http://jira.codehaus.org/browse/JIBX-465
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-core"))
|
||||
@@ -581,14 +577,12 @@ project("spring-oxm") {
|
||||
testCompile(project(":spring-context"))
|
||||
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
|
||||
testCompile("xpp3:xpp3:1.1.4c")
|
||||
testCompile("org.codehaus.jettison:jettison:1.3.7") {
|
||||
testCompile("org.codehaus.jettison:jettison:1.3.8") {
|
||||
exclude group: 'stax', module: 'stax-api'
|
||||
}
|
||||
if (compileTestJava.enabled) {
|
||||
testCompile(files(genCastor.classesDir).builtBy(genCastor))
|
||||
testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
|
||||
testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans))
|
||||
}
|
||||
testCompile(files(genCastor.classesDir).builtBy(genCastor))
|
||||
testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
|
||||
testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -621,9 +615,9 @@ project("spring-jdbc") {
|
||||
optional("javax.transaction:javax.transaction-api:${jtaVersion}")
|
||||
optional("com.mchange:c3p0:0.9.5.2")
|
||||
optional("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
optional("com.h2database:h2:1.4.192")
|
||||
optional("org.apache.derby:derby:10.12.1.1")
|
||||
optional("org.apache.derby:derbyclient:10.12.1.1")
|
||||
optional("com.h2database:h2:1.4.193")
|
||||
optional("org.apache.derby:derby:10.13.1.1")
|
||||
optional("org.apache.derby:derbyclient:10.13.1.1")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -727,6 +721,7 @@ project("spring-web") {
|
||||
testCompile("com.fasterxml.jackson.datatype:jackson-datatype-joda:${jackson2Version}")
|
||||
testCompile("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:${jackson2Version}")
|
||||
testCompile("com.fasterxml.jackson.module:jackson-module-kotlin:${jackson2Version}")
|
||||
testCompile("com.squareup.okhttp3:mockwebserver:${okhttp3Version}")
|
||||
testRuntime("com.sun.mail:javax.mail:${javamailVersion}")
|
||||
}
|
||||
}
|
||||
@@ -879,10 +874,10 @@ project("spring-webmvc") {
|
||||
testCompile("commons-io:commons-io:1.3")
|
||||
testCompile("joda-time:joda-time:${jodaVersion}")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
testCompile("org.jruby:jruby:${jrubyVersion}")
|
||||
testCompile("org.python:jython-standalone:2.5.3")
|
||||
testCompile("org.mozilla:rhino:1.7.7.1")
|
||||
testCompile("org.webjars:underscorejs:1.8.3")
|
||||
testRuntime("org.jruby:jruby:${jrubyVersion}")
|
||||
testRuntime("org.python:jython-standalone:2.5.3")
|
||||
testRuntime("org.webjars:underscorejs:1.8.3")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -955,11 +950,11 @@ project("spring-websocket") {
|
||||
optional("org.eclipse.jetty:jetty-webapp:${jettyVersion}") {
|
||||
exclude group: "javax.servlet", module: "javax.servlet"
|
||||
}
|
||||
optional("org.eclipse.jetty.websocket:websocket-server:${jettyVersion}") {
|
||||
optional("org.eclipse.jetty.websocket:websocket-server:${jetty94Version}") {
|
||||
exclude group: "javax.servlet", module: "javax.servlet"
|
||||
}
|
||||
optional("org.eclipse.jetty.websocket:websocket-client:${jettyVersion}")
|
||||
optional("org.eclipse.jetty:jetty-client:${jettyVersion}")
|
||||
optional("org.eclipse.jetty.websocket:websocket-client:${jetty94Version}")
|
||||
optional("org.eclipse.jetty:jetty-client:${jetty94Version}")
|
||||
optional("io.undertow:undertow-core:${undertowVersion}")
|
||||
optional("io.undertow:undertow-servlet:${undertowVersion}") {
|
||||
exclude group: "org.jboss.spec.javax.servlet", module: "jboss-servlet-api_3.1_spec"
|
||||
@@ -1008,10 +1003,10 @@ project("spring-test") {
|
||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||
optional("org.hamcrest:hamcrest-core:${hamcrestVersion}")
|
||||
optional("xmlunit:xmlunit:${xmlunitVersion}")
|
||||
optional("net.sourceforge.htmlunit:htmlunit:2.22")
|
||||
optional("org.seleniumhq.selenium:htmlunit-driver:2.21")
|
||||
optional("net.sourceforge.htmlunit:htmlunit:2.23")
|
||||
optional("org.seleniumhq.selenium:htmlunit-driver:2.23.2")
|
||||
optional("org.seleniumhq.selenium:selenium-java:2.53.1")
|
||||
optional("org.skyscreamer:jsonassert:1.3.0")
|
||||
optional("org.skyscreamer:jsonassert:1.4.0")
|
||||
optional("com.jayway.jsonpath:json-path:2.2.0")
|
||||
testCompile(project(":spring-context-support"))
|
||||
testCompile(project(":spring-oxm"))
|
||||
@@ -1036,7 +1031,7 @@ project("spring-test") {
|
||||
testCompile("javax.cache:cache-api:1.0.0")
|
||||
testRuntime("log4j:log4j:${log4jVersion}")
|
||||
testRuntime("org.ehcache:ehcache:${ehcache3Version}")
|
||||
testRuntime("org.terracotta:management-model:2.0.0")
|
||||
testRuntime("org.terracotta:management-model:2.3.0")
|
||||
}
|
||||
|
||||
task testNG(type: Test) {
|
||||
@@ -1367,7 +1362,7 @@ configure(rootProject) {
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
description = "Generates gradlew[.bat] scripts"
|
||||
gradleVersion = "2.13"
|
||||
gradleVersion = "2.14.1"
|
||||
|
||||
doLast() {
|
||||
def gradleOpts = "-XX:MaxMetaspaceSize=1024m -Xmx1024m"
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=4.3.1.BUILD-SNAPSHOT
|
||||
version=4.3.5.RELEASE
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+2
-2
@@ -1,6 +1,6 @@
|
||||
#Wed Jun 15 12:59:30 CEST 2016
|
||||
#Wed Aug 17 21:21:18 CEST 2016
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip
|
||||
|
||||
@@ -46,7 +46,7 @@ public interface MethodInterceptor extends Interceptor {
|
||||
* after the invocation. Polite implementations would certainly
|
||||
* like to invoke {@link Joinpoint#proceed()}.
|
||||
* @param invocation the method invocation joinpoint
|
||||
* @return the result of the call to {@link Joinpoint#proceed();
|
||||
* @return the result of the call to {@link Joinpoint#proceed()};
|
||||
* might be intercepted by the interceptor
|
||||
* @throws Throwable if the interceptors or the target object
|
||||
* throws an exception
|
||||
|
||||
+30
-25
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,7 +28,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.aspectj.weaver.BCException;
|
||||
import org.aspectj.weaver.patterns.NamePattern;
|
||||
import org.aspectj.weaver.reflect.ReflectionWorld.ReflectionWorldException;
|
||||
import org.aspectj.weaver.reflect.ShadowMatchImpl;
|
||||
@@ -258,7 +257,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (BCException ex) {
|
||||
catch (Throwable ex) {
|
||||
logger.debug("PointcutExpression matching rejected target class", ex);
|
||||
}
|
||||
return false;
|
||||
@@ -326,7 +325,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
// No current invocation...
|
||||
// TODO: Should we really proceed here?
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not access current invocation - matching with limited context: " + ex);
|
||||
}
|
||||
@@ -413,39 +411,46 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
shadowMatch = this.shadowMatchCache.get(targetMethod);
|
||||
if (shadowMatch == null) {
|
||||
try {
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
catch (ReflectionWorldException ex) {
|
||||
// Failed to introspect target method, probably because it has been loaded
|
||||
// in a special ClassLoader. Let's try the declaring ClassLoader instead...
|
||||
try {
|
||||
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
|
||||
if (fallbackExpression != null) {
|
||||
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
}
|
||||
catch (ReflectionWorldException ex2) {
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
if (shadowMatch == null && targetMethod != originalMethod) {
|
||||
methodToMatch = originalMethod;
|
||||
try {
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
catch (ReflectionWorldException ex3) {
|
||||
// Could neither introspect the target class nor the proxy class ->
|
||||
// let's try the original method's declaring class before we give up...
|
||||
catch (ReflectionWorldException ex) {
|
||||
// Failed to introspect target method, probably because it has been loaded
|
||||
// in a special ClassLoader. Let's try the declaring ClassLoader instead...
|
||||
try {
|
||||
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
|
||||
if (fallbackExpression != null) {
|
||||
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
}
|
||||
catch (ReflectionWorldException ex4) {
|
||||
catch (ReflectionWorldException ex2) {
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
if (shadowMatch == null && targetMethod != originalMethod) {
|
||||
methodToMatch = originalMethod;
|
||||
try {
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
catch (ReflectionWorldException ex3) {
|
||||
// Could neither introspect the target class nor the proxy class ->
|
||||
// let's try the original method's declaring class before we give up...
|
||||
try {
|
||||
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
|
||||
if (fallbackExpression != null) {
|
||||
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
}
|
||||
catch (ReflectionWorldException ex4) {
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// Possibly AspectJ 1.8.10 encountering an invalid signature
|
||||
logger.debug("PointcutExpression matching rejected target method", ex);
|
||||
fallbackExpression = null;
|
||||
}
|
||||
if (shadowMatch == null) {
|
||||
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -55,10 +55,12 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
return this.aspectClass.newInstance();
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new AopConfigException("Unable to instantiate aspect class [" + this.aspectClass.getName() + "]", ex);
|
||||
throw new AopConfigException(
|
||||
"Unable to instantiate aspect class: " + this.aspectClass.getName(), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new AopConfigException("Cannot access element class [" + this.aspectClass.getName() + "]", ex);
|
||||
throw new AopConfigException(
|
||||
"Could not access aspect constructor: " + this.aspectClass.getName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-2
@@ -97,8 +97,19 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
|
||||
|
||||
@Override
|
||||
public Object getAspectCreationMutex() {
|
||||
return (this.beanFactory instanceof ConfigurableBeanFactory ?
|
||||
((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex() : this);
|
||||
if (this.beanFactory != null) {
|
||||
if (this.beanFactory.isSingleton(name)) {
|
||||
// Rely on singleton semantics provided by the factory -> no local lock.
|
||||
return null;
|
||||
}
|
||||
else if (this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
// No singleton guarantees from the factory -> let's lock locally but
|
||||
// reuse the factory's singleton lock, just in case a lazy dependency
|
||||
// of our advice bean happens to trigger the singleton lock implicitly...
|
||||
return ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+9
-3
@@ -48,9 +48,15 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
|
||||
@Override
|
||||
public Object getAspectInstance() {
|
||||
if (this.materialized == null) {
|
||||
synchronized (this.maaif.getAspectCreationMutex()) {
|
||||
if (this.materialized == null) {
|
||||
this.materialized = this.maaif.getAspectInstance();
|
||||
Object mutex = this.maaif.getAspectCreationMutex();
|
||||
if (mutex == null) {
|
||||
this.materialized = this.maaif.getAspectInstance();
|
||||
}
|
||||
else {
|
||||
synchronized (mutex) {
|
||||
if (this.materialized == null) {
|
||||
this.materialized = this.maaif.getAspectInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactor
|
||||
|
||||
/**
|
||||
* Return the best possible creation mutex for this factory.
|
||||
* @return the mutex object (never {@code null})
|
||||
* @return the mutex object (may be {@code null} for no mutex to use)
|
||||
* @since 4.3
|
||||
*/
|
||||
Object getAspectCreationMutex();
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -71,7 +71,7 @@ public abstract class AbstractInterceptorDrivenBeanDefinitionDecorator implement
|
||||
BeanDefinition interceptorDefinition = createInterceptorDefinition(node);
|
||||
|
||||
// generate name and register the interceptor
|
||||
String interceptorName = existingBeanName + "." + getInterceptorNameSuffix(interceptorDefinition);
|
||||
String interceptorName = existingBeanName + '.' + getInterceptorNameSuffix(interceptorDefinition);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(
|
||||
new BeanDefinitionHolder(interceptorDefinition, interceptorName), registry);
|
||||
|
||||
|
||||
@@ -351,7 +351,8 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
*/
|
||||
private static Object processReturnType(Object proxy, Object target, Method method, Object retVal) {
|
||||
// Massage return value if necessary
|
||||
if (retVal != null && retVal == target && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
|
||||
if (retVal != null && retVal == target &&
|
||||
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
|
||||
// Special case: it returned "this". Note that we can't help
|
||||
// if the target sets a reference to itself in another returned object.
|
||||
retVal = proxy;
|
||||
|
||||
@@ -215,7 +215,8 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
|
||||
// Massage return value if necessary.
|
||||
Class<?> returnType = method.getReturnType();
|
||||
if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
|
||||
if (retVal != null && retVal == target &&
|
||||
returnType != Object.class && returnType.isInstance(proxy) &&
|
||||
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
|
||||
// Special case: it returned "this" and the return type of the method
|
||||
// is type-compatible. Note that we can't help if the target sets
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -139,7 +139,8 @@ public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanC
|
||||
* @return whether the given interface is an internal language interface
|
||||
*/
|
||||
protected boolean isInternalLanguageInterface(Class<?> ifc) {
|
||||
return ifc.getName().equals("groovy.lang.GroovyObject");
|
||||
return (ifc.getName().equals("groovy.lang.GroovyObject") ||
|
||||
ifc.getName().endsWith(".cglib.proxy.Factory"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -246,7 +246,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
*/
|
||||
@Override
|
||||
protected Object invokeUnderTrace(MethodInvocation invocation, Log logger) throws Throwable {
|
||||
String name = invocation.getMethod().getDeclaringClass().getName() + "." + invocation.getMethod().getName();
|
||||
String name = ClassUtils.getQualifiedMethodName(invocation.getMethod());
|
||||
StopWatch stopWatch = new StopWatch(name);
|
||||
Object returnValue = null;
|
||||
boolean exitThroughException = false;
|
||||
|
||||
+22
-6
@@ -46,7 +46,7 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private transient Advice advice;
|
||||
private transient volatile Advice advice;
|
||||
|
||||
private transient volatile Object adviceMonitor = new Object();
|
||||
|
||||
@@ -98,12 +98,28 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
|
||||
|
||||
@Override
|
||||
public Advice getAdvice() {
|
||||
synchronized (this.adviceMonitor) {
|
||||
if (this.advice == null && this.adviceBeanName != null) {
|
||||
Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
|
||||
this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
|
||||
Advice advice = this.advice;
|
||||
if (advice != null || this.adviceBeanName == null) {
|
||||
return advice;
|
||||
}
|
||||
|
||||
Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
|
||||
if (this.beanFactory.isSingleton(this.adviceBeanName)) {
|
||||
// Rely on singleton semantics provided by the factory.
|
||||
advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
|
||||
this.advice = advice;
|
||||
return advice;
|
||||
}
|
||||
else {
|
||||
// No singleton guarantees from the factory -> let's lock locally but
|
||||
// reuse the factory's singleton lock, just in case a lazy dependency
|
||||
// of our advice bean happens to trigger the singleton lock implicitly...
|
||||
synchronized (this.adviceMonitor) {
|
||||
if (this.advice == null) {
|
||||
this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
|
||||
}
|
||||
return this.advice;
|
||||
}
|
||||
return this.advice;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -129,8 +130,8 @@ public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPo
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
return ((targetClass != null && matchesPattern(targetClass.getName() + "." + method.getName())) ||
|
||||
matchesPattern(method.getDeclaringClass().getName() + "." + method.getName()));
|
||||
return ((targetClass != null && matchesPattern(ClassUtils.getQualifiedMethodName(method, targetClass))) ||
|
||||
matchesPattern(ClassUtils.getQualifiedMethodName(method)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,7 +39,7 @@ import org.springframework.aop.TargetSource;
|
||||
public abstract class AbstractRefreshableTargetSource implements TargetSource, Refreshable {
|
||||
|
||||
/** Logger available to subclasses */
|
||||
protected Log logger = LogFactory.getLog(getClass());
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected Object targetObject;
|
||||
|
||||
|
||||
+8
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.aop.scope;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
@@ -28,18 +30,21 @@ import static org.springframework.tests.TestResourceUtils.*;
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public final class ScopedProxyAutowireTests {
|
||||
public class ScopedProxyAutowireTests {
|
||||
|
||||
private static final Class<?> CLASS = ScopedProxyAutowireTests.class;
|
||||
|
||||
private static final Resource SCOPED_AUTOWIRE_TRUE_CONTEXT = qualifiedResource(CLASS, "scopedAutowireTrue.xml");
|
||||
private static final Resource SCOPED_AUTOWIRE_FALSE_CONTEXT = qualifiedResource(CLASS, "scopedAutowireFalse.xml");
|
||||
|
||||
|
||||
@Test
|
||||
public void testScopedProxyInheritsAutowireCandidateFalse() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(SCOPED_AUTOWIRE_FALSE_CONTEXT);
|
||||
assertTrue(Arrays.asList(bf.getBeanNamesForType(TestBean.class, false, false)).contains("scoped"));
|
||||
TestBean autowired = (TestBean) bf.getBean("autowired");
|
||||
TestBean unscoped = (TestBean) bf.getBean("unscoped");
|
||||
assertSame(unscoped, autowired.getChild());
|
||||
@@ -49,6 +54,7 @@ public final class ScopedProxyAutowireTests {
|
||||
public void testScopedProxyReplacesAutowireCandidateTrue() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(SCOPED_AUTOWIRE_TRUE_CONTEXT);
|
||||
assertTrue(Arrays.asList(bf.getBeanNamesForType(TestBean.class, false, false)).contains("scoped"));
|
||||
TestBean autowired = (TestBean) bf.getBean("autowired");
|
||||
TestBean scoped = (TestBean) bf.getBean("scoped");
|
||||
assertSame(scoped, autowired.getChild());
|
||||
|
||||
+10
-13
@@ -1,6 +1,5 @@
|
||||
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,27 +28,21 @@ public class NopInterceptor implements MethodInterceptor {
|
||||
|
||||
private int count;
|
||||
|
||||
/**
|
||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(MethodInvocation)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
increment();
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
protected void increment() {
|
||||
this.count++;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
protected void increment() {
|
||||
++count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
@@ -62,5 +55,9 @@ public class NopInterceptor implements MethodInterceptor {
|
||||
return this.count == ((NopInterceptor) other).count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return NopInterceptor.class.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,22 +28,10 @@ import org.springframework.util.ObjectUtils;
|
||||
@SuppressWarnings("serial")
|
||||
public class SerializablePerson implements Person, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
@Override
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@@ -55,6 +43,16 @@ public class SerializablePerson implements Person, Serializable {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object echo(Object o) throws Throwable {
|
||||
if (o instanceof Throwable) {
|
||||
@@ -63,10 +61,6 @@ public class SerializablePerson implements Person, Serializable {
|
||||
return o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
@@ -77,4 +71,9 @@ public class SerializablePerson implements Person, Serializable {
|
||||
return p.age == age && ObjectUtils.nullSafeEquals(name, p.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return SerializablePerson.class.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
@@ -36,7 +36,9 @@ import org.springframework.util.ObjectUtils;
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @author Sam Brannen
|
||||
* @deprecated as of Spring 4.3, in favor of a custom aspect for such purposes
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMethod()) {
|
||||
|
||||
private final Expectations expectations = new Expectations();
|
||||
|
||||
+2
@@ -59,7 +59,9 @@ import org.aspectj.lang.annotation.SuppressAjWarnings;
|
||||
* @author Ramnivas Laddad
|
||||
* @author Sam Brannen
|
||||
* @see MockStaticEntityMethods
|
||||
* @deprecated as of Spring 4.3, in favor of a custom aspect for such purposes
|
||||
*/
|
||||
@Deprecated
|
||||
@RequiredTypes("javax.persistence.Entity")
|
||||
public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodMockingControl {
|
||||
|
||||
|
||||
+2
@@ -29,7 +29,9 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Sam Brannen
|
||||
* @deprecated as of Spring 4.3, in favor of a custom aspect for such purposes
|
||||
*/
|
||||
@Deprecated
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface MockStaticEntityMethods {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -458,7 +458,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
private GroovyBeanDefinitionWrapper invokeBeanDefiningMethod(String beanName, Object[] args) {
|
||||
boolean hasClosureArgument = args[args.length - 1] instanceof Closure;
|
||||
if (args[0] instanceof Class) {
|
||||
Class<?> beanClass = (args[0] instanceof Class ? (Class) args[0] : args[0].getClass());
|
||||
Class<?> beanClass = (args[0] instanceof Class ? (Class<?>) args[0] : args[0].getClass());
|
||||
if (args.length >= 1) {
|
||||
if (hasClosureArgument) {
|
||||
if (args.length-1 != 1) {
|
||||
|
||||
+4
-6
@@ -94,7 +94,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
|
||||
private String nestedPath = "";
|
||||
|
||||
private Object rootObject;
|
||||
Object rootObject;
|
||||
|
||||
/**
|
||||
* Map with cached nested Accessors: nested path -> Accessor instance.
|
||||
@@ -590,7 +590,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
|
||||
throw new ConversionNotSupportedException(pce, requiredType, ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
catch (IllegalArgumentException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
|
||||
throw new TypeMismatchException(pce, requiredType, ex);
|
||||
@@ -914,11 +914,9 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
return BeanUtils.instantiate(type);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// TODO: Root cause exception context is lost here; just exception message preserved.
|
||||
// Should we throw another exception type that preserves context instead?
|
||||
catch (Throwable ex) {
|
||||
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + name,
|
||||
"Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path: " + ex);
|
||||
"Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ public abstract class AbstractPropertyAccessor extends TypeConverterSupport impl
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyAccessException if the property was valid but the
|
||||
* accessor method failed or a type mismatch occured
|
||||
* accessor method failed or a type mismatch occurred
|
||||
*/
|
||||
@Override
|
||||
public abstract void setPropertyValue(String propertyName, Object value) throws BeansException;
|
||||
|
||||
@@ -63,11 +63,10 @@ public abstract class BeanUtils {
|
||||
|
||||
/**
|
||||
* Convenience method to instantiate a class using its no-arg constructor.
|
||||
* As this method doesn't try to load classes by name, it should avoid
|
||||
* class-loading issues.
|
||||
* @param clazz class to instantiate
|
||||
* @return the new instance
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated
|
||||
* @see Class#newInstance()
|
||||
*/
|
||||
public static <T> T instantiate(Class<T> clazz) throws BeanInstantiationException {
|
||||
Assert.notNull(clazz, "Class must not be null");
|
||||
@@ -87,13 +86,12 @@ public abstract class BeanUtils {
|
||||
|
||||
/**
|
||||
* Instantiate a class using its no-arg constructor.
|
||||
* As this method doesn't try to load classes by name, it should avoid
|
||||
* class-loading issues.
|
||||
* <p>Note that this method tries to set the constructor accessible
|
||||
* if given a non-accessible (that is, non-public) constructor.
|
||||
* @param clazz class to instantiate
|
||||
* @return the new instance
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated
|
||||
* @see Constructor#newInstance
|
||||
*/
|
||||
public static <T> T instantiateClass(Class<T> clazz) throws BeanInstantiationException {
|
||||
Assert.notNull(clazz, "Class must not be null");
|
||||
@@ -111,17 +109,15 @@ public abstract class BeanUtils {
|
||||
/**
|
||||
* Instantiate a class using its no-arg constructor and return the new instance
|
||||
* as the specified assignable type.
|
||||
* <p>Useful in cases where
|
||||
* the type of the class to instantiate (clazz) is not available, but the type
|
||||
* desired (assignableTo) is known.
|
||||
* <p>As this method doesn't try to load classes by name, it should avoid
|
||||
* class-loading issues.
|
||||
* <p>Note that this method tries to set the constructor accessible
|
||||
* if given a non-accessible (that is, non-public) constructor.
|
||||
* <p>Useful in cases where the type of the class to instantiate (clazz) is not
|
||||
* available, but the type desired (assignableTo) is known.
|
||||
* <p>Note that this method tries to set the constructor accessible if given a
|
||||
* non-accessible (that is, non-public) constructor.
|
||||
* @param clazz class to instantiate
|
||||
* @param assignableTo type that clazz must be assignableTo
|
||||
* @return the new instance
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated
|
||||
* @see Constructor#newInstance
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T instantiateClass(Class<?> clazz, Class<T> assignableTo) throws BeanInstantiationException {
|
||||
@@ -131,14 +127,13 @@ public abstract class BeanUtils {
|
||||
|
||||
/**
|
||||
* Convenience method to instantiate a class using the given constructor.
|
||||
* As this method doesn't try to load classes by name, it should avoid
|
||||
* class-loading issues.
|
||||
* <p>Note that this method tries to set the constructor accessible
|
||||
* if given a non-accessible (that is, non-public) constructor.
|
||||
* <p>Note that this method tries to set the constructor accessible if given a
|
||||
* non-accessible (that is, non-public) constructor.
|
||||
* @param ctor the constructor to instantiate
|
||||
* @param args the constructor arguments to apply
|
||||
* @return the new instance
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated
|
||||
* @see Constructor#newInstance
|
||||
*/
|
||||
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
|
||||
Assert.notNull(ctor, "Constructor must not be null");
|
||||
|
||||
@@ -141,6 +141,7 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
*/
|
||||
public void setBeanInstance(Object object) {
|
||||
this.wrappedObject = object;
|
||||
this.rootObject = object;
|
||||
this.typeConverterDelegate = new TypeConverterDelegate(this, this.wrappedObject);
|
||||
setIntrospectionClass(object.getClass());
|
||||
}
|
||||
|
||||
+14
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,6 +24,7 @@ package org.springframework.beans;
|
||||
* spouse property of the target object has a null value.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class NullValueInNestedPathException extends InvalidPropertyException {
|
||||
@@ -47,4 +48,16 @@ public class NullValueInNestedPathException extends InvalidPropertyException {
|
||||
super(beanClass, propertyName, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new NullValueInNestedPathException.
|
||||
* @param beanClass the offending bean class
|
||||
* @param propertyName the offending property
|
||||
* @param msg the detail message
|
||||
* @param cause the root cause
|
||||
* @since 4.3.2
|
||||
*/
|
||||
public NullValueInNestedPathException(Class<?> beanClass, String propertyName, String msg, Throwable cause) {
|
||||
super(beanClass, propertyName, msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -120,7 +120,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyAccessException if the property was valid but the
|
||||
* accessor method failed or a type mismatch occured
|
||||
* accessor method failed or a type mismatch occurred
|
||||
*/
|
||||
void setPropertyValue(String propertyName, Object value) throws BeansException;
|
||||
|
||||
@@ -130,7 +130,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyAccessException if the property was valid but the
|
||||
* accessor method failed or a type mismatch occured
|
||||
* accessor method failed or a type mismatch occurred
|
||||
*/
|
||||
void setPropertyValue(PropertyValue pv) throws BeansException;
|
||||
|
||||
@@ -144,7 +144,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
|
||||
* occured for specific properties during the batch update. This exception bundles
|
||||
* occurred for specific properties during the batch update. This exception bundles
|
||||
* all individual PropertyAccessExceptions. All other properties will have been
|
||||
* successfully updated.
|
||||
*/
|
||||
@@ -164,7 +164,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
|
||||
* occured for specific properties during the batch update. This exception bundles
|
||||
* occurred for specific properties during the batch update. This exception bundles
|
||||
* all individual PropertyAccessExceptions. All other properties will have been
|
||||
* successfully updated.
|
||||
* @see #setPropertyValues(PropertyValues, boolean, boolean)
|
||||
@@ -185,7 +185,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
|
||||
* occured for specific properties during the batch update. This exception bundles
|
||||
* occurred for specific properties during the batch update. This exception bundles
|
||||
* all individual PropertyAccessExceptions. All other properties will have been
|
||||
* successfully updated.
|
||||
* @see #setPropertyValues(PropertyValues, boolean, boolean)
|
||||
@@ -208,7 +208,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
|
||||
* occured for specific properties during the batch update. This exception bundles
|
||||
* occurred for specific properties during the batch update. This exception bundles
|
||||
* all individual PropertyAccessExceptions. All other properties will have been
|
||||
* successfully updated.
|
||||
*/
|
||||
|
||||
+15
-1
@@ -59,6 +59,7 @@ import org.springframework.beans.propertyeditors.FileEditor;
|
||||
import org.springframework.beans.propertyeditors.InputSourceEditor;
|
||||
import org.springframework.beans.propertyeditors.InputStreamEditor;
|
||||
import org.springframework.beans.propertyeditors.LocaleEditor;
|
||||
import org.springframework.beans.propertyeditors.PathEditor;
|
||||
import org.springframework.beans.propertyeditors.PatternEditor;
|
||||
import org.springframework.beans.propertyeditors.PropertiesEditor;
|
||||
import org.springframework.beans.propertyeditors.ReaderEditor;
|
||||
@@ -87,11 +88,21 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
|
||||
private static Class<?> pathClass;
|
||||
|
||||
private static Class<?> zoneIdClass;
|
||||
|
||||
static {
|
||||
ClassLoader cl = PropertyEditorRegistrySupport.class.getClassLoader();
|
||||
try {
|
||||
zoneIdClass = ClassUtils.forName("java.time.ZoneId", PropertyEditorRegistrySupport.class.getClassLoader());
|
||||
pathClass = ClassUtils.forName("java.nio.file.Path", cl);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Java 7 Path class not available
|
||||
pathClass = null;
|
||||
}
|
||||
try {
|
||||
zoneIdClass = ClassUtils.forName("java.time.ZoneId", cl);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Java 8 ZoneId class not available
|
||||
@@ -211,6 +222,9 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
this.defaultEditors.put(InputStream.class, new InputStreamEditor());
|
||||
this.defaultEditors.put(InputSource.class, new InputSourceEditor());
|
||||
this.defaultEditors.put(Locale.class, new LocaleEditor());
|
||||
if (pathClass != null) {
|
||||
this.defaultEditors.put(pathClass, new PathEditor());
|
||||
}
|
||||
this.defaultEditors.put(Pattern.class, new PatternEditor());
|
||||
this.defaultEditors.put(Properties.class, new PropertiesEditor());
|
||||
this.defaultEditors.put(Reader.class, new ReaderEditor());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,8 +30,8 @@ import org.springframework.util.StringUtils;
|
||||
* Helper class for calculating property matches, according to a configurable
|
||||
* distance. Provide the list of potential matches and an easy way to generate
|
||||
* an error message. Works for both java bean properties and fields.
|
||||
* <p>
|
||||
* Mainly for use within the framework and in particular the binding facility
|
||||
*
|
||||
* <p>Mainly for use within the framework and in particular the binding facility.
|
||||
*
|
||||
* @author Alef Arendsen
|
||||
* @author Arjen Poutsma
|
||||
@@ -43,14 +43,12 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public abstract class PropertyMatches {
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Static section
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
/** Default maximum property distance: 2 */
|
||||
public static final int DEFAULT_MAX_DISTANCE = 2;
|
||||
|
||||
|
||||
// Static factory methods
|
||||
|
||||
/**
|
||||
* Create PropertyMatches for the given bean property.
|
||||
* @param propertyName the name of the property to find possible matches for
|
||||
@@ -90,9 +88,7 @@ public abstract class PropertyMatches {
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Instance section
|
||||
//---------------------------------------------------------------------
|
||||
// Instance state
|
||||
|
||||
private final String propertyName;
|
||||
|
||||
@@ -107,18 +103,19 @@ public abstract class PropertyMatches {
|
||||
this.possibleMatches = possibleMatches;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of the requested property.
|
||||
*/
|
||||
public String getPropertyName() {
|
||||
return propertyName;
|
||||
return this.propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the calculated possible matches.
|
||||
*/
|
||||
public String[] getPossibleMatches() {
|
||||
return possibleMatches;
|
||||
return this.possibleMatches;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,6 +124,9 @@ public abstract class PropertyMatches {
|
||||
*/
|
||||
public abstract String buildErrorMessage();
|
||||
|
||||
|
||||
// Implementation support for subclasses
|
||||
|
||||
protected void appendHintMessage(StringBuilder msg) {
|
||||
msg.append("Did you mean ");
|
||||
for (int i = 0; i < this.possibleMatches.length; i++) {
|
||||
@@ -184,9 +184,12 @@ public abstract class PropertyMatches {
|
||||
return d[s1.length()][s2.length()];
|
||||
}
|
||||
|
||||
|
||||
// Concrete subclasses
|
||||
|
||||
private static class BeanPropertyMatches extends PropertyMatches {
|
||||
|
||||
private BeanPropertyMatches(String propertyName, Class<?> beanClass, int maxDistance) {
|
||||
public BeanPropertyMatches(String propertyName, Class<?> beanClass, int maxDistance) {
|
||||
super(propertyName, calculateMatches(propertyName,
|
||||
BeanUtils.getPropertyDescriptors(beanClass), maxDistance));
|
||||
}
|
||||
@@ -231,12 +234,12 @@ public abstract class PropertyMatches {
|
||||
}
|
||||
return msg.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static class FieldPropertyMatches extends PropertyMatches {
|
||||
|
||||
private FieldPropertyMatches(String propertyName, Class<?> beanClass, int maxDistance) {
|
||||
public FieldPropertyMatches(String propertyName, Class<?> beanClass, int maxDistance) {
|
||||
super(propertyName, calculateMatches(propertyName, beanClass, maxDistance));
|
||||
}
|
||||
|
||||
@@ -255,7 +258,6 @@ public abstract class PropertyMatches {
|
||||
return StringUtils.toStringArray(candidates);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String buildErrorMessage() {
|
||||
String propertyName = getPropertyName();
|
||||
@@ -270,7 +272,6 @@ public abstract class PropertyMatches {
|
||||
}
|
||||
return msg.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -45,8 +45,6 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
|
||||
|
||||
private final Object value;
|
||||
|
||||
private Object source;
|
||||
|
||||
private boolean optional = false;
|
||||
|
||||
private boolean converted = false;
|
||||
@@ -78,12 +76,12 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
|
||||
Assert.notNull(original, "Original must not be null");
|
||||
this.name = original.getName();
|
||||
this.value = original.getValue();
|
||||
this.source = original.getSource();
|
||||
this.optional = original.isOptional();
|
||||
this.converted = original.converted;
|
||||
this.convertedValue = original.convertedValue;
|
||||
this.conversionNecessary = original.conversionNecessary;
|
||||
this.resolvedTokens = original.resolvedTokens;
|
||||
setSource(original.getSource());
|
||||
copyAttributesFrom(original);
|
||||
}
|
||||
|
||||
@@ -97,10 +95,10 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
|
||||
Assert.notNull(original, "Original must not be null");
|
||||
this.name = original.getName();
|
||||
this.value = newValue;
|
||||
this.source = original;
|
||||
this.optional = original.isOptional();
|
||||
this.conversionNecessary = original.conversionNecessary;
|
||||
this.resolvedTokens = original.resolvedTokens;
|
||||
setSource(original);
|
||||
copyAttributesFrom(original);
|
||||
}
|
||||
|
||||
@@ -129,16 +127,28 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
|
||||
*/
|
||||
public PropertyValue getOriginalPropertyValue() {
|
||||
PropertyValue original = this;
|
||||
while (original.source instanceof PropertyValue && original.source != original) {
|
||||
original = (PropertyValue) original.source;
|
||||
Object source = getSource();
|
||||
while (source instanceof PropertyValue && source != original) {
|
||||
original = (PropertyValue) source;
|
||||
source = original.getSource();
|
||||
}
|
||||
return original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this is an optional value, that is, to be ignored
|
||||
* when no corresponding property exists on the target class.
|
||||
* @since 3.0
|
||||
*/
|
||||
public void setOptional(boolean optional) {
|
||||
this.optional = optional;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this is an optional value, that is, to be ignored
|
||||
* when no corresponding property exists on the target class.
|
||||
* @since 3.0
|
||||
*/
|
||||
public boolean isOptional() {
|
||||
return this.optional;
|
||||
}
|
||||
@@ -180,7 +190,7 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
|
||||
PropertyValue otherPv = (PropertyValue) other;
|
||||
return (this.name.equals(otherPv.name) &&
|
||||
ObjectUtils.nullSafeEquals(this.value, otherPv.value) &&
|
||||
ObjectUtils.nullSafeEquals(this.source, otherPv.source));
|
||||
ObjectUtils.nullSafeEquals(getSource(), otherPv.getSource()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -269,7 +269,7 @@ class TypeConverterDelegate {
|
||||
}
|
||||
else {
|
||||
// convertedValue == null
|
||||
if (javaUtilOptionalEmpty != null && requiredType.equals(javaUtilOptionalEmpty.getClass())) {
|
||||
if (javaUtilOptionalEmpty != null && requiredType == javaUtilOptionalEmpty.getClass()) {
|
||||
convertedValue = javaUtilOptionalEmpty;
|
||||
}
|
||||
}
|
||||
@@ -290,15 +290,15 @@ class TypeConverterDelegate {
|
||||
|
||||
// Definitely doesn't match: throw IllegalArgumentException/IllegalStateException
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append("Cannot convert value of type [").append(ClassUtils.getDescriptiveType(newValue));
|
||||
msg.append("] to required type [").append(ClassUtils.getQualifiedName(requiredType)).append("]");
|
||||
msg.append("Cannot convert value of type '").append(ClassUtils.getDescriptiveType(newValue));
|
||||
msg.append("' to required type '").append(ClassUtils.getQualifiedName(requiredType)).append("'");
|
||||
if (propertyName != null) {
|
||||
msg.append(" for property '").append(propertyName).append("'");
|
||||
}
|
||||
if (editor != null) {
|
||||
msg.append(": PropertyEditor [").append(editor.getClass().getName()).append(
|
||||
"] returned inappropriate value of type [").append(
|
||||
ClassUtils.getDescriptiveType(convertedValue)).append("]");
|
||||
"] returned inappropriate value of type '").append(
|
||||
ClassUtils.getDescriptiveType(convertedValue)).append("'");
|
||||
throw new IllegalArgumentException(msg.toString());
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -73,7 +73,7 @@ public abstract class TypeConverterSupport extends PropertyEditorRegistrySupport
|
||||
catch (IllegalStateException ex) {
|
||||
throw new ConversionNotSupportedException(value, requiredType, ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
catch (IllegalArgumentException ex) {
|
||||
throw new TypeMismatchException(value, requiredType, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -57,10 +57,10 @@ public class TypeMismatchException extends PropertyAccessException {
|
||||
*/
|
||||
public TypeMismatchException(PropertyChangeEvent propertyChangeEvent, Class<?> requiredType, Throwable cause) {
|
||||
super(propertyChangeEvent,
|
||||
"Failed to convert property value of type [" +
|
||||
ClassUtils.getDescriptiveType(propertyChangeEvent.getNewValue()) + "]" +
|
||||
"Failed to convert property value of type '" +
|
||||
ClassUtils.getDescriptiveType(propertyChangeEvent.getNewValue()) + "'" +
|
||||
(requiredType != null ?
|
||||
" to required type [" + ClassUtils.getQualifiedName(requiredType) + "]" : "") +
|
||||
" to required type '" + ClassUtils.getQualifiedName(requiredType) + "'" : "") +
|
||||
(propertyChangeEvent.getPropertyName() != null ?
|
||||
" for property '" + propertyChangeEvent.getPropertyName() + "'" : ""),
|
||||
cause);
|
||||
@@ -84,8 +84,8 @@ public class TypeMismatchException extends PropertyAccessException {
|
||||
* @param cause the root cause (may be {@code null})
|
||||
*/
|
||||
public TypeMismatchException(Object value, Class<?> requiredType, Throwable cause) {
|
||||
super("Failed to convert value of type [" + ClassUtils.getDescriptiveType(value) + "]" +
|
||||
(requiredType != null ? " to required type [" + ClassUtils.getQualifiedName(requiredType) + "]" : ""),
|
||||
super("Failed to convert value of type '" + ClassUtils.getDescriptiveType(value) + "'" +
|
||||
(requiredType != null ? " to required type '" + ClassUtils.getQualifiedName(requiredType) + "'" : ""),
|
||||
cause);
|
||||
this.value = value;
|
||||
this.requiredType = requiredType;
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ public class BeanCreationException extends FatalBeanException {
|
||||
|
||||
/**
|
||||
* Add a related cause to this bean creation exception,
|
||||
* not being a direct cause of the failure but having occured
|
||||
* not being a direct cause of the failure but having occurred
|
||||
* earlier in the creation of the same bean instance.
|
||||
* @param ex the related cause to add
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -63,28 +63,35 @@ import org.springframework.core.ResolvableType;
|
||||
* are supposed to override beans of the same name in any parent factory.
|
||||
*
|
||||
* <p>Bean factory implementations should support the standard bean lifecycle interfaces
|
||||
* as far as possible. The full set of initialization methods and their standard order is:<br>
|
||||
* 1. BeanNameAware's {@code setBeanName}<br>
|
||||
* 2. BeanClassLoaderAware's {@code setBeanClassLoader}<br>
|
||||
* 3. BeanFactoryAware's {@code setBeanFactory}<br>
|
||||
* 4. ResourceLoaderAware's {@code setResourceLoader}
|
||||
* (only applicable when running in an application context)<br>
|
||||
* 5. ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
|
||||
* (only applicable when running in an application context)<br>
|
||||
* 6. MessageSourceAware's {@code setMessageSource}
|
||||
* (only applicable when running in an application context)<br>
|
||||
* 7. ApplicationContextAware's {@code setApplicationContext}
|
||||
* (only applicable when running in an application context)<br>
|
||||
* 8. ServletContextAware's {@code setServletContext}
|
||||
* (only applicable when running in a web application context)<br>
|
||||
* 9. {@code postProcessBeforeInitialization} methods of BeanPostProcessors<br>
|
||||
* 10. InitializingBean's {@code afterPropertiesSet}<br>
|
||||
* 11. a custom init-method definition<br>
|
||||
* 12. {@code postProcessAfterInitialization} methods of BeanPostProcessors
|
||||
* as far as possible. The full set of initialization methods and their standard order is:
|
||||
* <ol>
|
||||
* <li>BeanNameAware's {@code setBeanName}
|
||||
* <li>BeanClassLoaderAware's {@code setBeanClassLoader}
|
||||
* <li>BeanFactoryAware's {@code setBeanFactory}
|
||||
* <li>EnvironmentAware's {@code setEnvironment}
|
||||
* <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
|
||||
* <li>ResourceLoaderAware's {@code setResourceLoader}
|
||||
* (only applicable when running in an application context)
|
||||
* <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
|
||||
* (only applicable when running in an application context)
|
||||
* <li>MessageSourceAware's {@code setMessageSource}
|
||||
* (only applicable when running in an application context)
|
||||
* <li>ApplicationContextAware's {@code setApplicationContext}
|
||||
* (only applicable when running in an application context)
|
||||
* <li>ServletContextAware's {@code setServletContext}
|
||||
* (only applicable when running in a web application context)
|
||||
* <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
|
||||
* <li>InitializingBean's {@code afterPropertiesSet}
|
||||
* <li>a custom init-method definition
|
||||
* <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
|
||||
* </ol>
|
||||
*
|
||||
* <p>On shutdown of a bean factory, the following lifecycle methods apply:<br>
|
||||
* 1. DisposableBean's {@code destroy}<br>
|
||||
* 2. a custom destroy-method definition
|
||||
* <p>On shutdown of a bean factory, the following lifecycle methods apply:
|
||||
* <ol>
|
||||
* <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
|
||||
* <li>DisposableBean's {@code destroy}
|
||||
* <li>a custom destroy-method definition
|
||||
* </ol>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
@@ -153,12 +160,12 @@ public interface BeanFactory {
|
||||
|
||||
/**
|
||||
* Return the bean instance that uniquely matches the given object type, if any.
|
||||
* @param requiredType type the bean must match; can be an interface or superclass.
|
||||
* {@code null} is disallowed.
|
||||
* <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
|
||||
* but may also be translated into a conventional by-name lookup based on the name
|
||||
* of the given type. For more extensive retrieval operations across sets of beans,
|
||||
* use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
|
||||
* @param requiredType type the bean must match; can be an interface or superclass.
|
||||
* {@code null} is disallowed.
|
||||
* @return an instance of the single bean matching the required type
|
||||
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||
|
||||
+4
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Thrown when a bean doesn't match the expected type.
|
||||
@@ -45,8 +46,8 @@ public class BeanNotOfRequiredTypeException extends BeansException {
|
||||
* the expected type
|
||||
*/
|
||||
public BeanNotOfRequiredTypeException(String beanName, Class<?> requiredType, Class<?> actualType) {
|
||||
super("Bean named '" + beanName + "' must be of type [" + requiredType.getName() +
|
||||
"], but was actually of type [" + actualType.getName() + "]");
|
||||
super("Bean named '" + beanName + "' is expected to be of type '" + ClassUtils.getQualifiedName(requiredType) +
|
||||
"' but was actually of type '" + ClassUtils.getQualifiedName(actualType) + "'");
|
||||
this.beanName = beanName;
|
||||
this.requiredType = requiredType;
|
||||
this.actualType = actualType;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,10 +17,10 @@
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
/**
|
||||
* Counterpart of BeanNameAware. Returns the bean name of an object.
|
||||
* Counterpart of {@link BeanNameAware}. Returns the bean name of an object.
|
||||
*
|
||||
* <p>This interface can be introduced to avoid a brittle dependence
|
||||
* on bean name in objects used with Spring IoC and Spring AOP.
|
||||
* <p>This interface can be introduced to avoid a brittle dependence on
|
||||
* bean name in objects used with Spring IoC and Spring AOP.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
@@ -29,7 +29,7 @@ package org.springframework.beans.factory;
|
||||
public interface NamedBean {
|
||||
|
||||
/**
|
||||
* Return the name of this bean in a Spring bean factory.
|
||||
* Return the name of this bean in a Spring bean factory, if known.
|
||||
*/
|
||||
String getBeanName();
|
||||
|
||||
|
||||
+47
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -26,6 +28,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @see BeanFactory#getBean(String)
|
||||
* @see BeanFactory#getBean(Class)
|
||||
* @see NoUniqueBeanDefinitionException
|
||||
@@ -33,11 +36,9 @@ import org.springframework.util.StringUtils;
|
||||
@SuppressWarnings("serial")
|
||||
public class NoSuchBeanDefinitionException extends BeansException {
|
||||
|
||||
/** Name of the missing bean */
|
||||
private String beanName;
|
||||
|
||||
/** Required type of the missing bean */
|
||||
private Class<?> beanType;
|
||||
private ResolvableType resolvableType;
|
||||
|
||||
|
||||
/**
|
||||
@@ -45,7 +46,7 @@ public class NoSuchBeanDefinitionException extends BeansException {
|
||||
* @param name the name of the missing bean
|
||||
*/
|
||||
public NoSuchBeanDefinitionException(String name) {
|
||||
super("No bean named '" + name + "' is defined");
|
||||
super("No bean named '" + name + "' available");
|
||||
this.beanName = name;
|
||||
}
|
||||
|
||||
@@ -55,7 +56,7 @@ public class NoSuchBeanDefinitionException extends BeansException {
|
||||
* @param message detailed message describing the problem
|
||||
*/
|
||||
public NoSuchBeanDefinitionException(String name, String message) {
|
||||
super("No bean named '" + name + "' is defined: " + message);
|
||||
super("No bean named '" + name + "' available: " + message);
|
||||
this.beanName = name;
|
||||
}
|
||||
|
||||
@@ -64,8 +65,7 @@ public class NoSuchBeanDefinitionException extends BeansException {
|
||||
* @param type required type of the missing bean
|
||||
*/
|
||||
public NoSuchBeanDefinitionException(Class<?> type) {
|
||||
super("No qualifying bean of type [" + type.getName() + "] is defined");
|
||||
this.beanType = type;
|
||||
this(ResolvableType.forClass(type));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,8 +74,28 @@ public class NoSuchBeanDefinitionException extends BeansException {
|
||||
* @param message detailed message describing the problem
|
||||
*/
|
||||
public NoSuchBeanDefinitionException(Class<?> type, String message) {
|
||||
super("No qualifying bean of type [" + type.getName() + "] is defined: " + message);
|
||||
this.beanType = type;
|
||||
this(ResolvableType.forClass(type), message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code NoSuchBeanDefinitionException}.
|
||||
* @param type full type declaration of the missing bean
|
||||
* @since 4.3.4
|
||||
*/
|
||||
public NoSuchBeanDefinitionException(ResolvableType type) {
|
||||
super("No qualifying bean of type '" + type + "' available");
|
||||
this.resolvableType = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code NoSuchBeanDefinitionException}.
|
||||
* @param type full type declaration of the missing bean
|
||||
* @param message detailed message describing the problem
|
||||
* @since 4.3.4
|
||||
*/
|
||||
public NoSuchBeanDefinitionException(ResolvableType type, String message) {
|
||||
super("No qualifying bean of type '" + type + "' available: " + message);
|
||||
this.resolvableType = type;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,12 +103,15 @@ public class NoSuchBeanDefinitionException extends BeansException {
|
||||
* @param type required type of the missing bean
|
||||
* @param dependencyDescription a description of the originating dependency
|
||||
* @param message detailed message describing the problem
|
||||
* @deprecated as of 4.3.4, in favor of {@link #NoSuchBeanDefinitionException(ResolvableType, String)}
|
||||
*/
|
||||
@Deprecated
|
||||
public NoSuchBeanDefinitionException(Class<?> type, String dependencyDescription, String message) {
|
||||
super("No qualifying bean of type [" + type.getName() + "] found for dependency" +
|
||||
super("No qualifying bean" + (!StringUtils.hasLength(dependencyDescription) ?
|
||||
" of type '" + ClassUtils.getQualifiedName(type) + "'" : "") + " found for dependency" +
|
||||
(StringUtils.hasLength(dependencyDescription) ? " [" + dependencyDescription + "]" : "") +
|
||||
": " + message);
|
||||
this.beanType = type;
|
||||
this.resolvableType = ResolvableType.forClass(type);
|
||||
}
|
||||
|
||||
|
||||
@@ -100,10 +123,20 @@ public class NoSuchBeanDefinitionException extends BeansException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the required type of the missing bean, if it was a lookup <em>by type</em> that failed.
|
||||
* Return the required type of the missing bean, if it was a lookup <em>by type</em>
|
||||
* that failed.
|
||||
*/
|
||||
public Class<?> getBeanType() {
|
||||
return this.beanType;
|
||||
return (this.resolvableType != null ? this.resolvableType.resolve() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the required {@link ResolvableType} of the missing bean, if it was a lookup
|
||||
* <em>by type</em> that failed.
|
||||
* @since 4.3.4
|
||||
*/
|
||||
public ResolvableType getResolvableType() {
|
||||
return this.resolvableType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+7
-4
@@ -18,6 +18,7 @@ package org.springframework.beans.factory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Exception thrown when a bean depends on other beans or simple properties
|
||||
@@ -46,7 +47,7 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
|
||||
|
||||
super(resourceDescription, beanName,
|
||||
"Unsatisfied dependency expressed through bean property '" + propertyName + "'" +
|
||||
(msg != null ? ": " + msg : ""));
|
||||
(StringUtils.hasLength(msg) ? ": " + msg : ""));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,7 +60,7 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
|
||||
public UnsatisfiedDependencyException(
|
||||
String resourceDescription, String beanName, String propertyName, BeansException ex) {
|
||||
|
||||
this(resourceDescription, beanName, propertyName, (ex != null ? ex.getMessage() : ""));
|
||||
this(resourceDescription, beanName, propertyName, "");
|
||||
initCause(ex);
|
||||
}
|
||||
|
||||
@@ -74,7 +75,9 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
|
||||
public UnsatisfiedDependencyException(
|
||||
String resourceDescription, String beanName, InjectionPoint injectionPoint, String msg) {
|
||||
|
||||
super(resourceDescription, beanName, "Unsatisfied dependency expressed through " + injectionPoint + ": " + msg);
|
||||
super(resourceDescription, beanName,
|
||||
"Unsatisfied dependency expressed through " + injectionPoint +
|
||||
(StringUtils.hasLength(msg) ? ": " + msg : ""));
|
||||
this.injectionPoint = injectionPoint;
|
||||
}
|
||||
|
||||
@@ -89,7 +92,7 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
|
||||
public UnsatisfiedDependencyException(
|
||||
String resourceDescription, String beanName, InjectionPoint injectionPoint, BeansException ex) {
|
||||
|
||||
this(resourceDescription, beanName, injectionPoint, (ex != null ? ex.getMessage() : ""));
|
||||
this(resourceDescription, beanName, injectionPoint, "");
|
||||
initCause(ex);
|
||||
}
|
||||
|
||||
|
||||
+65
-42
@@ -220,7 +220,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
|
||||
throw new IllegalArgumentException(
|
||||
"AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory");
|
||||
@@ -238,35 +238,56 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName) throws BeansException {
|
||||
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
|
||||
throws BeanCreationException {
|
||||
|
||||
// Let's check for lookup methods here..
|
||||
if (!this.lookupMethodsChecked.contains(beanName)) {
|
||||
ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
|
||||
@Override
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
Lookup lookup = method.getAnnotation(Lookup.class);
|
||||
if (lookup != null) {
|
||||
LookupOverride override = new LookupOverride(method, lookup.value());
|
||||
try {
|
||||
RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
|
||||
mbd.getMethodOverrides().addOverride(override);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
throw new BeanCreationException(beanName,
|
||||
"Cannot apply @Lookup to beans without corresponding bean definition");
|
||||
try {
|
||||
ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
|
||||
@Override
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
Lookup lookup = method.getAnnotation(Lookup.class);
|
||||
if (lookup != null) {
|
||||
LookupOverride override = new LookupOverride(method, lookup.value());
|
||||
try {
|
||||
RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
|
||||
mbd.getMethodOverrides().addOverride(override);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
throw new BeanCreationException(beanName,
|
||||
"Cannot apply @Lookup to beans without corresponding bean definition");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
|
||||
}
|
||||
catch (NoClassDefFoundError err) {
|
||||
throw new BeanCreationException(beanName, "Failed to introspect bean class [" + beanClass.getName() +
|
||||
"] for lookup method metadata: could not find class that it depends on", err);
|
||||
}
|
||||
this.lookupMethodsChecked.add(beanName);
|
||||
}
|
||||
|
||||
// Quick check on the concurrent map first, with minimal locking.
|
||||
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
|
||||
if (candidateConstructors == null) {
|
||||
// Fully synchronized resolution now...
|
||||
synchronized (this.candidateConstructorsCache) {
|
||||
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
|
||||
if (candidateConstructors == null) {
|
||||
Constructor<?>[] rawCandidates = beanClass.getDeclaredConstructors();
|
||||
Constructor<?>[] rawCandidates;
|
||||
try {
|
||||
rawCandidates = beanClass.getDeclaredConstructors();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new BeanCreationException(beanName,
|
||||
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
|
||||
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
|
||||
}
|
||||
List<Constructor<?>> candidates = new ArrayList<Constructor<?>>(rawCandidates.length);
|
||||
Constructor<?> requiredConstructor = null;
|
||||
Constructor<?> defaultConstructor = null;
|
||||
@@ -292,10 +313,6 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
". Found constructor with 'required' Autowired annotation already: " +
|
||||
requiredConstructor);
|
||||
}
|
||||
if (candidate.getParameterTypes().length == 0) {
|
||||
throw new IllegalStateException(
|
||||
"Autowired annotation requires at least one argument: " + candidate);
|
||||
}
|
||||
boolean required = determineRequiredStatus(ann);
|
||||
if (required) {
|
||||
if (!candidates.isEmpty()) {
|
||||
@@ -320,9 +337,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
}
|
||||
else if (candidates.size() == 1 && logger.isWarnEnabled()) {
|
||||
logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
|
||||
"': single autowire-marked constructor flagged as optional - this constructor " +
|
||||
"is effectively required since there is no default constructor to fall back to: " +
|
||||
candidates.get(0));
|
||||
"': single autowire-marked constructor flagged as optional - " +
|
||||
"this constructor is effectively required since there is no " +
|
||||
"default constructor to fall back to: " + candidates.get(0));
|
||||
}
|
||||
}
|
||||
candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
|
||||
@@ -342,7 +359,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
|
||||
@Override
|
||||
public PropertyValues postProcessPropertyValues(
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
|
||||
|
||||
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
|
||||
try {
|
||||
@@ -361,9 +378,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
* 'Native' processing method for direct calls with an arbitrary target instance,
|
||||
* resolving all of its fields and methods which are annotated with {@code @Autowired}.
|
||||
* @param bean the target instance to process
|
||||
* @throws BeansException if autowiring failed
|
||||
* @throws BeanCreationException if autowiring failed
|
||||
*/
|
||||
public void processInjection(Object bean) throws BeansException {
|
||||
public void processInjection(Object bean) throws BeanCreationException {
|
||||
Class<?> clazz = bean.getClass();
|
||||
InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz, null);
|
||||
try {
|
||||
@@ -373,7 +390,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
throw ex;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new BeanCreationException("Injection of autowired dependencies failed for class [" + clazz + "]", ex);
|
||||
throw new BeanCreationException(
|
||||
"Injection of autowired dependencies failed for class [" + clazz + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,7 +464,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
}
|
||||
if (method.getParameterTypes().length == 0) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Autowired annotation should be used on methods with parameters: " + method);
|
||||
logger.warn("Autowired annotation should only be used on methods with parameters: " +
|
||||
method);
|
||||
}
|
||||
}
|
||||
boolean required = determineRequiredStatus(ann);
|
||||
@@ -577,7 +596,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
String autowiredBeanName = autowiredBeanNames.iterator().next();
|
||||
if (beanFactory.containsBean(autowiredBeanName)) {
|
||||
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
|
||||
this.cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName);
|
||||
this.cachedFieldValue = new ShortcutDependencyDescriptor(
|
||||
desc, autowiredBeanName, field.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -628,7 +648,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
arguments = new Object[paramTypes.length];
|
||||
DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
|
||||
Set<String> autowiredBeanNames = new LinkedHashSet<String>(paramTypes.length);
|
||||
Set<String> autowiredBeans = new LinkedHashSet<String>(paramTypes.length);
|
||||
TypeConverter typeConverter = beanFactory.getTypeConverter();
|
||||
for (int i = 0; i < arguments.length; i++) {
|
||||
MethodParameter methodParam = new MethodParameter(method, i);
|
||||
@@ -636,7 +656,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
currDesc.setContainingClass(bean.getClass());
|
||||
descriptors[i] = currDesc;
|
||||
try {
|
||||
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeanNames, typeConverter);
|
||||
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
|
||||
if (arg == null && !this.required) {
|
||||
arguments = null;
|
||||
break;
|
||||
@@ -654,15 +674,15 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
for (int i = 0; i < arguments.length; i++) {
|
||||
this.cachedMethodArguments[i] = descriptors[i];
|
||||
}
|
||||
registerDependentBeans(beanName, autowiredBeanNames);
|
||||
if (autowiredBeanNames.size() == paramTypes.length) {
|
||||
Iterator<String> it = autowiredBeanNames.iterator();
|
||||
registerDependentBeans(beanName, autowiredBeans);
|
||||
if (autowiredBeans.size() == paramTypes.length) {
|
||||
Iterator<String> it = autowiredBeans.iterator();
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
String autowiredBeanName = it.next();
|
||||
if (beanFactory.containsBean(autowiredBeanName)) {
|
||||
if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
|
||||
this.cachedMethodArguments[i] =
|
||||
new ShortcutDependencyDescriptor(descriptors[i], autowiredBeanName);
|
||||
this.cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
|
||||
descriptors[i], autowiredBeanName, paramTypes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -705,16 +725,19 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
@SuppressWarnings("serial")
|
||||
private static class ShortcutDependencyDescriptor extends DependencyDescriptor {
|
||||
|
||||
private final String shortcutBeanName;
|
||||
private final String shortcut;
|
||||
|
||||
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcutBeanName) {
|
||||
private final Class<?> requiredType;
|
||||
|
||||
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcut, Class<?> requiredType) {
|
||||
super(original);
|
||||
this.shortcutBeanName = shortcutBeanName;
|
||||
this.shortcut = shortcut;
|
||||
this.requiredType = requiredType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveShortcut(BeanFactory beanFactory) {
|
||||
return resolveCandidate(this.shortcutBeanName, beanFactory);
|
||||
return resolveCandidate(this.shortcut, this.requiredType, beanFactory);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,27 +18,30 @@ package org.springframework.beans.factory.annotation;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Convenience methods performing bean lookups related to annotations, for example
|
||||
* Spring's {@link Qualifier @Qualifier} annotation.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 3.1.2
|
||||
* @see BeanFactoryUtils
|
||||
*/
|
||||
public class BeanFactoryAnnotationUtils {
|
||||
public abstract class BeanFactoryAnnotationUtils {
|
||||
|
||||
/**
|
||||
* Obtain a bean of type {@code T} from the given {@code BeanFactory} declaring a
|
||||
@@ -48,9 +51,16 @@ public class BeanFactoryAnnotationUtils {
|
||||
* @param beanType the type of bean to retrieve
|
||||
* @param qualifier the qualifier for selecting between multiple bean matches
|
||||
* @return the matching bean of type {@code T} (never {@code null})
|
||||
* @throws NoUniqueBeanDefinitionException if multiple matching beans of type {@code T} found
|
||||
* @throws NoSuchBeanDefinitionException if no matching bean of type {@code T} found
|
||||
* @throws BeansException if the bean could not be created
|
||||
* @see BeanFactory#getBean(Class)
|
||||
*/
|
||||
public static <T> T qualifiedBeanOfType(BeanFactory beanFactory, Class<T> beanType, String qualifier) {
|
||||
public static <T> T qualifiedBeanOfType(BeanFactory beanFactory, Class<T> beanType, String qualifier)
|
||||
throws BeansException {
|
||||
|
||||
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||
|
||||
if (beanFactory instanceof ConfigurableListableBeanFactory) {
|
||||
// Full qualifier matching supported.
|
||||
return qualifiedBeanOfType((ConfigurableListableBeanFactory) beanFactory, beanType, qualifier);
|
||||
@@ -74,7 +84,6 @@ public class BeanFactoryAnnotationUtils {
|
||||
* @param beanType the type of bean to retrieve
|
||||
* @param qualifier the qualifier for selecting between multiple bean matches
|
||||
* @return the matching bean of type {@code T} (never {@code null})
|
||||
* @throws NoSuchBeanDefinitionException if no matching bean of type {@code T} found
|
||||
*/
|
||||
private static <T> T qualifiedBeanOfType(ConfigurableListableBeanFactory bf, Class<T> beanType, String qualifier) {
|
||||
String[] candidateBeans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(bf, beanType);
|
||||
@@ -82,8 +91,7 @@ public class BeanFactoryAnnotationUtils {
|
||||
for (String beanName : candidateBeans) {
|
||||
if (isQualifierMatch(qualifier, beanName, bf)) {
|
||||
if (matchingBean != null) {
|
||||
throw new NoSuchBeanDefinitionException(qualifier, "No unique " + beanType.getSimpleName() +
|
||||
" bean found for qualifier '" + qualifier + "'");
|
||||
throw new NoUniqueBeanDefinitionException(beanType, matchingBean, beanName);
|
||||
}
|
||||
matchingBean = beanName;
|
||||
}
|
||||
|
||||
+2
-1
@@ -40,6 +40,7 @@ import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcess
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.PriorityOrdered;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
@@ -349,7 +350,7 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
}
|
||||
this.method = method;
|
||||
this.identifier = (Modifier.isPrivate(method.getModifiers()) ?
|
||||
method.getDeclaringClass() + "." + method.getName() : method.getName());
|
||||
ClassUtils.getQualifiedMethodName(method) : method.getName());
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
|
||||
+14
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.beans.factory.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
@@ -49,6 +50,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.5
|
||||
* @see AutowireCandidateQualifier
|
||||
* @see Qualifier
|
||||
@@ -225,8 +227,12 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
|
||||
qualifier = bd.getQualifier(ClassUtils.getShortName(type));
|
||||
}
|
||||
if (qualifier == null) {
|
||||
// First, check annotation on factory method, if applicable
|
||||
Annotation targetAnnotation = getFactoryMethodAnnotation(bd, type);
|
||||
// First, check annotation on qualified element, if any
|
||||
Annotation targetAnnotation = getQualifiedElementAnnotation(bd, type);
|
||||
// Then, check annotation on factory method, if applicable
|
||||
if (targetAnnotation == null) {
|
||||
targetAnnotation = getFactoryMethodAnnotation(bd, type);
|
||||
}
|
||||
if (targetAnnotation == null) {
|
||||
RootBeanDefinition dbd = getResolvedDecoratedDefinition(bd);
|
||||
if (dbd != null) {
|
||||
@@ -291,6 +297,11 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Annotation getQualifiedElementAnnotation(RootBeanDefinition bd, Class<? extends Annotation> type) {
|
||||
AnnotatedElement qualifiedElement = bd.getQualifiedElement();
|
||||
return (qualifiedElement != null ? AnnotationUtils.getAnnotation(qualifiedElement, type) : null);
|
||||
}
|
||||
|
||||
protected Annotation getFactoryMethodAnnotation(RootBeanDefinition bd, Class<? extends Annotation> type) {
|
||||
Method resolvedFactoryMethod = bd.getResolvedFactoryMethod();
|
||||
return (resolvedFactoryMethod != null ? AnnotationUtils.getAnnotation(resolvedFactoryMethod, type) : null);
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -141,8 +141,7 @@ public class RequiredAnnotationBeanPostProcessor extends InstantiationAwareBeanP
|
||||
|
||||
@Override
|
||||
public PropertyValues postProcessPropertyValues(
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
|
||||
throws BeansException {
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
|
||||
|
||||
if (!this.validatedBeanNames.contains(beanName)) {
|
||||
if (!shouldSkip(this.beanFactory, beanName)) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -208,7 +208,7 @@ public abstract class AbstractFactoryBean<T>
|
||||
* <p>Invoked on initialization of this FactoryBean in case of
|
||||
* a singleton; else, on each {@link #getObject()} call.
|
||||
* @return the object returned by this factory
|
||||
* @throws Exception if an exception occured during object creation
|
||||
* @throws Exception if an exception occurred during object creation
|
||||
* @see #getObject()
|
||||
*/
|
||||
protected abstract T createInstance() throws Exception;
|
||||
|
||||
+47
-17
@@ -21,6 +21,8 @@ import java.util.Set;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
|
||||
/**
|
||||
* Extension of the {@link org.springframework.beans.factory.BeanFactory}
|
||||
@@ -154,15 +156,6 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
*/
|
||||
Object configureBean(Object existingBean, String beanName) throws BeansException;
|
||||
|
||||
/**
|
||||
* Resolve the specified dependency against the beans defined in this factory.
|
||||
* @param descriptor the descriptor for the dependency
|
||||
* @param beanName the name of the bean which declares the present dependency
|
||||
* @return the resolved object, or {@code null} if none found
|
||||
* @throws BeansException if dependency resolution failed
|
||||
*/
|
||||
Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Specialized methods for fine-grained control over the bean lifecycle
|
||||
@@ -312,18 +305,55 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
*/
|
||||
void destroyBean(Object existingBean);
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Delegate methods for resolving injection points
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Resolve the bean instance that uniquely matches the given object type, if any,
|
||||
* including its bean name.
|
||||
* <p>This is effectively a variant of {@link #getBean(Class)} which preserves the
|
||||
* bean name of the matching instance.
|
||||
* @param requiredType type the bean must match; can be an interface or superclass.
|
||||
* {@code null} is disallowed.
|
||||
* @return the bean name plus bean instance
|
||||
* @throws NoSuchBeanDefinitionException if no matching bean was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
|
||||
* @throws BeansException if the bean could not be created
|
||||
* @since 4.3.3
|
||||
* @see #getBean(Class)
|
||||
*/
|
||||
<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;
|
||||
|
||||
/**
|
||||
* Resolve the specified dependency against the beans defined in this factory.
|
||||
* @param descriptor the descriptor for the dependency
|
||||
* @param beanName the name of the bean which declares the present dependency
|
||||
* @param autowiredBeanNames a Set that all names of autowired beans (used for
|
||||
* resolving the present dependency) are supposed to be added to
|
||||
* @param typeConverter the TypeConverter to use for populating arrays and
|
||||
* collections
|
||||
* @param descriptor the descriptor for the dependency (field/method/constructor)
|
||||
* @param requestingBeanName the name of the bean which declares the given dependency
|
||||
* @return the resolved object, or {@code null} if none found
|
||||
* @throws BeansException if dependency resolution failed
|
||||
* @throws NoSuchBeanDefinitionException if no matching bean was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
|
||||
* @throws BeansException if dependency resolution failed for any other reason
|
||||
* @since 2.5
|
||||
* @see #resolveDependency(DependencyDescriptor, String, Set, TypeConverter)
|
||||
*/
|
||||
Object resolveDependency(DependencyDescriptor descriptor, String beanName,
|
||||
Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) throws BeansException;
|
||||
|
||||
/**
|
||||
* Resolve the specified dependency against the beans defined in this factory.
|
||||
* @param descriptor the descriptor for the dependency (field/method/constructor)
|
||||
* @param requestingBeanName the name of the bean which declares the given dependency
|
||||
* @param autowiredBeanNames a Set that all names of autowired beans (used for
|
||||
* resolving the given dependency) are supposed to be added to
|
||||
* @param typeConverter the TypeConverter to use for populating arrays and collections
|
||||
* @return the resolved object, or {@code null} if none found
|
||||
* @throws NoSuchBeanDefinitionException if no matching bean was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
|
||||
* @throws BeansException if dependency resolution failed for any other reason
|
||||
* @since 2.5
|
||||
* @see DependencyDescriptor
|
||||
*/
|
||||
Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
|
||||
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException;
|
||||
|
||||
}
|
||||
|
||||
+21
-16
@@ -172,21 +172,6 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the specified bean name, as a candidate result of the matching
|
||||
* algorithm for this dependency, to a bean instance from the given factory.
|
||||
* <p>The default implementation calls {@link BeanFactory#getBean(String)}.
|
||||
* Subclasses may provide additional arguments or other customizations.
|
||||
* @param beanName the bean name, as a candidate result for this dependency
|
||||
* @param beanFactory the associated factory
|
||||
* @return the bean instance (never {@code null})
|
||||
* @since 4.3
|
||||
* @see BeanFactory#getBean(String)
|
||||
*/
|
||||
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
|
||||
return beanFactory.getBean(beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a shortcut for this dependency against the given factory, for example
|
||||
* taking some pre-resolved information into account.
|
||||
@@ -196,12 +181,32 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
* pre-cached information while still receiving {@link InjectionPoint} exposure etc.
|
||||
* @param beanFactory the associated factory
|
||||
* @return the shortcut result if any, or {@code null} if none
|
||||
* @throws BeansException if the shortcut could not be obtained
|
||||
* @since 4.3.1
|
||||
*/
|
||||
public Object resolveShortcut(BeanFactory beanFactory) {
|
||||
public Object resolveShortcut(BeanFactory beanFactory) throws BeansException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the specified bean name, as a candidate result of the matching
|
||||
* algorithm for this dependency, to a bean instance from the given factory.
|
||||
* <p>The default implementation calls {@link BeanFactory#getBean(String)}.
|
||||
* Subclasses may provide additional arguments or other customizations.
|
||||
* @param beanName the bean name, as a candidate result for this dependency
|
||||
* @param requiredType the expected type of the bean (as an assertion)
|
||||
* @param beanFactory the associated factory
|
||||
* @return the bean instance (never {@code null})
|
||||
* @throws BeansException if the bean could not be obtained
|
||||
* @since 4.3.2
|
||||
* @see BeanFactory#getBean(String)
|
||||
*/
|
||||
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
|
||||
throws BeansException {
|
||||
|
||||
return beanFactory.getBean(beanName, requiredType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Increase this descriptor's nesting level.
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -103,7 +103,6 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
|
||||
* @see org.springframework.beans.MutablePropertyValues
|
||||
*/
|
||||
PropertyValues postProcessPropertyValues(
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
|
||||
throws BeansException;
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
|
||||
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -66,8 +66,7 @@ public abstract class InstantiationAwareBeanPostProcessorAdapter implements Smar
|
||||
|
||||
@Override
|
||||
public PropertyValues postProcessPropertyValues(
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
|
||||
throws BeansException {
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
|
||||
|
||||
return pvs;
|
||||
}
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://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.beans.factory.config;
|
||||
|
||||
import org.springframework.beans.factory.NamedBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A simple holder for a given bean name plus bean instance.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.3.3
|
||||
* @see AutowireCapableBeanFactory#resolveNamedBean(Class)
|
||||
*/
|
||||
public class NamedBeanHolder<T> implements NamedBean {
|
||||
|
||||
private final String beanName;
|
||||
|
||||
private final T beanInstance;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new holder for the given bean name plus instance.
|
||||
* @param beanName the name of the bean
|
||||
* @param beanInstance the corresponding bean instance
|
||||
*/
|
||||
public NamedBeanHolder(String beanName, T beanInstance) {
|
||||
Assert.notNull(beanName, "Bean name must not be null");
|
||||
this.beanName = beanName;
|
||||
this.beanInstance = beanInstance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of the bean (never {@code null}).
|
||||
*/
|
||||
@Override
|
||||
public String getBeanName() {
|
||||
return this.beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the corresponding bean instance (can be {@code null}).
|
||||
*/
|
||||
public T getBeanInstance() {
|
||||
return this.beanInstance;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -95,7 +95,7 @@ public class PropertiesFactoryBean extends PropertiesLoaderSupport
|
||||
* <p>Invoked on initialization of this FactoryBean in case of a
|
||||
* shared singleton; else, on each {@link #getObject()} call.
|
||||
* @return the object returned by this factory
|
||||
* @throws IOException if an exception occured during properties loading
|
||||
* @throws IOException if an exception occurred during properties loading
|
||||
* @see #mergeProperties()
|
||||
*/
|
||||
protected Properties createProperties() throws IOException {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -68,6 +68,7 @@ public interface Scope {
|
||||
* @param objectFactory the {@link ObjectFactory} to use to create the scoped
|
||||
* object if it is not present in the underlying storage mechanism
|
||||
* @return the desired object (never {@code null})
|
||||
* @throws IllegalStateException if the underlying scope is not currently active
|
||||
*/
|
||||
Object get(String name, ObjectFactory<?> objectFactory);
|
||||
|
||||
@@ -84,6 +85,7 @@ public interface Scope {
|
||||
* removing an object.
|
||||
* @param name the name of the object to remove
|
||||
* @return the removed object, or {@code null} if no object was present
|
||||
* @throws IllegalStateException if the underlying scope is not currently active
|
||||
* @see #registerDestructionCallback
|
||||
*/
|
||||
Object remove(String name);
|
||||
@@ -112,6 +114,7 @@ public interface Scope {
|
||||
* so it can safely be executed without an enclosing try-catch block.
|
||||
* Furthermore, the Runnable will usually be serializable, provided
|
||||
* that its target object is serializable as well.
|
||||
* @throws IllegalStateException if the underlying scope is not currently active
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#getDestroyMethodName()
|
||||
* @see DestructionAwareBeanPostProcessor
|
||||
@@ -123,6 +126,7 @@ public interface Scope {
|
||||
* E.g. the HttpServletRequest object for key "request".
|
||||
* @param key the contextual key
|
||||
* @return the corresponding object, or {@code null} if none found
|
||||
* @throws IllegalStateException if the underlying scope is not currently active
|
||||
*/
|
||||
Object resolveContextualObject(String key);
|
||||
|
||||
@@ -139,6 +143,7 @@ public interface Scope {
|
||||
* underlying storage mechanism has no obvious candidate for such an ID.
|
||||
* @return the conversation ID, or {@code null} if there is no
|
||||
* conversation ID for the current scope
|
||||
* @throws IllegalStateException if the underlying scope is not currently active
|
||||
*/
|
||||
String getConversationId();
|
||||
|
||||
|
||||
+14
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,12 +25,16 @@ import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* Factory for a Map that reads from a YAML source. YAML is a nice human-readable
|
||||
* format for configuration, and it has some useful hierarchical properties. It's
|
||||
* more or less a superset of JSON, so it has a lot of similar features. If
|
||||
* multiple resources are provided the later ones will override entries in the
|
||||
* earlier ones hierarchically - that is all entries with the same nested key of
|
||||
* type Map at any depth are merged. For example:
|
||||
* Factory for a {@code Map} that reads from a YAML source, preserving the
|
||||
* YAML-declared value types and their structure.
|
||||
*
|
||||
* <p>YAML is a nice human-readable format for configuration, and it has some
|
||||
* useful hierarchical properties. It's more or less a superset of JSON, so it
|
||||
* has a lot of similar features.
|
||||
*
|
||||
* <p>If multiple resources are provided the later ones will override entries in
|
||||
* the earlier ones hierarchically; that is, all entries with the same nested key
|
||||
* of type {@code Map} at any depth are merged. For example:
|
||||
*
|
||||
* <pre class="code">
|
||||
* foo:
|
||||
@@ -62,6 +66,7 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
* with the value in the second, but its nested values are merged.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
*/
|
||||
public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean<Map<String, Object>>, InitializingBean {
|
||||
@@ -104,10 +109,10 @@ public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean<Map
|
||||
|
||||
/**
|
||||
* Template method that subclasses may override to construct the object
|
||||
* returned by this factory. The default implementation returns the
|
||||
* merged Map instance.
|
||||
* returned by this factory.
|
||||
* <p>Invoked lazily the first time {@link #getObject()} is invoked in
|
||||
* case of a shared singleton; else, on each {@link #getObject()} call.
|
||||
* <p>The default implementation returns the merged {@code Map} instance.
|
||||
* @return the object returned by this factory
|
||||
* @see #process(java.util.Map, MatchCallback)
|
||||
*/
|
||||
|
||||
+12
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,6 +37,7 @@ import org.yaml.snakeyaml.nodes.MappingNode;
|
||||
import org.yaml.snakeyaml.parser.ParserException;
|
||||
import org.yaml.snakeyaml.reader.UnicodeReader;
|
||||
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -45,6 +46,7 @@ import org.springframework.util.StringUtils;
|
||||
* Base class for YAML factories.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
*/
|
||||
public abstract class YamlProcessor {
|
||||
@@ -217,7 +219,7 @@ public abstract class YamlProcessor {
|
||||
}
|
||||
|
||||
private boolean process(Map<String, Object> map, MatchCallback callback) {
|
||||
Properties properties = new Properties();
|
||||
Properties properties = CollectionFactory.createStringAdaptingProperties();
|
||||
properties.putAll(getFlattenedMap(map));
|
||||
|
||||
if (this.documentMatchers.isEmpty()) {
|
||||
@@ -278,7 +280,7 @@ public abstract class YamlProcessor {
|
||||
key = path + key;
|
||||
}
|
||||
else {
|
||||
key = path + "." + key;
|
||||
key = path + '.' + key;
|
||||
}
|
||||
}
|
||||
Object value = entry.getValue();
|
||||
@@ -302,21 +304,23 @@ public abstract class YamlProcessor {
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.put(key, value != null ? value : "");
|
||||
result.put(key, (value != null ? value : ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback interface used to process properties in a resulting map.
|
||||
* Callback interface used to process the YAML parsing results.
|
||||
*/
|
||||
public interface MatchCallback {
|
||||
|
||||
/**
|
||||
* Process the properties.
|
||||
* @param properties the properties to process
|
||||
* @param map a mutable result map
|
||||
* Process the given representation of the parsing results.
|
||||
* @param properties the properties to process (as a flattened
|
||||
* representation with indexed keys in case of a collection or map)
|
||||
* @param map the result map (preserving the original value structure
|
||||
* in the YAML document)
|
||||
*/
|
||||
void process(Properties properties, Map<String, Object> map);
|
||||
}
|
||||
|
||||
+20
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,13 +21,23 @@ import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.CollectionFactory;
|
||||
|
||||
/**
|
||||
* Factory for Java Properties that reads from a YAML source. YAML is a nice
|
||||
* human-readable format for configuration, and it has some useful hierarchical
|
||||
* properties. It's more or less a superset of JSON, so it has a lot of similar
|
||||
* features. The Properties created by this factory have nested paths for
|
||||
* hierarchical objects, so for instance this YAML
|
||||
* Factory for {@link java.util.Properties} that reads from a YAML source,
|
||||
* exposing a flat structure of String property values.
|
||||
*
|
||||
* <p>YAML is a nice human-readable format for configuration, and it has some
|
||||
* useful hierarchical properties. It's more or less a superset of JSON, so it
|
||||
* has a lot of similar features.
|
||||
*
|
||||
* <p><b>Note: All exposed values are of type {@code String}</b> for access through
|
||||
* the common {@link Properties#getProperty} method (e.g. in configuration property
|
||||
* resolution through {@link PropertyResourceConfigurer#setProperties(Properties)}).
|
||||
* If this is not desirable, use {@link YamlMapFactoryBean} instead.
|
||||
*
|
||||
* <p>The Properties created by this factory have nested paths for hierarchical
|
||||
* objects, so for instance this YAML
|
||||
*
|
||||
* <pre class="code">
|
||||
* environments:
|
||||
@@ -39,7 +49,7 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
* name: My Cool App
|
||||
* </pre>
|
||||
*
|
||||
* is transformed into these Properties:
|
||||
* is transformed into these properties:
|
||||
*
|
||||
* <pre class="code">
|
||||
* environments.dev.url=http://dev.bar.com
|
||||
@@ -57,7 +67,7 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
* - foo.bar.com
|
||||
* </pre>
|
||||
*
|
||||
* becomes Java Properties like this:
|
||||
* becomes properties like this:
|
||||
*
|
||||
* <pre class="code">
|
||||
* servers[0]=dev.bar.com
|
||||
@@ -66,6 +76,7 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Stephane Nicoll
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
*/
|
||||
public class YamlPropertiesFactoryBean extends YamlProcessor implements FactoryBean<Properties>, InitializingBean {
|
||||
@@ -116,7 +127,7 @@ public class YamlPropertiesFactoryBean extends YamlProcessor implements FactoryB
|
||||
* @see #process(MatchCallback) ()
|
||||
*/
|
||||
protected Properties createProperties() {
|
||||
final Properties result = new Properties();
|
||||
final Properties result = CollectionFactory.createStringAdaptingProperties();
|
||||
process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
|
||||
+60
-47
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -74,6 +74,7 @@ import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.PriorityOrdered;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -325,8 +326,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException {
|
||||
return resolveDependency(descriptor, beanName, null, null);
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) throws BeansException {
|
||||
return resolveDependency(descriptor, requestingBeanName, null, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -500,7 +501,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @see #instantiateUsingFactoryMethod
|
||||
* @see #autowireConstructor
|
||||
*/
|
||||
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
|
||||
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
|
||||
throws BeanCreationException {
|
||||
|
||||
// Instantiate the bean.
|
||||
BeanWrapper instanceWrapper = null;
|
||||
if (mbd.isSingleton()) {
|
||||
@@ -515,7 +518,13 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
// Allow post-processors to modify the merged bean definition.
|
||||
synchronized (mbd.postProcessingLock) {
|
||||
if (!mbd.postProcessed) {
|
||||
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
|
||||
try {
|
||||
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
"Post-processing of merged bean definition failed", ex);
|
||||
}
|
||||
mbd.postProcessed = true;
|
||||
}
|
||||
}
|
||||
@@ -550,7 +559,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
throw (BeanCreationException) ex;
|
||||
}
|
||||
else {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
|
||||
throw new BeanCreationException(
|
||||
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,7 +596,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
registerDisposableBeanIfNecessary(beanName, bean, mbd);
|
||||
}
|
||||
catch (BeanDefinitionValidationException ex) {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
|
||||
throw new BeanCreationException(
|
||||
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
|
||||
}
|
||||
|
||||
return exposedObject;
|
||||
@@ -624,10 +635,11 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
protected Class<?> determineTargetType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
|
||||
Class<?> targetType = mbd.getTargetType();
|
||||
if (targetType == null) {
|
||||
targetType = (mbd.getFactoryMethodName() != null ? getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
|
||||
targetType = (mbd.getFactoryMethodName() != null ?
|
||||
getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
|
||||
resolveBeanClass(mbd, beanName, typesToMatch));
|
||||
if (ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null) {
|
||||
mbd.setTargetType(targetType);
|
||||
mbd.resolvedTargetType = targetType;
|
||||
}
|
||||
}
|
||||
return targetType;
|
||||
@@ -648,9 +660,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @see #createBean
|
||||
*/
|
||||
protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
|
||||
Class<?> preResolved = mbd.resolvedFactoryMethodReturnType;
|
||||
if (preResolved != null) {
|
||||
return preResolved;
|
||||
ResolvableType cachedReturnType = mbd.factoryMethodReturnType;
|
||||
if (cachedReturnType != null) {
|
||||
return cachedReturnType.resolve();
|
||||
}
|
||||
|
||||
Class<?> factoryClass;
|
||||
@@ -674,11 +686,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
if (factoryClass == null) {
|
||||
return null;
|
||||
}
|
||||
factoryClass = ClassUtils.getUserClass(factoryClass);
|
||||
|
||||
// If all factory methods have the same return type, return that type.
|
||||
// Can't clearly figure out exact method due to type converting / autowiring!
|
||||
Class<?> commonType = null;
|
||||
boolean cache = false;
|
||||
Method uniqueCandidate = null;
|
||||
int minNrOfArgs = mbd.getConstructorArgumentValues().getArgumentCount();
|
||||
Method[] candidates = ReflectionUtils.getUniqueDeclaredMethods(factoryClass);
|
||||
for (Method factoryMethod : candidates) {
|
||||
@@ -713,8 +726,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
Class<?> returnType = AutowireUtils.resolveReturnTypeForFactoryMethod(
|
||||
factoryMethod, args, getBeanClassLoader());
|
||||
if (returnType != null) {
|
||||
cache = true;
|
||||
uniqueCandidate = (commonType == null ? factoryMethod : null);
|
||||
commonType = ClassUtils.determineCommonAncestor(returnType, commonType);
|
||||
if (commonType == null) {
|
||||
// Ambiguous return types found: return null to indicate "not determinable".
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
@@ -724,22 +741,22 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
}
|
||||
else {
|
||||
uniqueCandidate = (commonType == null ? factoryMethod : null);
|
||||
commonType = ClassUtils.determineCommonAncestor(factoryMethod.getReturnType(), commonType);
|
||||
if (commonType == null) {
|
||||
// Ambiguous return types found: return null to indicate "not determinable".
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (commonType != null) {
|
||||
// Clear return type found: all factory methods return same type.
|
||||
if (cache) {
|
||||
mbd.resolvedFactoryMethodReturnType = commonType;
|
||||
}
|
||||
return commonType;
|
||||
}
|
||||
else {
|
||||
// Ambiguous return types found: return null to indicate "not determinable".
|
||||
return null;
|
||||
mbd.factoryMethodReturnType = (uniqueCandidate != null ?
|
||||
ResolvableType.forMethodReturnType(uniqueCandidate) : ResolvableType.forClass(commonType));
|
||||
}
|
||||
return commonType;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -772,10 +789,11 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
ReflectionUtils.doWithMethods(fbClass,
|
||||
new ReflectionUtils.MethodCallback() {
|
||||
@Override
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
public void doWith(Method method) {
|
||||
if (method.getName().equals(factoryMethodName) &&
|
||||
FactoryBean.class.isAssignableFrom(method.getReturnType())) {
|
||||
objectType.value = GenericTypeResolver.resolveReturnTypeArgument(method, FactoryBean.class);
|
||||
objectType.value = GenericTypeResolver.resolveReturnTypeArgument(
|
||||
method, FactoryBean.class);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -802,10 +820,14 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
if (objectType.value != null) {
|
||||
return objectType.value;
|
||||
}
|
||||
else {
|
||||
// No type found for shortcut FactoryBean instance:
|
||||
// fall back to full creation of the FactoryBean instance.
|
||||
return super.getTypeForFactoryBean(beanName, mbd);
|
||||
}
|
||||
}
|
||||
|
||||
// No type found - fall back to full creation of the FactoryBean instance.
|
||||
return super.getTypeForFactoryBean(beanName, mbd);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -824,7 +846,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
|
||||
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
|
||||
if (exposedObject == null) {
|
||||
return exposedObject;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -922,24 +944,15 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @param mbd the merged bean definition for the bean
|
||||
* @param beanType the actual type of the managed bean instance
|
||||
* @param beanName the name of the bean
|
||||
* @throws BeansException if any post-processing failed
|
||||
* @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
|
||||
*/
|
||||
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)
|
||||
throws BeansException {
|
||||
|
||||
try {
|
||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||
if (bp instanceof MergedBeanDefinitionPostProcessor) {
|
||||
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
|
||||
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
|
||||
}
|
||||
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
|
||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||
if (bp instanceof MergedBeanDefinitionPostProcessor) {
|
||||
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
|
||||
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
"Post-processing failed of bean type [" + beanType + "] failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -976,12 +989,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @param beanClass the class of the bean to be instantiated
|
||||
* @param beanName the name of the bean
|
||||
* @return the bean object to use instead of a default instance of the target bean, or {@code null}
|
||||
* @throws BeansException if any post-processing failed
|
||||
* @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
|
||||
*/
|
||||
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
|
||||
throws BeansException {
|
||||
|
||||
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
|
||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||
if (bp instanceof InstantiationAwareBeanPostProcessor) {
|
||||
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
|
||||
@@ -1102,7 +1112,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
return bw;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
|
||||
throw new BeanCreationException(
|
||||
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1654,7 +1665,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* methods with arguments.
|
||||
* @see #invokeInitMethods
|
||||
*/
|
||||
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
|
||||
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd)
|
||||
throws Throwable {
|
||||
|
||||
String initMethodName = mbd.getInitMethodName();
|
||||
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
|
||||
BeanUtils.findMethod(bean.getClass(), initMethodName) :
|
||||
|
||||
+54
-28
@@ -134,13 +134,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
private final Set<PropertyEditorRegistrar> propertyEditorRegistrars =
|
||||
new LinkedHashSet<PropertyEditorRegistrar>(4);
|
||||
|
||||
/** A custom TypeConverter to use, overriding the default PropertyEditor mechanism */
|
||||
private TypeConverter typeConverter;
|
||||
|
||||
/** Custom PropertyEditors to apply to the beans of this factory */
|
||||
private final Map<Class<?>, Class<? extends PropertyEditor>> customEditors =
|
||||
new HashMap<Class<?>, Class<? extends PropertyEditor>>(4);
|
||||
|
||||
/** A custom TypeConverter to use, overriding the default PropertyEditor mechanism */
|
||||
private TypeConverter typeConverter;
|
||||
|
||||
/** String resolvers to apply e.g. to annotation attribute values */
|
||||
private final List<StringValueResolver> embeddedValueResolvers = new LinkedList<StringValueResolver>();
|
||||
|
||||
@@ -287,13 +287,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
// Guarantee initialization of beans that the current bean depends on.
|
||||
String[] dependsOn = mbd.getDependsOn();
|
||||
if (dependsOn != null) {
|
||||
for (String dependsOnBean : dependsOn) {
|
||||
if (isDependent(beanName, dependsOnBean)) {
|
||||
for (String dep : dependsOn) {
|
||||
if (isDependent(beanName, dep)) {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
|
||||
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
|
||||
}
|
||||
registerDependentBean(dependsOnBean, beanName);
|
||||
getBean(dependsOnBean);
|
||||
registerDependentBean(dep, beanName);
|
||||
getBean(dep);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,8 +372,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
}
|
||||
catch (TypeMismatchException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to convert bean '" + name + "' to required type [" +
|
||||
ClassUtils.getQualifiedName(requiredType) + "]", ex);
|
||||
logger.debug("Failed to convert bean '" + name + "' to required type '" +
|
||||
ClassUtils.getQualifiedName(requiredType) + "'", ex);
|
||||
}
|
||||
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
|
||||
}
|
||||
@@ -460,19 +460,19 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
return false;
|
||||
}
|
||||
if (isFactoryBean(beanName, mbd)) {
|
||||
final FactoryBean<?> factoryBean = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
|
||||
final FactoryBean<?> fb = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
|
||||
if (System.getSecurityManager() != null) {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
||||
@Override
|
||||
public Boolean run() {
|
||||
return ((factoryBean instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factoryBean).isPrototype()) ||
|
||||
!factoryBean.isSingleton());
|
||||
return ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) ||
|
||||
!fb.isSingleton());
|
||||
}
|
||||
}, getAccessControlContext());
|
||||
}
|
||||
else {
|
||||
return ((factoryBean instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factoryBean).isPrototype()) ||
|
||||
!factoryBean.isSingleton());
|
||||
return ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) ||
|
||||
!fb.isSingleton());
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -517,7 +517,10 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
// Retrieve corresponding bean definition.
|
||||
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
|
||||
|
||||
Class<?> classToMatch = typeToMatch.getRawClass();
|
||||
Class<?> classToMatch = typeToMatch.resolve();
|
||||
if (classToMatch == null) {
|
||||
classToMatch = FactoryBean.class;
|
||||
}
|
||||
Class<?>[] typesToMatch = (FactoryBean.class == classToMatch ?
|
||||
new Class<?>[] {classToMatch} : new Class<?>[] {FactoryBean.class, classToMatch});
|
||||
|
||||
@@ -557,6 +560,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
}
|
||||
}
|
||||
|
||||
ResolvableType resolvableType = mbd.targetType;
|
||||
if (resolvableType == null) {
|
||||
resolvableType = mbd.factoryMethodReturnType;
|
||||
}
|
||||
if (resolvableType != null && resolvableType.resolve() == beanType) {
|
||||
return typeToMatch.isAssignableFrom(resolvableType);
|
||||
}
|
||||
return typeToMatch.isAssignableFrom(beanType);
|
||||
}
|
||||
}
|
||||
@@ -805,12 +815,15 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
|
||||
@Override
|
||||
public String resolveEmbeddedValue(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String result = value;
|
||||
for (StringValueResolver resolver : this.embeddedValueResolvers) {
|
||||
result = resolver.resolveStringValue(result);
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
result = resolver.resolveStringValue(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -918,10 +931,12 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
setBeanClassLoader(otherFactory.getBeanClassLoader());
|
||||
setCacheBeanMetadata(otherFactory.isCacheBeanMetadata());
|
||||
setBeanExpressionResolver(otherFactory.getBeanExpressionResolver());
|
||||
setConversionService(otherFactory.getConversionService());
|
||||
if (otherFactory instanceof AbstractBeanFactory) {
|
||||
AbstractBeanFactory otherAbstractFactory = (AbstractBeanFactory) otherFactory;
|
||||
this.customEditors.putAll(otherAbstractFactory.customEditors);
|
||||
this.propertyEditorRegistrars.addAll(otherAbstractFactory.propertyEditorRegistrars);
|
||||
this.customEditors.putAll(otherAbstractFactory.customEditors);
|
||||
this.typeConverter = otherAbstractFactory.typeConverter;
|
||||
this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors);
|
||||
this.hasInstantiationAwareBeanPostProcessors = this.hasInstantiationAwareBeanPostProcessors ||
|
||||
otherAbstractFactory.hasInstantiationAwareBeanPostProcessors;
|
||||
@@ -932,6 +947,10 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
}
|
||||
else {
|
||||
setTypeConverter(otherFactory.getTypeConverter());
|
||||
String[] otherScopeNames = otherFactory.getRegisteredScopeNames();
|
||||
for (String scopeName : otherScopeNames) {
|
||||
this.scopes.put(scopeName, otherFactory.getRegisteredScope(scopeName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1050,11 +1069,11 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
* Destroy the given bean instance (usually a prototype instance
|
||||
* obtained from this factory) according to the given bean definition.
|
||||
* @param beanName the name of the bean definition
|
||||
* @param beanInstance the bean instance to destroy
|
||||
* @param bean the bean instance to destroy
|
||||
* @param mbd the merged bean definition
|
||||
*/
|
||||
protected void destroyBean(String beanName, Object beanInstance, RootBeanDefinition mbd) {
|
||||
new DisposableBeanAdapter(beanInstance, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy();
|
||||
protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) {
|
||||
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1235,12 +1254,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
pbd = getMergedBeanDefinition(parentBeanName);
|
||||
}
|
||||
else {
|
||||
if (getParentBeanFactory() instanceof ConfigurableBeanFactory) {
|
||||
pbd = ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(parentBeanName);
|
||||
BeanFactory parent = getParentBeanFactory();
|
||||
if (parent instanceof ConfigurableBeanFactory) {
|
||||
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
|
||||
}
|
||||
else {
|
||||
throw new NoSuchBeanDefinitionException(bd.getParentName(),
|
||||
"Parent name '" + bd.getParentName() + "' is equal to bean name '" + beanName +
|
||||
throw new NoSuchBeanDefinitionException(parentBeanName,
|
||||
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
|
||||
"': cannot be resolved without an AbstractBeanFactory parent");
|
||||
}
|
||||
}
|
||||
@@ -1356,12 +1376,14 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
|
||||
}
|
||||
catch (LinkageError err) {
|
||||
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
|
||||
catch (LinkageError ex) {
|
||||
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch) throws ClassNotFoundException {
|
||||
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
|
||||
throws ClassNotFoundException {
|
||||
|
||||
ClassLoader beanClassLoader = getBeanClassLoader();
|
||||
ClassLoader classLoaderToUse = beanClassLoader;
|
||||
if (!ObjectUtils.isEmpty(typesToMatch)) {
|
||||
@@ -1435,6 +1457,10 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
* @return the type of the bean, or {@code null} if not predictable
|
||||
*/
|
||||
protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
|
||||
Class<?> targetType = mbd.getTargetType();
|
||||
if (targetType != null) {
|
||||
return targetType;
|
||||
}
|
||||
if (mbd.getFactoryMethodName() != null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -162,8 +162,8 @@ abstract class AutowireUtils {
|
||||
* Determine the target type for the generic return type of the given
|
||||
* <em>generic factory method</em>, where formal type variables are declared
|
||||
* on the given method itself.
|
||||
* <p>For example, given a factory method with the following signature,
|
||||
* if {@code resolveReturnTypeForFactoryMethod()} is invoked with the reflected
|
||||
* <p>For example, given a factory method with the following signature, if
|
||||
* {@code resolveReturnTypeForFactoryMethod()} is invoked with the reflected
|
||||
* method for {@code creatProxy()} and an {@code Object[]} array containing
|
||||
* {@code MyService.class}, {@code resolveReturnTypeForFactoryMethod()} will
|
||||
* infer that the target return type is {@code MyService}.
|
||||
@@ -184,9 +184,9 @@ abstract class AutowireUtils {
|
||||
* @param method the method to introspect (never {@code null})
|
||||
* @param args the arguments that will be supplied to the method when it is
|
||||
* invoked (never {@code null})
|
||||
* @param classLoader the ClassLoader to resolve class names against, if necessary
|
||||
* (never {@code null})
|
||||
* @return the resolved target return type, the standard return type, or {@code null}
|
||||
* @param classLoader the ClassLoader to resolve class names against,
|
||||
* if necessary (never {@code null})
|
||||
* @return the resolved target return type or the standard method return type
|
||||
* @since 3.2.5
|
||||
*/
|
||||
public static Class<?> resolveReturnTypeForFactoryMethod(Method method, Object[] args, ClassLoader classLoader) {
|
||||
|
||||
+18
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -69,6 +69,23 @@ public class BeanDefinitionReaderUtils {
|
||||
return bd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a bean name for the given top-level bean definition,
|
||||
* unique within the given bean factory.
|
||||
* @param beanDefinition the bean definition to generate a bean name for
|
||||
* @param registry the bean factory that the definition is going to be
|
||||
* registered with (to check for existing bean names)
|
||||
* @return the generated bean name
|
||||
* @throws BeanDefinitionStoreException if no unique name can be generated
|
||||
* for the given bean definition
|
||||
* @see #generateBeanName(BeanDefinition, BeanDefinitionRegistry, boolean)
|
||||
*/
|
||||
public static String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry registry)
|
||||
throws BeanDefinitionStoreException {
|
||||
|
||||
return generateBeanName(beanDefinition, registry, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a bean name for the given bean definition, unique within the
|
||||
* given bean factory.
|
||||
@@ -117,22 +134,6 @@ public class BeanDefinitionReaderUtils {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a bean name for the given top-level bean definition,
|
||||
* unique within the given bean factory.
|
||||
* @param beanDefinition the bean definition to generate a bean name for
|
||||
* @param registry the bean factory that the definition is going to be
|
||||
* registered with (to check for existing bean names)
|
||||
* @return the generated bean name
|
||||
* @throws BeanDefinitionStoreException if no unique name can be generated
|
||||
* for the given bean definition
|
||||
*/
|
||||
public static String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry registry)
|
||||
throws BeanDefinitionStoreException {
|
||||
|
||||
return generateBeanName(beanDefinition, registry, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the given bean definition with the given bean factory.
|
||||
* @param definitionHolder the bean definition including name and aliases
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -115,7 +115,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
|
||||
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
|
||||
Object instance;
|
||||
if (ctor == null) {
|
||||
instance = BeanUtils.instantiate(subclass);
|
||||
instance = BeanUtils.instantiateClass(subclass);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
|
||||
+9
-8
@@ -609,8 +609,8 @@ class ConstructorResolver {
|
||||
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
|
||||
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
|
||||
|
||||
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
|
||||
this.beanFactory.getCustomTypeConverter() : bw);
|
||||
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
|
||||
TypeConverter converter = (customConverter != null ? customConverter : bw);
|
||||
BeanDefinitionValueResolver valueResolver =
|
||||
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
|
||||
|
||||
@@ -665,8 +665,8 @@ class ConstructorResolver {
|
||||
BeanWrapper bw, Class<?>[] paramTypes, String[] paramNames, Object methodOrCtor,
|
||||
boolean autowiring) throws UnsatisfiedDependencyException {
|
||||
|
||||
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
|
||||
this.beanFactory.getCustomTypeConverter() : bw);
|
||||
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
|
||||
TypeConverter converter = (customConverter != null ? customConverter : bw);
|
||||
|
||||
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
|
||||
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
|
||||
@@ -769,12 +769,13 @@ class ConstructorResolver {
|
||||
private Object[] resolvePreparedArguments(
|
||||
String beanName, RootBeanDefinition mbd, BeanWrapper bw, Member methodOrCtor, Object[] argsToResolve) {
|
||||
|
||||
Class<?>[] paramTypes = (methodOrCtor instanceof Method ?
|
||||
((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes());
|
||||
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
|
||||
this.beanFactory.getCustomTypeConverter() : bw);
|
||||
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
|
||||
TypeConverter converter = (customConverter != null ? customConverter : bw);
|
||||
BeanDefinitionValueResolver valueResolver =
|
||||
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
|
||||
Class<?>[] paramTypes = (methodOrCtor instanceof Method ?
|
||||
((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes());
|
||||
|
||||
Object[] resolvedArgs = new Object[argsToResolve.length];
|
||||
for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
|
||||
Object argValue = argsToResolve[argIndex];
|
||||
|
||||
+239
-128
@@ -32,7 +32,6 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -44,6 +43,7 @@ import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.inject.Provider;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
@@ -52,6 +52,7 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
|
||||
import org.springframework.beans.factory.CannotLoadBeanClassException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InjectionPoint;
|
||||
@@ -61,11 +62,13 @@ import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.SmartFactoryBean;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.config.NamedBeanHolder;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
@@ -264,6 +267,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
/**
|
||||
* Set a {@link java.util.Comparator} for dependency Lists and arrays.
|
||||
* @since 4.0
|
||||
* @see org.springframework.core.OrderComparator
|
||||
* @see org.springframework.core.annotation.AnnotationAwareOrderComparator
|
||||
*/
|
||||
@@ -273,6 +277,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
/**
|
||||
* Return the dependency comparator for this BeanFactory (may be {@code null}.
|
||||
* @since 4.0
|
||||
*/
|
||||
public Comparator<Object> getDependencyComparator() {
|
||||
return this.dependencyComparator;
|
||||
@@ -287,11 +292,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
|
||||
if (autowireCandidateResolver instanceof BeanFactoryAware) {
|
||||
if (System.getSecurityManager() != null) {
|
||||
final BeanFactory target = this;
|
||||
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
@Override
|
||||
public Object run() {
|
||||
((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(target);
|
||||
((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(DefaultListableBeanFactory.this);
|
||||
return null;
|
||||
}
|
||||
}, getAccessControlContext());
|
||||
@@ -318,7 +322,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
DefaultListableBeanFactory otherListableFactory = (DefaultListableBeanFactory) otherFactory;
|
||||
this.allowBeanDefinitionOverriding = otherListableFactory.allowBeanDefinitionOverriding;
|
||||
this.allowEagerClassLoading = otherListableFactory.allowEagerClassLoading;
|
||||
this.autowireCandidateResolver = otherListableFactory.autowireCandidateResolver;
|
||||
this.dependencyComparator = otherListableFactory.dependencyComparator;
|
||||
// A clone of the AutowireCandidateResolver since it is potentially BeanFactoryAware...
|
||||
setAutowireCandidateResolver(BeanUtils.instantiateClass(getAutowireCandidateResolver().getClass()));
|
||||
// Make resolvable dependencies (e.g. ResourceLoader) available here as well...
|
||||
this.resolvableDependencies.putAll(otherListableFactory.resolvableDependencies);
|
||||
}
|
||||
}
|
||||
@@ -335,43 +342,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
@Override
|
||||
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
|
||||
Assert.notNull(requiredType, "Required type must not be null");
|
||||
String[] beanNames = getBeanNamesForType(requiredType);
|
||||
if (beanNames.length > 1) {
|
||||
ArrayList<String> autowireCandidates = new ArrayList<String>();
|
||||
for (String beanName : beanNames) {
|
||||
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
|
||||
autowireCandidates.add(beanName);
|
||||
}
|
||||
}
|
||||
if (autowireCandidates.size() > 0) {
|
||||
beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
|
||||
}
|
||||
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);
|
||||
if (namedBean != null) {
|
||||
return namedBean.getBeanInstance();
|
||||
}
|
||||
if (beanNames.length == 1) {
|
||||
return getBean(beanNames[0], requiredType, args);
|
||||
}
|
||||
else if (beanNames.length > 1) {
|
||||
Map<String, Object> candidates = new HashMap<String, Object>();
|
||||
for (String beanName : beanNames) {
|
||||
candidates.put(beanName, getBean(beanName, requiredType, args));
|
||||
}
|
||||
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
|
||||
if (primaryCandidate != null) {
|
||||
return getBean(primaryCandidate, requiredType, args);
|
||||
}
|
||||
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
|
||||
if (priorityCandidate != null) {
|
||||
return getBean(priorityCandidate, requiredType, args);
|
||||
}
|
||||
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
|
||||
}
|
||||
else if (getParentBeanFactory() != null) {
|
||||
return getParentBeanFactory().getBean(requiredType, args);
|
||||
}
|
||||
else {
|
||||
throw new NoSuchBeanDefinitionException(requiredType);
|
||||
BeanFactory parent = getParentBeanFactory();
|
||||
if (parent != null) {
|
||||
return parent.getBean(requiredType, args);
|
||||
}
|
||||
throw new NoSuchBeanDefinitionException(requiredType);
|
||||
}
|
||||
|
||||
|
||||
@@ -393,7 +372,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
@Override
|
||||
public String[] getBeanDefinitionNames() {
|
||||
if (this.frozenBeanDefinitionNames != null) {
|
||||
return this.frozenBeanDefinitionNames;
|
||||
return this.frozenBeanDefinitionNames.clone();
|
||||
}
|
||||
else {
|
||||
return StringUtils.toStringArray(this.beanDefinitionNames);
|
||||
@@ -444,8 +423,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
|
||||
// In case of FactoryBean, match object created by FactoryBean.
|
||||
boolean isFactoryBean = isFactoryBean(beanName, mbd);
|
||||
boolean matchFound = (allowEagerInit || !isFactoryBean || containsSingleton(beanName)) &&
|
||||
(includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type);
|
||||
boolean matchFound = (allowEagerInit || !isFactoryBean ||
|
||||
(mbd.getDecoratedDefinition() != null && !mbd.isLazyInit()) ||
|
||||
containsSingleton(beanName)) &&
|
||||
(includeNonSingletons || isSingleton(beanName)) &&
|
||||
isTypeMatch(beanName, type);
|
||||
if (!matchFound && isFactoryBean) {
|
||||
// In case of FactoryBean, try to match FactoryBean instance itself next.
|
||||
beanName = FACTORY_BEAN_PREFIX + beanName;
|
||||
@@ -651,13 +633,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
else if (containsSingleton(beanName)) {
|
||||
return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver);
|
||||
}
|
||||
else if (getParentBeanFactory() instanceof DefaultListableBeanFactory) {
|
||||
|
||||
BeanFactory parent = getParentBeanFactory();
|
||||
if (parent instanceof DefaultListableBeanFactory) {
|
||||
// No bean definition found in this factory -> delegate to parent.
|
||||
return ((DefaultListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor, resolver);
|
||||
return ((DefaultListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor, resolver);
|
||||
}
|
||||
else if (getParentBeanFactory() instanceof ConfigurableListableBeanFactory) {
|
||||
else if (parent instanceof ConfigurableListableBeanFactory) {
|
||||
// If no DefaultListableBeanFactory, can't pass the resolver along.
|
||||
return ((ConfigurableListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor);
|
||||
return ((ConfigurableListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor);
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
@@ -998,24 +982,86 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, String beanName,
|
||||
public <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException {
|
||||
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, (Object[]) null);
|
||||
if (namedBean != null) {
|
||||
return namedBean;
|
||||
}
|
||||
BeanFactory parent = getParentBeanFactory();
|
||||
if (parent instanceof AutowireCapableBeanFactory) {
|
||||
return ((AutowireCapableBeanFactory) parent).resolveNamedBean(requiredType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType, Object... args) throws BeansException {
|
||||
Assert.notNull(requiredType, "Required type must not be null");
|
||||
String[] candidateNames = getBeanNamesForType(requiredType);
|
||||
|
||||
if (candidateNames.length > 1) {
|
||||
List<String> autowireCandidates = new ArrayList<String>(candidateNames.length);
|
||||
for (String beanName : candidateNames) {
|
||||
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
|
||||
autowireCandidates.add(beanName);
|
||||
}
|
||||
}
|
||||
if (!autowireCandidates.isEmpty()) {
|
||||
candidateNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
if (candidateNames.length == 1) {
|
||||
String beanName = candidateNames[0];
|
||||
return new NamedBeanHolder<T>(beanName, getBean(beanName, requiredType, args));
|
||||
}
|
||||
else if (candidateNames.length > 1) {
|
||||
Map<String, Object> candidates = new LinkedHashMap<String, Object>(candidateNames.length);
|
||||
for (String beanName : candidateNames) {
|
||||
if (containsSingleton(beanName)) {
|
||||
candidates.put(beanName, getBean(beanName, requiredType, args));
|
||||
}
|
||||
else {
|
||||
candidates.put(beanName, getType(beanName));
|
||||
}
|
||||
}
|
||||
String candidateName = determinePrimaryCandidate(candidates, requiredType);
|
||||
if (candidateName == null) {
|
||||
candidateName = determineHighestPriorityCandidate(candidates, requiredType);
|
||||
}
|
||||
if (candidateName != null) {
|
||||
Object beanInstance = candidates.get(candidateName);
|
||||
if (beanInstance instanceof Class) {
|
||||
beanInstance = getBean(candidateName, requiredType, args);
|
||||
}
|
||||
return new NamedBeanHolder<T>(candidateName, (T) beanInstance);
|
||||
}
|
||||
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
|
||||
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
|
||||
|
||||
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
|
||||
if (descriptor.getDependencyType().equals(javaUtilOptionalClass)) {
|
||||
return new OptionalDependencyFactory().createOptionalDependency(descriptor, beanName);
|
||||
if (javaUtilOptionalClass == descriptor.getDependencyType()) {
|
||||
return new OptionalDependencyFactory().createOptionalDependency(descriptor, requestingBeanName);
|
||||
}
|
||||
else if (ObjectFactory.class == descriptor.getDependencyType() ||
|
||||
ObjectProvider.class == descriptor.getDependencyType()) {
|
||||
return new DependencyObjectProvider(descriptor, beanName);
|
||||
return new DependencyObjectProvider(descriptor, requestingBeanName);
|
||||
}
|
||||
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
|
||||
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, beanName);
|
||||
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
|
||||
}
|
||||
else {
|
||||
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, beanName);
|
||||
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
|
||||
descriptor, requestingBeanName);
|
||||
if (result == null) {
|
||||
result = doResolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter);
|
||||
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1053,13 +1099,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
|
||||
if (matchingBeans.isEmpty()) {
|
||||
if (descriptor.isRequired()) {
|
||||
raiseNoSuchBeanDefinitionException(type, descriptor.getResolvableType().toString(), descriptor);
|
||||
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String autowiredBeanName;
|
||||
Object instanceCandidate;
|
||||
|
||||
if (matchingBeans.size() > 1) {
|
||||
String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor);
|
||||
if (primaryBeanName == null) {
|
||||
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
|
||||
if (autowiredBeanName == null) {
|
||||
if (descriptor.isRequired() || !indicatesMultipleBeans(type)) {
|
||||
return descriptor.resolveNotUnique(type, matchingBeans);
|
||||
}
|
||||
@@ -1070,17 +1120,20 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (autowiredBeanNames != null) {
|
||||
autowiredBeanNames.add(primaryBeanName);
|
||||
}
|
||||
return matchingBeans.get(primaryBeanName);
|
||||
instanceCandidate = matchingBeans.get(autowiredBeanName);
|
||||
}
|
||||
// We have exactly one match.
|
||||
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
|
||||
else {
|
||||
// We have exactly one match.
|
||||
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
|
||||
autowiredBeanName = entry.getKey();
|
||||
instanceCandidate = entry.getValue();
|
||||
}
|
||||
|
||||
if (autowiredBeanNames != null) {
|
||||
autowiredBeanNames.add(entry.getKey());
|
||||
autowiredBeanNames.add(autowiredBeanName);
|
||||
}
|
||||
return entry.getValue();
|
||||
return (instanceCandidate instanceof Class ?
|
||||
descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
|
||||
}
|
||||
finally {
|
||||
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
|
||||
@@ -1093,9 +1146,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
Class<?> type = descriptor.getDependencyType();
|
||||
if (type.isArray()) {
|
||||
Class<?> componentType = type.getComponentType();
|
||||
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
|
||||
targetDesc.increaseNestingLevel();
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, targetDesc);
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
|
||||
new MultiElementDescriptor(descriptor));
|
||||
if (matchingBeans.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -1114,9 +1166,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (elementType == null) {
|
||||
return null;
|
||||
}
|
||||
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
|
||||
targetDesc.increaseNestingLevel();
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, targetDesc);
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
|
||||
new MultiElementDescriptor(descriptor));
|
||||
if (matchingBeans.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -1139,9 +1190,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (valueType == null) {
|
||||
return null;
|
||||
}
|
||||
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
|
||||
targetDesc.increaseNestingLevel();
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, targetDesc);
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
|
||||
new MultiElementDescriptor(descriptor));
|
||||
if (matchingBeans.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -1208,24 +1258,27 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String candidateName : candidateNames) {
|
||||
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {
|
||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
|
||||
for (String candidate : candidateNames) {
|
||||
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
|
||||
addCandidateEntry(result, candidate, descriptor, requiredType);
|
||||
}
|
||||
}
|
||||
if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
|
||||
// Consider fallback matches if the first pass failed to find anything...
|
||||
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
|
||||
for (String candidateName : candidateNames) {
|
||||
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
|
||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
|
||||
for (String candidate : candidateNames) {
|
||||
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {
|
||||
addCandidateEntry(result, candidate, descriptor, requiredType);
|
||||
}
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
// Consider self references before as a final pass
|
||||
for (String candidateName : candidateNames) {
|
||||
if (isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
|
||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
|
||||
// Consider self references as a final pass...
|
||||
// but in the case of a dependency collection, not the very same bean itself.
|
||||
for (String candidate : candidateNames) {
|
||||
if (isSelfReference(beanName, candidate) &&
|
||||
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
|
||||
isAutowireCandidate(candidate, fallbackDescriptor)) {
|
||||
addCandidateEntry(result, candidate, descriptor, requiredType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1233,31 +1286,46 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an entry to the candidate map: a bean instance if available or just the resolved
|
||||
* type, preventing early bean initialization ahead of primary candidate selection.
|
||||
*/
|
||||
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
|
||||
DependencyDescriptor descriptor, Class<?> requiredType) {
|
||||
|
||||
if (descriptor instanceof MultiElementDescriptor || containsSingleton(candidateName)) {
|
||||
candidates.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
|
||||
}
|
||||
else {
|
||||
candidates.put(candidateName, getType(candidateName));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the autowire candidate in the given set of beans.
|
||||
* <p>Looks for {@code @Primary} and {@code @Priority} (in that order).
|
||||
* @param candidateBeans a Map of candidate names and candidate instances
|
||||
* @param candidates a Map of candidate names and candidate instances
|
||||
* that match the required type, as returned by {@link #findAutowireCandidates}
|
||||
* @param descriptor the target dependency to match against
|
||||
* @return the name of the autowire candidate, or {@code null} if none found
|
||||
*/
|
||||
protected String determineAutowireCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) {
|
||||
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
|
||||
Class<?> requiredType = descriptor.getDependencyType();
|
||||
String primaryCandidate = determinePrimaryCandidate(candidateBeans, requiredType);
|
||||
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
|
||||
if (primaryCandidate != null) {
|
||||
return primaryCandidate;
|
||||
}
|
||||
String priorityCandidate = determineHighestPriorityCandidate(candidateBeans, requiredType);
|
||||
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
|
||||
if (priorityCandidate != null) {
|
||||
return priorityCandidate;
|
||||
}
|
||||
// Fallback
|
||||
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
|
||||
String candidateBeanName = entry.getKey();
|
||||
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
|
||||
String candidateName = entry.getKey();
|
||||
Object beanInstance = entry.getValue();
|
||||
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
|
||||
matchesBeanName(candidateBeanName, descriptor.getDependencyName())) {
|
||||
return candidateBeanName;
|
||||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
|
||||
return candidateName;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -1265,15 +1333,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
/**
|
||||
* Determine the primary candidate in the given set of beans.
|
||||
* @param candidateBeans a Map of candidate names and candidate instances
|
||||
* that match the required type
|
||||
* @param candidates a Map of candidate names and candidate instances
|
||||
* (or candidate classes if not created yet) that match the required type
|
||||
* @param requiredType the target dependency type to match against
|
||||
* @return the name of the primary candidate, or {@code null} if none found
|
||||
* @see #isPrimary(String, Object)
|
||||
*/
|
||||
protected String determinePrimaryCandidate(Map<String, Object> candidateBeans, Class<?> requiredType) {
|
||||
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
|
||||
String primaryBeanName = null;
|
||||
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
|
||||
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
|
||||
String candidateBeanName = entry.getKey();
|
||||
Object beanInstance = entry.getValue();
|
||||
if (isPrimary(candidateBeanName, beanInstance)) {
|
||||
@@ -1281,8 +1349,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
|
||||
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
|
||||
if (candidateLocal && primaryLocal) {
|
||||
throw new NoUniqueBeanDefinitionException(requiredType, candidateBeans.size(),
|
||||
"more than one 'primary' bean found among candidates: " + candidateBeans.keySet());
|
||||
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
|
||||
"more than one 'primary' bean found among candidates: " + candidates.keySet());
|
||||
}
|
||||
else if (candidateLocal) {
|
||||
primaryBeanName = candidateBeanName;
|
||||
@@ -1297,29 +1365,30 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the candidate with the highest priority in the given set of beans. As
|
||||
* defined by the {@link org.springframework.core.Ordered} interface, the lowest
|
||||
* value has the highest priority.
|
||||
* @param candidateBeans a Map of candidate names and candidate instances
|
||||
* that match the required type
|
||||
* Determine the candidate with the highest priority in the given set of beans.
|
||||
* <p>Based on {@code @javax.annotation.Priority}. As defined by the related
|
||||
* {@link org.springframework.core.Ordered} interface, the lowest value has
|
||||
* the highest priority.
|
||||
* @param candidates a Map of candidate names and candidate instances
|
||||
* (or candidate classes if not created yet) that match the required type
|
||||
* @param requiredType the target dependency type to match against
|
||||
* @return the name of the candidate with the highest priority,
|
||||
* or {@code null} if none found
|
||||
* @see #getPriority(Object)
|
||||
*/
|
||||
protected String determineHighestPriorityCandidate(Map<String, Object> candidateBeans, Class<?> requiredType) {
|
||||
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
|
||||
String highestPriorityBeanName = null;
|
||||
Integer highestPriority = null;
|
||||
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
|
||||
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
|
||||
String candidateBeanName = entry.getKey();
|
||||
Object beanInstance = entry.getValue();
|
||||
Integer candidatePriority = getPriority(beanInstance);
|
||||
if (candidatePriority != null) {
|
||||
if (highestPriorityBeanName != null) {
|
||||
if (candidatePriority.equals(highestPriority)) {
|
||||
throw new NoUniqueBeanDefinitionException(requiredType, candidateBeans.size(),
|
||||
"Multiple beans found with the same priority ('" + highestPriority + "') " +
|
||||
"among candidates: " + candidateBeans.keySet());
|
||||
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
|
||||
"Multiple beans found with the same priority ('" + highestPriority +
|
||||
"') among candidates: " + candidates.keySet());
|
||||
}
|
||||
else if (candidatePriority < highestPriority) {
|
||||
highestPriorityBeanName = candidateBeanName;
|
||||
@@ -1346,9 +1415,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (containsBeanDefinition(beanName)) {
|
||||
return getMergedLocalBeanDefinition(beanName).isPrimary();
|
||||
}
|
||||
BeanFactory parentFactory = getParentBeanFactory();
|
||||
return (parentFactory instanceof DefaultListableBeanFactory &&
|
||||
((DefaultListableBeanFactory) parentFactory).isPrimary(beanName, beanInstance));
|
||||
BeanFactory parent = getParentBeanFactory();
|
||||
return (parent instanceof DefaultListableBeanFactory &&
|
||||
((DefaultListableBeanFactory) parent).isPrimary(beanName, beanInstance));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1392,17 +1461,44 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
|
||||
/**
|
||||
* Raise a NoSuchBeanDefinitionException for an unresolvable dependency.
|
||||
* Raise a NoSuchBeanDefinitionException or BeanNotOfRequiredTypeException
|
||||
* for an unresolvable dependency.
|
||||
*/
|
||||
private void raiseNoSuchBeanDefinitionException(
|
||||
Class<?> type, String dependencyDescription, DependencyDescriptor descriptor)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
private void raiseNoMatchingBeanFound(
|
||||
Class<?> type, ResolvableType resolvableType, DependencyDescriptor descriptor) throws BeansException {
|
||||
|
||||
throw new NoSuchBeanDefinitionException(type, dependencyDescription,
|
||||
"expected at least 1 bean which qualifies as autowire candidate for this dependency. " +
|
||||
checkBeanNotOfRequiredType(type, descriptor);
|
||||
|
||||
throw new NoSuchBeanDefinitionException(resolvableType,
|
||||
"expected at least 1 bean which qualifies as autowire candidate. " +
|
||||
"Dependency annotations: " + ObjectUtils.nullSafeToString(descriptor.getAnnotations()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Raise a BeanNotOfRequiredTypeException for an unresolvable dependency, if applicable,
|
||||
* i.e. if the target type of the bean would match but an exposed proxy doesn't.
|
||||
*/
|
||||
private void checkBeanNotOfRequiredType(Class<?> type, DependencyDescriptor descriptor) {
|
||||
for (String beanName : this.beanDefinitionNames) {
|
||||
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
|
||||
Class<?> targetType = mbd.getTargetType();
|
||||
if (targetType != null && type.isAssignableFrom(targetType) &&
|
||||
isAutowireCandidate(beanName, mbd, descriptor, getAutowireCandidateResolver())) {
|
||||
// Probably a proxy interfering with target type match -> throw meaningful exception.
|
||||
Object beanInstance = getSingleton(beanName, false);
|
||||
Class<?> beanType = (beanInstance != null ? beanInstance.getClass() : predictBeanType(beanName, mbd));
|
||||
if (!type.isAssignableFrom((beanType))) {
|
||||
throw new BeanNotOfRequiredTypeException(beanName, type, beanType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BeanFactory parent = getParentBeanFactory();
|
||||
if (parent instanceof DefaultListableBeanFactory) {
|
||||
((DefaultListableBeanFactory) parent).checkBeanNotOfRequiredType(type, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@@ -1473,18 +1569,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
private class OptionalDependencyFactory {
|
||||
|
||||
public Object createOptionalDependency(DependencyDescriptor descriptor, String beanName, final Object... args) {
|
||||
DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
|
||||
DependencyDescriptor descriptorToUse = new NestedDependencyDescriptor(descriptor) {
|
||||
@Override
|
||||
public boolean isRequired() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
|
||||
return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, args) :
|
||||
super.resolveCandidate(beanName, beanFactory));
|
||||
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
|
||||
return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, requiredType, args) :
|
||||
super.resolveCandidate(beanName, requiredType, beanFactory));
|
||||
}
|
||||
};
|
||||
descriptorToUse.increaseNestingLevel();
|
||||
return Optional.ofNullable(doResolveDependency(descriptorToUse, beanName, null, null));
|
||||
}
|
||||
}
|
||||
@@ -1502,9 +1597,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
private final String beanName;
|
||||
|
||||
public DependencyObjectProvider(DependencyDescriptor descriptor, String beanName) {
|
||||
this.descriptor = new DependencyDescriptor(descriptor);
|
||||
this.descriptor.increaseNestingLevel();
|
||||
this.optional = this.descriptor.getDependencyType().equals(javaUtilOptionalClass);
|
||||
this.descriptor = new NestedDependencyDescriptor(descriptor);
|
||||
this.optional = (this.descriptor.getDependencyType() == javaUtilOptionalClass);
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
@@ -1526,8 +1620,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
else {
|
||||
DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
|
||||
@Override
|
||||
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
|
||||
return beanFactory.getBean(beanName, args);
|
||||
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
|
||||
return ((AbstractBeanFactory) beanFactory).getBean(beanName, requiredType, args);
|
||||
}
|
||||
};
|
||||
return doResolveDependency(descriptorToUse, this.beanName, null, null);
|
||||
@@ -1620,13 +1714,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (beanDefinition == null) {
|
||||
return null;
|
||||
}
|
||||
List<Object> sources = new ArrayList<Object>();
|
||||
List<Object> sources = new ArrayList<Object>(2);
|
||||
Method factoryMethod = beanDefinition.getResolvedFactoryMethod();
|
||||
if (factoryMethod != null) {
|
||||
sources.add(factoryMethod);
|
||||
}
|
||||
Class<?> targetType = beanDefinition.getTargetType();
|
||||
if (targetType != null && !targetType.equals(obj.getClass())) {
|
||||
if (targetType != null && targetType != obj.getClass()) {
|
||||
sources.add(targetType);
|
||||
}
|
||||
return sources.toArray(new Object[sources.size()]);
|
||||
@@ -1643,4 +1737,21 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class NestedDependencyDescriptor extends DependencyDescriptor {
|
||||
|
||||
public NestedDependencyDescriptor(DependencyDescriptor original) {
|
||||
super(original);
|
||||
increaseNestingLevel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MultiElementDescriptor extends NestedDependencyDescriptor {
|
||||
|
||||
public MultiElementDescriptor(DependencyDescriptor original) {
|
||||
super(original);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -214,7 +214,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
if (singletonObject == null) {
|
||||
if (this.singletonsCurrentlyInDestruction) {
|
||||
throw new BeanCreationNotAllowedException(beanName,
|
||||
"Singleton bean creation not allowed while the singletons of this factory are in destruction " +
|
||||
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
|
||||
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -449,10 +449,10 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
}
|
||||
|
||||
private boolean isDependent(String beanName, String dependentBeanName, Set<String> alreadySeen) {
|
||||
String canonicalName = canonicalName(beanName);
|
||||
if (alreadySeen != null && alreadySeen.contains(beanName)) {
|
||||
return false;
|
||||
}
|
||||
String canonicalName = canonicalName(beanName);
|
||||
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
|
||||
if (dependentBeans == null) {
|
||||
return false;
|
||||
|
||||
+39
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -74,21 +74,31 @@ public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandid
|
||||
// No generic type -> we know it's a Class type-match, so no need to check again.
|
||||
return true;
|
||||
}
|
||||
|
||||
ResolvableType targetType = null;
|
||||
boolean cacheType = false;
|
||||
RootBeanDefinition rbd = null;
|
||||
if (bdHolder.getBeanDefinition() instanceof RootBeanDefinition) {
|
||||
rbd = (RootBeanDefinition) bdHolder.getBeanDefinition();
|
||||
}
|
||||
if (rbd != null) {
|
||||
// First, check factory method return type, if applicable
|
||||
targetType = getReturnTypeForFactoryMethod(rbd, descriptor);
|
||||
targetType = rbd.targetType;
|
||||
if (targetType == null) {
|
||||
RootBeanDefinition dbd = getResolvedDecoratedDefinition(rbd);
|
||||
if (dbd != null) {
|
||||
targetType = getReturnTypeForFactoryMethod(dbd, descriptor);
|
||||
cacheType = true;
|
||||
// First, check factory method return type, if applicable
|
||||
targetType = getReturnTypeForFactoryMethod(rbd, descriptor);
|
||||
if (targetType == null) {
|
||||
RootBeanDefinition dbd = getResolvedDecoratedDefinition(rbd);
|
||||
if (dbd != null) {
|
||||
targetType = dbd.targetType;
|
||||
if (targetType == null) {
|
||||
targetType = getReturnTypeForFactoryMethod(dbd, descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (targetType == null) {
|
||||
// Regular case: straight bean instance, with BeanFactory available.
|
||||
if (this.beanFactory != null) {
|
||||
@@ -106,7 +116,14 @@ public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandid
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetType == null || (descriptor.fallbackMatchAllowed() && targetType.hasUnresolvableGenerics())) {
|
||||
|
||||
if (targetType == null) {
|
||||
return true;
|
||||
}
|
||||
if (cacheType) {
|
||||
rbd.targetType = targetType;
|
||||
}
|
||||
if (descriptor.fallbackMatchAllowed() && targetType.hasUnresolvableGenerics()) {
|
||||
return true;
|
||||
}
|
||||
// Full check for complex generic type match...
|
||||
@@ -130,22 +147,23 @@ public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandid
|
||||
protected ResolvableType getReturnTypeForFactoryMethod(RootBeanDefinition rbd, DependencyDescriptor descriptor) {
|
||||
// Should typically be set for any kind of factory method, since the BeanFactory
|
||||
// pre-resolves them before reaching out to the AutowireCandidateResolver...
|
||||
Class<?> preResolved = rbd.resolvedFactoryMethodReturnType;
|
||||
if (preResolved != null) {
|
||||
return ResolvableType.forClass(preResolved);
|
||||
}
|
||||
else {
|
||||
Method resolvedFactoryMethod = rbd.getResolvedFactoryMethod();
|
||||
if (resolvedFactoryMethod != null) {
|
||||
if (descriptor.getDependencyType().isAssignableFrom(resolvedFactoryMethod.getReturnType())) {
|
||||
// Only use factory method metadata if the return type is actually expressive enough
|
||||
// for our dependency. Otherwise, the returned instance type may have matched instead
|
||||
// in case of a singleton instance having been registered with the container already.
|
||||
return ResolvableType.forMethodReturnType(resolvedFactoryMethod);
|
||||
}
|
||||
ResolvableType returnType = rbd.factoryMethodReturnType;
|
||||
if (returnType == null) {
|
||||
Method factoryMethod = rbd.getResolvedFactoryMethod();
|
||||
if (factoryMethod != null) {
|
||||
returnType = ResolvableType.forMethodReturnType(factoryMethod);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (returnType != null) {
|
||||
Class<?> resolvedClass = returnType.resolve();
|
||||
if (resolvedClass != null && descriptor.getDependencyType().isAssignableFrom(resolvedClass)) {
|
||||
// Only use factory method metadata if the return type is actually expressive enough
|
||||
// for our dependency. Otherwise, the returned instance type may have matched instead
|
||||
// in case of a singleton instance having been registered with the container already.
|
||||
return returnType;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+55
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
@@ -25,6 +26,7 @@ import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -48,22 +50,28 @@ import org.springframework.util.Assert;
|
||||
@SuppressWarnings("serial")
|
||||
public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
|
||||
boolean allowCaching = true;
|
||||
|
||||
private BeanDefinitionHolder decoratedDefinition;
|
||||
|
||||
private volatile Class<?> targetType;
|
||||
private AnnotatedElement qualifiedElement;
|
||||
|
||||
boolean allowCaching = true;
|
||||
|
||||
boolean isFactoryMethodUnique = false;
|
||||
|
||||
volatile ResolvableType targetType;
|
||||
|
||||
/** Package-visible field for caching the determined Class of a given bean definition */
|
||||
volatile Class<?> resolvedTargetType;
|
||||
|
||||
/** Package-visible field for caching the return type of a generically typed factory method */
|
||||
volatile ResolvableType factoryMethodReturnType;
|
||||
|
||||
/** Common lock for the four constructor fields below */
|
||||
final Object constructorArgumentLock = new Object();
|
||||
|
||||
/** Package-visible field for caching the resolved constructor or factory method */
|
||||
Object resolvedConstructorOrFactoryMethod;
|
||||
|
||||
/** Package-visible field for caching the return type of a generically typed factory method */
|
||||
volatile Class<?> resolvedFactoryMethodReturnType;
|
||||
|
||||
/** Package-visible field that marks the constructor arguments as resolved */
|
||||
boolean constructorArgumentsResolved = false;
|
||||
|
||||
@@ -73,6 +81,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
/** Package-visible field for caching partly prepared constructor arguments */
|
||||
Object[] preparedConstructorArguments;
|
||||
|
||||
/** Common lock for the two post-processing fields below */
|
||||
final Object postProcessingLock = new Object();
|
||||
|
||||
/** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied */
|
||||
@@ -125,7 +134,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
setBeanClass(beanClass);
|
||||
setAutowireMode(autowireMode);
|
||||
if (dependencyCheck && getResolvedAutowireMode() != AUTOWIRE_CONSTRUCTOR) {
|
||||
setDependencyCheck(RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
|
||||
setDependencyCheck(DEPENDENCY_CHECK_OBJECTS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,10 +180,11 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
*/
|
||||
public RootBeanDefinition(RootBeanDefinition original) {
|
||||
super(original);
|
||||
this.allowCaching = original.allowCaching;
|
||||
this.decoratedDefinition = original.decoratedDefinition;
|
||||
this.targetType = original.targetType;
|
||||
this.qualifiedElement = original.qualifiedElement;
|
||||
this.allowCaching = original.allowCaching;
|
||||
this.isFactoryMethodUnique = original.isFactoryMethodUnique;
|
||||
this.targetType = original.targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,19 +223,52 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
return this.decoratedDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the {@link AnnotatedElement} defining qualifiers,
|
||||
* to be used instead of the target class or factory method.
|
||||
* @since 4.3.3
|
||||
* @see #setTargetType(ResolvableType)
|
||||
* @see #getResolvedFactoryMethod()
|
||||
*/
|
||||
public void setQualifiedElement(AnnotatedElement qualifiedElement) {
|
||||
this.qualifiedElement = qualifiedElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link AnnotatedElement} defining qualifiers, if any.
|
||||
* Otherwise, the factory method and target class will be checked.
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public AnnotatedElement getQualifiedElement() {
|
||||
return this.qualifiedElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a generics-containing target type of this bean definition, if known in advance.
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public void setTargetType(ResolvableType targetType) {
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the target type of this bean definition, if known in advance.
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public void setTargetType(Class<?> targetType) {
|
||||
this.targetType = targetType;
|
||||
this.targetType = (targetType != null ? ResolvableType.forClass(targetType) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the target type of this bean definition, if known
|
||||
* (either specified in advance or resolved on first instantiation).
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public Class<?> getTargetType() {
|
||||
return this.targetType;
|
||||
if (this.resolvedTargetType != null) {
|
||||
return this.resolvedTargetType;
|
||||
}
|
||||
return (this.targetType != null ? this.targetType.resolve() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
||||
}
|
||||
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -248,7 +248,13 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
|
||||
|
||||
@Override
|
||||
public String[] getBeanNamesForType(ResolvableType type) {
|
||||
boolean isFactoryType = (type != null && FactoryBean.class.isAssignableFrom(type.getRawClass()));
|
||||
boolean isFactoryType = false;
|
||||
if (type != null) {
|
||||
Class<?> resolved = type.resolve();
|
||||
if (resolved != null && FactoryBean.class.isAssignableFrom(resolved)) {
|
||||
isFactoryType = true;
|
||||
}
|
||||
}
|
||||
List<String> matches = new ArrayList<String>();
|
||||
for (Map.Entry<String, Object> entry : this.beans.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -200,6 +200,7 @@ public class UtilNamespaceHandler extends NamespaceHandlerSupport {
|
||||
|
||||
String location = element.getAttribute("location");
|
||||
if (StringUtils.hasLength(location)) {
|
||||
location = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(location);
|
||||
String[] locations = StringUtils.commaDelimitedListToStringArray(location);
|
||||
builder.addPropertyValue("locations", locations);
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -154,9 +154,9 @@ public class CustomCollectionEditor extends PropertyEditorSupport {
|
||||
try {
|
||||
return collectionType.newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not instantiate collection class [" + collectionType.getName() + "]: " + ex.getMessage());
|
||||
"Could not instantiate collection class: " + collectionType.getName(), ex);
|
||||
}
|
||||
}
|
||||
else if (List.class == collectionType) {
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -132,9 +132,9 @@ public class CustomMapEditor extends PropertyEditorSupport {
|
||||
try {
|
||||
return mapType.newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not instantiate map class [" + mapType.getName() + "]: " + ex.getMessage());
|
||||
"Could not instantiate map class: " + mapType.getName(), ex);
|
||||
}
|
||||
}
|
||||
else if (SortedMap.class == mapType) {
|
||||
|
||||
+9
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -59,16 +59,14 @@ public class FileEditor extends PropertyEditorSupport {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new FileEditor,
|
||||
* using the default ResourceEditor underneath.
|
||||
* Create a new FileEditor, using a default ResourceEditor underneath.
|
||||
*/
|
||||
public FileEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new FileEditor,
|
||||
* using the given ResourceEditor underneath.
|
||||
* Create a new FileEditor, using the given ResourceEditor underneath.
|
||||
* @param resourceEditor the ResourceEditor to use
|
||||
*/
|
||||
public FileEditor(ResourceEditor resourceEditor) {
|
||||
@@ -86,8 +84,9 @@ public class FileEditor extends PropertyEditorSupport {
|
||||
|
||||
// Check whether we got an absolute file path without "file:" prefix.
|
||||
// For backwards compatibility, we'll consider those as straight file path.
|
||||
File file = null;
|
||||
if (!ResourceUtils.isUrl(text)) {
|
||||
File file = new File(text);
|
||||
file = new File(text);
|
||||
if (file.isAbsolute()) {
|
||||
setValue(file);
|
||||
return;
|
||||
@@ -99,18 +98,18 @@ public class FileEditor extends PropertyEditorSupport {
|
||||
Resource resource = (Resource) this.resourceEditor.getValue();
|
||||
|
||||
// If it's a URL or a path pointing to an existing resource, use it as-is.
|
||||
if (ResourceUtils.isUrl(text) || resource.exists()) {
|
||||
if (file == null || resource.exists()) {
|
||||
try {
|
||||
setValue(resource.getFile());
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not retrieve File for " + resource + ": " + ex.getMessage());
|
||||
"Could not retrieve file for " + resource + ": " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Create a relative File reference and hope for the best.
|
||||
setValue(new File(text));
|
||||
// Set a relative File reference and hope for the best.
|
||||
setValue(file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,16 +47,14 @@ public class InputStreamEditor extends PropertyEditorSupport {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new InputStreamEditor,
|
||||
* using the default ResourceEditor underneath.
|
||||
* Create a new InputStreamEditor, using the default ResourceEditor underneath.
|
||||
*/
|
||||
public InputStreamEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new InputStreamEditor,
|
||||
* using the given ResourceEditor underneath.
|
||||
* Create a new InputStreamEditor, using the given ResourceEditor underneath.
|
||||
* @param resourceEditor the ResourceEditor to use
|
||||
*/
|
||||
public InputStreamEditor(ResourceEditor resourceEditor) {
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://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.beans.propertyeditors;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.FileSystemNotFoundException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceEditor;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.lang.UsesJava7;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Editor for {@code java.nio.file.Path}, to directly populate a Path
|
||||
* property instead of using a String property as bridge.
|
||||
*
|
||||
* <p>Based on {@link Paths#get(URI)}'s resolution algorithm, checking
|
||||
* registered NIO file system providers, including the default file system
|
||||
* for "file:..." paths. Also supports Spring-style URL notation: any fully
|
||||
* qualified standard URL and Spring's special "classpath:" pseudo-URL, as
|
||||
* well as Spring's context-specific relative file paths. As a fallback, a
|
||||
* path will be resolved in the file system via {@code Paths#get(String)}
|
||||
* if no existing context-relative resource could be found.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.3.2
|
||||
* @see java.nio.file.Path
|
||||
* @see Paths#get(URI)
|
||||
* @see ResourceEditor
|
||||
* @see org.springframework.core.io.ResourceLoader
|
||||
* @see FileEditor
|
||||
* @see URLEditor
|
||||
*/
|
||||
@UsesJava7
|
||||
public class PathEditor extends PropertyEditorSupport {
|
||||
|
||||
private final ResourceEditor resourceEditor;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new PathEditor, using the default ResourceEditor underneath.
|
||||
*/
|
||||
public PathEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PathEditor, using the given ResourceEditor underneath.
|
||||
* @param resourceEditor the ResourceEditor to use
|
||||
*/
|
||||
public PathEditor(ResourceEditor resourceEditor) {
|
||||
Assert.notNull(resourceEditor, "ResourceEditor must not be null");
|
||||
this.resourceEditor = resourceEditor;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
boolean nioPathCandidate = !text.startsWith(ResourceLoader.CLASSPATH_URL_PREFIX);
|
||||
if (nioPathCandidate && !text.startsWith("/")) {
|
||||
try {
|
||||
URI uri = new URI(text);
|
||||
if (uri.getScheme() != null) {
|
||||
nioPathCandidate = false;
|
||||
// Let's try NIO file system providers via Paths.get(URI)
|
||||
setValue(Paths.get(uri).normalize());
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (URISyntaxException ex) {
|
||||
// Not a valid URI: Let's try as Spring resource location.
|
||||
}
|
||||
catch (FileSystemNotFoundException ex) {
|
||||
// URI scheme not registered for NIO:
|
||||
// Let's try URL protocol handlers via Spring's resource mechanism.
|
||||
}
|
||||
}
|
||||
|
||||
this.resourceEditor.setAsText(text);
|
||||
Resource resource = (Resource) this.resourceEditor.getValue();
|
||||
if (resource == null) {
|
||||
setValue(null);
|
||||
}
|
||||
else if (!resource.exists() && nioPathCandidate) {
|
||||
setValue(Paths.get(text).normalize());
|
||||
}
|
||||
else {
|
||||
try {
|
||||
setValue(resource.getFile().toPath());
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalArgumentException("Failed to retrieve file for " + resource, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsText() {
|
||||
Path value = (Path) getValue();
|
||||
return (value != null ? value.toString() : "");
|
||||
}
|
||||
|
||||
}
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,16 +47,14 @@ public class ReaderEditor extends PropertyEditorSupport {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ReaderEditor,
|
||||
* using the default ResourceEditor underneath.
|
||||
* Create a new ReaderEditor, using the default ResourceEditor underneath.
|
||||
*/
|
||||
public ReaderEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ReaderEditor,
|
||||
* using the given ResourceEditor underneath.
|
||||
* Create a new ReaderEditor, using the given ResourceEditor underneath.
|
||||
* @param resourceEditor the ResourceEditor to use
|
||||
*/
|
||||
public ReaderEditor(ResourceEditor resourceEditor) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -60,8 +60,7 @@ public class URIEditor extends PropertyEditorSupport {
|
||||
* standard URIs (not trying to resolve them into physical resources).
|
||||
*/
|
||||
public URIEditor() {
|
||||
this.classLoader = null;
|
||||
this.encode = true;
|
||||
this(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,7 +73,6 @@ public class URIEditor extends PropertyEditorSupport {
|
||||
this.encode = encode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new URIEditor, using the given ClassLoader to resolve
|
||||
* "classpath:" locations into physical resource URLs.
|
||||
@@ -82,8 +80,7 @@ public class URIEditor extends PropertyEditorSupport {
|
||||
* (may be {@code null} to indicate the default ClassLoader)
|
||||
*/
|
||||
public URIEditor(ClassLoader classLoader) {
|
||||
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
|
||||
this.encode = true;
|
||||
this(classLoader, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,7 +50,7 @@ public class URLEditor extends PropertyEditorSupport {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new URLEditor, using the default ResourceEditor underneath.
|
||||
* Create a new URLEditor, using a default ResourceEditor underneath.
|
||||
*/
|
||||
public URLEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
|
||||
+19
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,6 +33,7 @@ import org.springframework.beans.propertyeditors.ClassEditor;
|
||||
import org.springframework.beans.propertyeditors.FileEditor;
|
||||
import org.springframework.beans.propertyeditors.InputSourceEditor;
|
||||
import org.springframework.beans.propertyeditors.InputStreamEditor;
|
||||
import org.springframework.beans.propertyeditors.PathEditor;
|
||||
import org.springframework.beans.propertyeditors.ReaderEditor;
|
||||
import org.springframework.beans.propertyeditors.URIEditor;
|
||||
import org.springframework.beans.propertyeditors.URLEditor;
|
||||
@@ -43,6 +44,7 @@ import org.springframework.core.io.ResourceEditor;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.ResourceArrayPropertyEditor;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* PropertyEditorRegistrar implementation that populates a given
|
||||
@@ -58,6 +60,19 @@ import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
*/
|
||||
public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
|
||||
|
||||
private static Class<?> pathClass;
|
||||
|
||||
static {
|
||||
try {
|
||||
pathClass = ClassUtils.forName("java.nio.file.Path", ResourceEditorRegistrar.class.getClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Java 7 Path class not available
|
||||
pathClass = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final PropertyResolver propertyResolver;
|
||||
|
||||
private final ResourceLoader resourceLoader;
|
||||
@@ -103,6 +118,9 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
|
||||
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
|
||||
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
|
||||
doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
|
||||
if (pathClass != null) {
|
||||
doRegisterEditor(registry, pathClass, new PathEditor(baseEditor));
|
||||
}
|
||||
doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
|
||||
doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));
|
||||
|
||||
|
||||
+5
-20
@@ -776,6 +776,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
private void testSingleTestBean(ListableBeanFactory lbf) {
|
||||
assertTrue("1 beans defined", lbf.getBeanDefinitionCount() == 1);
|
||||
String[] names = lbf.getBeanDefinitionNames();
|
||||
assertTrue(names != lbf.getBeanDefinitionNames());
|
||||
assertTrue("Array length == 1", names.length == 1);
|
||||
assertTrue("0th element == test", names[0].equals("test"));
|
||||
TestBean tb = (TestBean) lbf.getBean("test");
|
||||
@@ -1435,12 +1436,14 @@ public class DefaultListableBeanFactoryTests {
|
||||
public void testGetBeanByTypeWithPrimary() throws Exception {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||
bd1.setLazyInit(true);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
bd2.setPrimary(true);
|
||||
lbf.registerBeanDefinition("bd1", bd1);
|
||||
lbf.registerBeanDefinition("bd2", bd2);
|
||||
TestBean bean = lbf.getBean(TestBean.class);
|
||||
assertThat(bean.getBeanName(), equalTo("bd2"));
|
||||
assertFalse(lbf.containsSingleton("bd1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1760,24 +1763,6 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutowireBeanByTypeWithTwoMatchesAndParameterNameDiscovery() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("test", bd);
|
||||
lbf.registerBeanDefinition("spouse", bd2);
|
||||
try {
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
fail("Should have thrown UnsatisfiedDependencyException");
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getMessage().contains("test"));
|
||||
assertTrue(ex.getMessage().contains("spouse"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutowireBeanByTypeWithDependencyCheck() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
@@ -2216,7 +2201,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testPrototypeWithArrayConversionForConstructor() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
List<String> list = new ManagedList<String>();
|
||||
List<String> list = new ManagedList<>();
|
||||
list.add("myName");
|
||||
list.add("myBeanName");
|
||||
RootBeanDefinition bd = new RootBeanDefinition(DerivedTestBean.class);
|
||||
@@ -2235,7 +2220,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testPrototypeWithArrayConversionForFactoryMethod() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
List<String> list = new ManagedList<String>();
|
||||
List<String> list = new ManagedList<>();
|
||||
list.add("myName");
|
||||
list.add("myBeanName");
|
||||
RootBeanDefinition bd = new RootBeanDefinition(DerivedTestBean.class);
|
||||
|
||||
+176
-18
@@ -29,6 +29,7 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
@@ -41,6 +42,7 @@ import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
@@ -62,6 +64,7 @@ import org.springframework.tests.sample.beans.ITestBean;
|
||||
import org.springframework.tests.sample.beans.IndexedTestBean;
|
||||
import org.springframework.tests.sample.beans.NestedTestBean;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
@@ -918,7 +921,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
RootBeanDefinition tbm = new RootBeanDefinition(CollectionFactoryMethods.class);
|
||||
tbm.setUniqueFactoryMethodName("testBeanMap");
|
||||
bf.registerBeanDefinition("myTestBeanMap", tbm);
|
||||
bf.registerSingleton("otherMap", new HashMap<Object, Object>());
|
||||
bf.registerSingleton("otherMap", new HashMap<>());
|
||||
|
||||
MapConstructorInjectionBean bean = (MapConstructorInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("myTestBeanMap"), bean.getTestBeanMap());
|
||||
@@ -940,7 +943,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
tbs.add(new TestBean("tb1"));
|
||||
tbs.add(new TestBean("tb2"));
|
||||
bf.registerSingleton("testBeans", tbs);
|
||||
bf.registerSingleton("otherSet", new HashSet<Object>());
|
||||
bf.registerSingleton("otherSet", new HashSet<>());
|
||||
|
||||
SetConstructorInjectionBean bean = (SetConstructorInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(tbs, bean.getTestBeanSet());
|
||||
@@ -961,7 +964,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
RootBeanDefinition tbs = new RootBeanDefinition(CollectionFactoryMethods.class);
|
||||
tbs.setUniqueFactoryMethodName("testBeanSet");
|
||||
bf.registerBeanDefinition("myTestBeanSet", tbs);
|
||||
bf.registerSingleton("otherSet", new HashSet<Object>());
|
||||
bf.registerSingleton("otherSet", new HashSet<>());
|
||||
|
||||
SetConstructorInjectionBean bean = (SetConstructorInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("myTestBeanSet"), bean.getTestBeanSet());
|
||||
@@ -976,11 +979,59 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
RootBeanDefinition bd = new RootBeanDefinition(SelfInjectionBean.class);
|
||||
bf.registerBeanDefinition("annotatedBean", bd);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SelfInjectionBean.class));
|
||||
|
||||
SelfInjectionBean bean = (SelfInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bean, bean.selfReference);
|
||||
assertSame(bean, bean.reference);
|
||||
assertNull(bean.referenceCollection);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelfReferenceWithOther() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SelfInjectionBean.class));
|
||||
bf.registerBeanDefinition("annotatedBean2", new RootBeanDefinition(SelfInjectionBean.class));
|
||||
|
||||
SelfInjectionBean bean = (SelfInjectionBean) bf.getBean("annotatedBean");
|
||||
SelfInjectionBean bean2 = (SelfInjectionBean) bf.getBean("annotatedBean2");
|
||||
assertSame(bean2, bean.reference);
|
||||
assertEquals(1, bean.referenceCollection.size());
|
||||
assertSame(bean2, bean.referenceCollection.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelfReferenceCollection() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SelfInjectionCollectionBean.class));
|
||||
|
||||
SelfInjectionCollectionBean bean = (SelfInjectionCollectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bean, bean.reference);
|
||||
assertNull(bean.referenceCollection);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelfReferenceCollectionWithOther() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SelfInjectionCollectionBean.class));
|
||||
bf.registerBeanDefinition("annotatedBean2", new RootBeanDefinition(SelfInjectionCollectionBean.class));
|
||||
|
||||
SelfInjectionCollectionBean bean = (SelfInjectionCollectionBean) bf.getBean("annotatedBean");
|
||||
SelfInjectionCollectionBean bean2 = (SelfInjectionCollectionBean) bf.getBean("annotatedBean2");
|
||||
assertSame(bean2, bean.reference);
|
||||
assertSame(1, bean2.referenceCollection.size());
|
||||
assertSame(bean2, bean.referenceCollection.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1025,14 +1076,35 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryQualifierInjectionBean.class));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "testBean"));
|
||||
bf.registerBeanDefinition("testBean", bd);
|
||||
bf.registerBeanDefinition("testBean2", new RootBeanDefinition(TestBean.class));
|
||||
bf.registerBeanDefinition("dependencyBean", bd);
|
||||
bf.registerBeanDefinition("dependencyBean2", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
ObjectFactoryQualifierInjectionBean bean = (ObjectFactoryQualifierInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
assertSame(bf.getBean("dependencyBean"), bean.getTestBean());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryQualifierProviderInjection() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryQualifierInjectionBean.class));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.setQualifiedElement(ReflectionUtils.findMethod(getClass(), "testBeanQualifierProvider"));
|
||||
bf.registerBeanDefinition("dependencyBean", bd);
|
||||
bf.registerBeanDefinition("dependencyBean2", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
ObjectFactoryQualifierInjectionBean bean = (ObjectFactoryQualifierInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("dependencyBean"), bean.getTestBean());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Qualifier("testBean")
|
||||
private void testBeanQualifierProvider() {}
|
||||
|
||||
@Test
|
||||
public void testObjectFactorySerialization() throws Exception {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
@@ -1145,12 +1217,15 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
RootBeanDefinition tb1 = new RootBeanDefinition(TestBean.class);
|
||||
tb1.setPrimary(true);
|
||||
bf.registerBeanDefinition("testBean1", tb1);
|
||||
bf.registerBeanDefinition("testBean2", new RootBeanDefinition(TestBean.class));
|
||||
RootBeanDefinition tb2 = new RootBeanDefinition(TestBean.class);
|
||||
tb2.setLazyInit(true);
|
||||
bf.registerBeanDefinition("testBean2", tb2);
|
||||
|
||||
SmartObjectFactoryInjectionBean bean = (SmartObjectFactoryInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("testBean1"), bean.getTestBean());
|
||||
assertSame(bf.getBean("testBean1"), bean.getOptionalTestBean());
|
||||
assertSame(bf.getBean("testBean1"), bean.getUniqueTestBean());
|
||||
assertFalse(bf.containsSingleton("testBean2"));
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@@ -1220,7 +1295,6 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
// expected
|
||||
ex.printStackTrace();
|
||||
assertSame(CustomAnnotationRequiredFieldResourceInjectionBean.class,
|
||||
ex.getInjectionPoint().getField().getDeclaringClass());
|
||||
}
|
||||
@@ -1584,11 +1658,12 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
rbd.setFactoryBeanName("mocksControl");
|
||||
rbd.setFactoryMethodName("createMock");
|
||||
rbd.getConstructorArgumentValues().addGenericArgumentValue(Repository.class);
|
||||
bf.registerBeanDefinition("integerRepo", rbd);
|
||||
rbd.setQualifiedElement(ReflectionUtils.findField(getClass(), "integerRepositoryQualifierProvider"));
|
||||
bf.registerBeanDefinition("integerRepository", rbd); // Bean name not matching qualifier
|
||||
|
||||
RepositoryFieldInjectionBeanWithQualifiers bean = (RepositoryFieldInjectionBeanWithQualifiers) bf.getBean("annotatedBean");
|
||||
Repository<?> sr = bf.getBean("stringRepo", Repository.class);
|
||||
Repository<?> ir = bf.getBean("integerRepo", Repository.class);
|
||||
Repository<?> ir = bf.getBean("integerRepository", Repository.class);
|
||||
assertSame(sr, bean.stringRepository);
|
||||
assertSame(ir, bean.integerRepository);
|
||||
assertSame(1, bean.stringRepositoryArray.length);
|
||||
@@ -1602,7 +1677,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertSame(1, bean.stringRepositoryMap.size());
|
||||
assertSame(1, bean.integerRepositoryMap.size());
|
||||
assertSame(sr, bean.stringRepositoryMap.get("stringRepo"));
|
||||
assertSame(ir, bean.integerRepositoryMap.get("integerRepo"));
|
||||
assertSame(ir, bean.integerRepositoryMap.get("integerRepository"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -2047,6 +2122,24 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertSame(bean2, bean1.gi2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericsBasedInjectionWithBeanDefinitionTargetResolvableType() throws Exception {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(GenericInterface2Bean.class);
|
||||
bd1.setTargetType(ResolvableType.forClassWithGenerics(GenericInterface2Bean.class, String.class));
|
||||
bf.registerBeanDefinition("bean1", bd1);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(GenericInterface2Bean.class);
|
||||
bd2.setTargetType(ResolvableType.forClassWithGenerics(GenericInterface2Bean.class, Integer.class));
|
||||
bf.registerBeanDefinition("bean2", bd2);
|
||||
bf.registerBeanDefinition("bean3", new RootBeanDefinition(MultiGenericFieldInjection.class));
|
||||
|
||||
assertEquals("bean1 a bean2 123", bf.getBean("bean3").toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCircularTypeReference() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
@@ -2087,6 +2180,19 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertNotNull(bf.getBean(ProvidedArgumentBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotatedDefaultConstructor() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(AnnotatedDefaultConstructorBean.class));
|
||||
|
||||
assertNotNull(bf.getBean("annotatedBean"));
|
||||
}
|
||||
|
||||
|
||||
@Qualifier("integerRepo")
|
||||
private Repository<?> integerRepositoryQualifierProvider;
|
||||
|
||||
|
||||
public static class ResourceInjectionBean {
|
||||
|
||||
@@ -2534,7 +2640,21 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
public static class SelfInjectionBean {
|
||||
|
||||
@Autowired
|
||||
public SelfInjectionBean selfReference;
|
||||
public SelfInjectionBean reference;
|
||||
|
||||
@Autowired(required = false)
|
||||
public List<SelfInjectionBean> referenceCollection;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class SelfInjectionCollectionBean extends LinkedList<SelfInjectionCollectionBean> {
|
||||
|
||||
@Autowired
|
||||
public SelfInjectionCollectionBean reference;
|
||||
|
||||
@Autowired(required = false)
|
||||
public List<SelfInjectionCollectionBean> referenceCollection;
|
||||
}
|
||||
|
||||
|
||||
@@ -3101,7 +3221,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
public static GenericInterface1<String> createErased() {
|
||||
return new GenericInterface1Impl<String>();
|
||||
return new GenericInterface1Impl<>();
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@@ -3139,6 +3259,37 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
|
||||
public static class GenericInterface2Bean<K> implements GenericInterface2<K>, BeanNameAware {
|
||||
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
public void setBeanName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String doSomethingMoreGeneric(K o) {
|
||||
return this.name + " " + o;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class MultiGenericFieldInjection {
|
||||
|
||||
@Autowired
|
||||
private GenericInterface2<String> stringBean;
|
||||
|
||||
@Autowired
|
||||
private GenericInterface2<Integer> integerBean;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.stringBean.doSomethingMoreGeneric("a") + " " + this.integerBean.doSomethingMoreGeneric(123);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static class PlainGenericInterface2Impl implements GenericInterface2 {
|
||||
|
||||
@@ -3257,19 +3408,26 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
public static class CollectionFactoryMethods {
|
||||
|
||||
public static Map<String, TestBean> testBeanMap() {
|
||||
Map<String, TestBean> tbm = new LinkedHashMap<String, TestBean>();
|
||||
Map<String, TestBean> tbm = new LinkedHashMap<>();
|
||||
tbm.put("testBean1", new TestBean("tb1"));
|
||||
tbm.put("testBean2", new TestBean("tb2"));
|
||||
return tbm;
|
||||
}
|
||||
|
||||
public static Set<TestBean> testBeanSet() {
|
||||
Set<TestBean> tbs = new LinkedHashSet<TestBean>();
|
||||
Set<TestBean> tbs = new LinkedHashSet<>();
|
||||
tbs.add(new TestBean("tb1"));
|
||||
tbs.add(new TestBean("tb2"));
|
||||
return tbs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class AnnotatedDefaultConstructorBean {
|
||||
|
||||
@Autowired
|
||||
public AnnotatedDefaultConstructorBean() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+18
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -742,6 +742,15 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotatedDefaultConstructor() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(AnnotatedDefaultConstructorBean.class));
|
||||
|
||||
assertNotNull(bf.getBean("annotatedBean"));
|
||||
}
|
||||
|
||||
|
||||
public static class ResourceInjectionBean {
|
||||
|
||||
@@ -750,7 +759,6 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
|
||||
private TestBean testBean2;
|
||||
|
||||
|
||||
@Inject
|
||||
public void setTestBean2(TestBean testBean2) {
|
||||
if (this.testBean2 != null) {
|
||||
@@ -819,7 +827,6 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
|
||||
|
||||
public static class TypedExtendedResourceInjectionBean extends ExtendedResourceInjectionBean<NestedTestBean> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1087,7 +1094,6 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
@Inject
|
||||
private Map<String, TestBean> testBeanMap;
|
||||
|
||||
|
||||
public Map<String, TestBean> getTestBeanMap() {
|
||||
return this.testBeanMap;
|
||||
}
|
||||
@@ -1346,4 +1352,12 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class AnnotatedDefaultConstructorBean {
|
||||
|
||||
@Inject
|
||||
public AnnotatedDefaultConstructorBean() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+23
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -41,6 +41,7 @@ public class LookupAnnotationTests {
|
||||
aabpp.setBeanFactory(beanFactory);
|
||||
beanFactory.addBeanPostProcessor(aabpp);
|
||||
beanFactory.registerBeanDefinition("abstractBean", new RootBeanDefinition(AbstractBean.class));
|
||||
beanFactory.registerBeanDefinition("beanConsumer", new RootBeanDefinition(BeanConsumer.class));
|
||||
RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class);
|
||||
tbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
beanFactory.registerBeanDefinition("testBean", tbd);
|
||||
@@ -53,6 +54,7 @@ public class LookupAnnotationTests {
|
||||
assertNotNull(bean);
|
||||
Object expected = bean.get();
|
||||
assertEquals(TestBean.class, expected.getClass());
|
||||
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -62,6 +64,7 @@ public class LookupAnnotationTests {
|
||||
TestBean expected = bean.get("haha");
|
||||
assertEquals(TestBean.class, expected.getClass());
|
||||
assertEquals("haha", expected.getName());
|
||||
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,6 +74,7 @@ public class LookupAnnotationTests {
|
||||
TestBean expected = bean.getOneArgument("haha");
|
||||
assertEquals(TestBean.class, expected.getClass());
|
||||
assertEquals("haha", expected.getName());
|
||||
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -81,6 +85,7 @@ public class LookupAnnotationTests {
|
||||
assertEquals(TestBean.class, expected.getClass());
|
||||
assertEquals("haha", expected.getName());
|
||||
assertEquals(72, expected.getAge());
|
||||
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -93,6 +98,16 @@ public class LookupAnnotationTests {
|
||||
}
|
||||
catch (AbstractMethodError ex) {
|
||||
}
|
||||
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithEarlyInjection() {
|
||||
AbstractBean bean = beanFactory.getBean("beanConsumer", BeanConsumer.class).abstractBean;
|
||||
assertNotNull(bean);
|
||||
Object expected = bean.get();
|
||||
assertEquals(TestBean.class, expected.getClass());
|
||||
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,4 +128,11 @@ public class LookupAnnotationTests {
|
||||
public abstract TestBean getThreeArguments(String name, int age, int anotherArg);
|
||||
}
|
||||
|
||||
|
||||
public static class BeanConsumer {
|
||||
|
||||
@Autowired
|
||||
AbstractBean abstractBean;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+31
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,43 +34,40 @@ import static org.junit.Assert.*;
|
||||
* Tests for {@link YamlMapFactoryBean}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class YamlMapFactoryBeanTests {
|
||||
|
||||
private final YamlMapFactoryBean factory = new YamlMapFactoryBean();
|
||||
|
||||
|
||||
@Test
|
||||
public void testSetIgnoreResourceNotFound() throws Exception {
|
||||
this.factory
|
||||
.setResolutionMethod(YamlMapFactoryBean.ResolutionMethod.OVERRIDE_AND_IGNORE);
|
||||
this.factory.setResources(new FileSystemResource[] {new FileSystemResource(
|
||||
"non-exsitent-file.yml")});
|
||||
this.factory.setResolutionMethod(YamlMapFactoryBean.ResolutionMethod.OVERRIDE_AND_IGNORE);
|
||||
this.factory.setResources(new FileSystemResource("non-exsitent-file.yml"));
|
||||
assertEquals(0, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testSetBarfOnResourceNotFound() throws Exception {
|
||||
this.factory.setResources(new FileSystemResource[] {new FileSystemResource(
|
||||
"non-exsitent-file.yml")});
|
||||
this.factory.setResources(new FileSystemResource("non-exsitent-file.yml"));
|
||||
assertEquals(0, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetObject() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource[] {new ByteArrayResource(
|
||||
"foo: bar".getBytes())});
|
||||
this.factory.setResources(new ByteArrayResource("foo: bar".getBytes()));
|
||||
assertEquals(1, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testOverrideAndremoveDefaults() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource[] {
|
||||
new ByteArrayResource("foo:\n bar: spam".getBytes()),
|
||||
new ByteArrayResource("foo:\n spam: bar".getBytes())});
|
||||
public void testOverrideAndRemoveDefaults() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource("foo:\n bar: spam".getBytes()),
|
||||
new ByteArrayResource("foo:\n spam: bar".getBytes()));
|
||||
|
||||
assertEquals(1, this.factory.getObject().size());
|
||||
assertEquals(2,
|
||||
((Map<String, Object>) this.factory.getObject().get("foo")).size());
|
||||
assertEquals(2, ((Map<String, Object>) this.factory.getObject().get("foo")).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -81,20 +78,20 @@ public class YamlMapFactoryBeanTests {
|
||||
public String getDescription() {
|
||||
return "non-existent";
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
throw new IOException("planned");
|
||||
}
|
||||
}, new ByteArrayResource("foo:\n spam: bar".getBytes()));
|
||||
|
||||
assertEquals(1, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapWithPeriodsInKey() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource[] {new ByteArrayResource(
|
||||
"foo:\n ? key1.key2\n : value".getBytes())});
|
||||
this.factory.setResources(new ByteArrayResource("foo:\n ? key1.key2\n : value".getBytes()));
|
||||
Map<String, Object> map = this.factory.getObject();
|
||||
|
||||
assertEquals(1, map.size());
|
||||
assertTrue(map.containsKey("foo"));
|
||||
Object object = map.get("foo");
|
||||
@@ -105,10 +102,24 @@ public class YamlMapFactoryBeanTests {
|
||||
assertEquals("value", sub.get("key1.key2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapWithIntegerValue() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource("foo:\n ? key1.key2\n : 3".getBytes()));
|
||||
Map<String, Object> map = this.factory.getObject();
|
||||
|
||||
assertEquals(1, map.size());
|
||||
assertTrue(map.containsKey("foo"));
|
||||
Object object = map.get("foo");
|
||||
assertTrue(object instanceof LinkedHashMap);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> sub = (Map<String, Object>) object;
|
||||
assertTrue(sub.containsKey("key1.key2"));
|
||||
assertEquals(Integer.valueOf(3), sub.get("key1.key2"));
|
||||
}
|
||||
|
||||
@Test(expected = ParserException.class)
|
||||
public void testDuplicateKey() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource[] {new ByteArrayResource(
|
||||
"mymap:\n foo: bar\nmymap:\n bar: foo".getBytes())});
|
||||
this.factory.setResources(new ByteArrayResource("mymap:\n foo: bar\nmymap:\n bar: foo".getBytes()));
|
||||
this.factory.getObject().get("mymap");
|
||||
}
|
||||
|
||||
|
||||
+23
-23
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -24,6 +25,7 @@ import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.yaml.snakeyaml.parser.ParserException;
|
||||
import org.yaml.snakeyaml.scanner.ScannerException;
|
||||
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
@@ -33,34 +35,38 @@ import static org.springframework.beans.factory.config.YamlProcessor.*;
|
||||
* Tests for {@link YamlProcessor}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class YamlProcessorTests {
|
||||
|
||||
private final YamlProcessor processor = new YamlProcessor() {
|
||||
};
|
||||
private final YamlProcessor processor = new YamlProcessor() {};
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
|
||||
@Test
|
||||
public void arrayConvertedToIndexedBeanReference() {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo: bar\nbar: [1,2,3]".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar: [1,2,3]".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
assertEquals(1, properties.get("bar[0]"));
|
||||
assertEquals(2, properties.get("bar[1]"));
|
||||
assertEquals(3, properties.get("bar[2]"));
|
||||
assertEquals(4, properties.size());
|
||||
assertEquals("bar", properties.get("foo"));
|
||||
assertEquals("bar", properties.getProperty("foo"));
|
||||
assertEquals(1, properties.get("bar[0]"));
|
||||
assertEquals("1", properties.getProperty("bar[0]"));
|
||||
assertEquals(2, properties.get("bar[1]"));
|
||||
assertEquals("2", properties.getProperty("bar[1]"));
|
||||
assertEquals(3, properties.get("bar[2]"));
|
||||
assertEquals("3", properties.getProperty("bar[2]"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringResource() throws Exception {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo # a document that is a literal".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo # a document that is a literal".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
@@ -71,8 +77,7 @@ public class YamlProcessorTests {
|
||||
|
||||
@Test
|
||||
public void testBadDocumentStart() throws Exception {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo # a document\nbar: baz".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo # a document\nbar: baz".getBytes()));
|
||||
this.exception.expect(ParserException.class);
|
||||
this.exception.expectMessage("line 2, column 1");
|
||||
this.processor.process(new MatchCallback() {
|
||||
@@ -84,8 +89,7 @@ public class YamlProcessorTests {
|
||||
|
||||
@Test
|
||||
public void testBadResource() throws Exception {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo: bar\ncd\nspam:\n foo: baz".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\ncd\nspam:\n foo: baz".getBytes()));
|
||||
this.exception.expect(ScannerException.class);
|
||||
this.exception.expectMessage("line 3, column 1");
|
||||
this.processor.process(new MatchCallback() {
|
||||
@@ -97,8 +101,7 @@ public class YamlProcessorTests {
|
||||
|
||||
@Test
|
||||
public void mapConvertedToIndexedBeanReference() {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo: bar\nbar:\n spam: bucket".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar:\n spam: bucket".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
@@ -111,8 +114,7 @@ public class YamlProcessorTests {
|
||||
|
||||
@Test
|
||||
public void integerKeyBehaves() {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo: bar\n1: bar".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\n1: bar".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
@@ -124,10 +126,8 @@ public class YamlProcessorTests {
|
||||
|
||||
@Test
|
||||
public void integerDeepKeyBehaves() {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo:\n 1: bar".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo:\n 1: bar".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
assertEquals("bar", properties.get("foo[1]"));
|
||||
@@ -139,8 +139,7 @@ public class YamlProcessorTests {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void flattenedMapIsSameAsPropertiesButOrdered() {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo: bar\nbar:\n spam: bucket".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar:\n spam: bucket".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
@@ -155,4 +154,5 @@ public class YamlProcessorTests {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+25
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,12 +38,14 @@ import static org.springframework.beans.factory.config.YamlProcessor.*;
|
||||
* Tests for {@link YamlPropertiesFactoryBean}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class YamlPropertiesFactoryBeanTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
|
||||
@Test
|
||||
public void testLoadResource() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
@@ -113,8 +115,8 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
||||
@Override
|
||||
public MatchStatus matches(Properties properties) {
|
||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
||||
: MatchStatus.NOT_FOUND;
|
||||
return ("bag".equals(properties.getProperty("foo")) ?
|
||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||
}
|
||||
});
|
||||
Properties properties = factory.getObject();
|
||||
@@ -134,8 +136,8 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
if (!properties.containsKey("foo")) {
|
||||
return MatchStatus.ABSTAIN;
|
||||
}
|
||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
||||
: MatchStatus.NOT_FOUND;
|
||||
return ("bag".equals(properties.getProperty("foo")) ?
|
||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||
}
|
||||
});
|
||||
Properties properties = factory.getObject();
|
||||
@@ -156,8 +158,8 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
if (!properties.containsKey("foo")) {
|
||||
return MatchStatus.ABSTAIN;
|
||||
}
|
||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
||||
: MatchStatus.NOT_FOUND;
|
||||
return ("bag".equals(properties.getProperty("foo")) ?
|
||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||
}
|
||||
});
|
||||
Properties properties = factory.getObject();
|
||||
@@ -178,8 +180,8 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
if (!properties.containsKey("foo")) {
|
||||
return MatchStatus.ABSTAIN;
|
||||
}
|
||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
||||
: MatchStatus.NOT_FOUND;
|
||||
return ("bag".equals(properties.getProperty("foo")) ?
|
||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||
}
|
||||
});
|
||||
Properties properties = factory.getObject();
|
||||
@@ -200,8 +202,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
@Test
|
||||
public void testLoadNull() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource("foo: bar\nspam:"
|
||||
.getBytes()));
|
||||
factory.setResources(new ByteArrayResource("foo: bar\nspam:".getBytes()));
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bar"));
|
||||
assertThat(properties.getProperty("spam"), equalTo(""));
|
||||
@@ -210,20 +211,28 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
@Test
|
||||
public void testLoadArrayOfString() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource("foo:\n- bar\n- baz"
|
||||
.getBytes()));
|
||||
factory.setResources(new ByteArrayResource("foo:\n- bar\n- baz".getBytes()));
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo[0]"), equalTo("bar"));
|
||||
assertThat(properties.getProperty("foo[1]"), equalTo("baz"));
|
||||
assertThat(properties.get("foo"), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadArrayOfInteger() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource("foo:\n- 1\n- 2".getBytes()));
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo[0]"), equalTo("1"));
|
||||
assertThat(properties.getProperty("foo[1]"), equalTo("2"));
|
||||
assertThat(properties.get("foo"), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadArrayOfObject() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource(
|
||||
"foo:\n- bar:\n spam: crap\n- baz\n- one: two\n three: four"
|
||||
.getBytes()
|
||||
"foo:\n- bar:\n spam: crap\n- baz\n- one: two\n three: four".getBytes()
|
||||
));
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo[0].bar.spam"), equalTo("crap"));
|
||||
@@ -239,8 +248,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
Yaml yaml = new Yaml();
|
||||
Map<String, ?> map = yaml.loadAs("foo: bar\nspam:\n foo: baz", Map.class);
|
||||
assertThat(map.get("foo"), equalTo((Object) "bar"));
|
||||
assertThat(((Map<String, Object>) map.get("spam")).get("foo"),
|
||||
equalTo((Object) "baz"));
|
||||
assertThat(((Map<String, Object>) map.get("spam")).get("foo"), equalTo((Object) "baz"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -126,6 +126,7 @@ public class BeanDefinitionTests {
|
||||
bd.getConstructorArgumentValues().addIndexedArgumentValue(1, new Integer(5));
|
||||
bd.getPropertyValues().add("name", "myName");
|
||||
bd.getPropertyValues().add("age", "99");
|
||||
bd.setQualifiedElement(getClass());
|
||||
|
||||
GenericBeanDefinition childBd = new GenericBeanDefinition();
|
||||
childBd.setParentName("bd");
|
||||
@@ -138,6 +139,7 @@ public class BeanDefinitionTests {
|
||||
|
||||
mergedBd.getConstructorArgumentValues().getArgumentValue(1, null).setValue(new Integer(9));
|
||||
assertEquals(new Integer(5), bd.getConstructorArgumentValues().getArgumentValue(1, null).getValue());
|
||||
assertEquals(getClass(), bd.getQualifiedElement());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,21 +28,22 @@ import static org.junit.Assert.*;
|
||||
/**
|
||||
* @author Thomas Risberg
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public final class FileEditorTests {
|
||||
public class FileEditorTests {
|
||||
|
||||
@Test
|
||||
public void testClasspathFileName() throws Exception {
|
||||
PropertyEditor fileEditor = new FileEditor();
|
||||
fileEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/"
|
||||
+ ClassUtils.getShortName(getClass()) + ".class");
|
||||
fileEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".class");
|
||||
Object value = fileEditor.getValue();
|
||||
assertTrue(value instanceof File);
|
||||
File file = (File) value;
|
||||
assertTrue(file.exists());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWithNonExistentResource() throws Exception {
|
||||
PropertyEditor propertyEditor = new FileEditor();
|
||||
propertyEditor.setAsText("classpath:no_way_this_file_is_found.doc");
|
||||
@@ -71,34 +72,29 @@ public final class FileEditorTests {
|
||||
@Test
|
||||
public void testUnqualifiedFileNameFound() throws Exception {
|
||||
PropertyEditor fileEditor = new FileEditor();
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass())
|
||||
+ ".class";
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".class";
|
||||
fileEditor.setAsText(fileName);
|
||||
Object value = fileEditor.getValue();
|
||||
assertTrue(value instanceof File);
|
||||
File file = (File) value;
|
||||
assertTrue(file.exists());
|
||||
String absolutePath = file.getAbsolutePath();
|
||||
if (File.separatorChar == '\\') {
|
||||
absolutePath = absolutePath.replace('\\', '/');
|
||||
}
|
||||
String absolutePath = file.getAbsolutePath().replace('\\', '/');
|
||||
assertTrue(absolutePath.endsWith(fileName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnqualifiedFileNameNotFound() throws Exception {
|
||||
PropertyEditor fileEditor = new FileEditor();
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass())
|
||||
+ ".clazz";
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".clazz";
|
||||
fileEditor.setAsText(fileName);
|
||||
Object value = fileEditor.getValue();
|
||||
assertTrue(value instanceof File);
|
||||
File file = (File) value;
|
||||
assertFalse(file.exists());
|
||||
String absolutePath = file.getAbsolutePath();
|
||||
if (File.separatorChar == '\\') {
|
||||
absolutePath = absolutePath.replace('\\', '/');
|
||||
}
|
||||
String absolutePath = file.getAbsolutePath().replace('\\', '/');
|
||||
assertTrue(absolutePath.endsWith(fileName));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -60,9 +60,8 @@ public class InputStreamEditorTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWhenResourceDoesNotExist() throws Exception {
|
||||
String resource = "classpath:bingo!";
|
||||
InputStreamEditor editor = new InputStreamEditor();
|
||||
editor.setAsText(resource);
|
||||
editor.setAsText("classpath:bingo!");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://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.beans.propertyeditors;
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.3.2
|
||||
*/
|
||||
public class PathEditorTests {
|
||||
|
||||
@Test
|
||||
public void testClasspathPathName() throws Exception {
|
||||
PropertyEditor pathEditor = new PathEditor();
|
||||
pathEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".class");
|
||||
Object value = pathEditor.getValue();
|
||||
assertTrue(value instanceof Path);
|
||||
Path path = (Path) value;
|
||||
assertTrue(path.toFile().exists());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWithNonExistentResource() throws Exception {
|
||||
PropertyEditor propertyEditor = new PathEditor();
|
||||
propertyEditor.setAsText("classpath:/no_way_this_file_is_found.doc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithNonExistentPath() throws Exception {
|
||||
PropertyEditor pathEditor = new PathEditor();
|
||||
pathEditor.setAsText("file:/no_way_this_file_is_found.doc");
|
||||
Object value = pathEditor.getValue();
|
||||
assertTrue(value instanceof Path);
|
||||
Path path = (Path) value;
|
||||
assertTrue(!path.toFile().exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbsolutePath() throws Exception {
|
||||
PropertyEditor pathEditor = new PathEditor();
|
||||
pathEditor.setAsText("/no_way_this_file_is_found.doc");
|
||||
Object value = pathEditor.getValue();
|
||||
assertTrue(value instanceof Path);
|
||||
Path path = (Path) value;
|
||||
assertTrue(!path.toFile().exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnqualifiedPathNameFound() throws Exception {
|
||||
PropertyEditor pathEditor = new PathEditor();
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".class";
|
||||
pathEditor.setAsText(fileName);
|
||||
Object value = pathEditor.getValue();
|
||||
assertTrue(value instanceof Path);
|
||||
Path path = (Path) value;
|
||||
File file = path.toFile();
|
||||
assertTrue(file.exists());
|
||||
String absolutePath = file.getAbsolutePath();
|
||||
if (File.separatorChar == '\\') {
|
||||
absolutePath = absolutePath.replace('\\', '/');
|
||||
}
|
||||
assertTrue(absolutePath.endsWith(fileName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnqualifiedPathNameNotFound() throws Exception {
|
||||
PropertyEditor pathEditor = new PathEditor();
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".clazz";
|
||||
pathEditor.setAsText(fileName);
|
||||
Object value = pathEditor.getValue();
|
||||
assertTrue(value instanceof Path);
|
||||
Path path = (Path) value;
|
||||
File file = path.toFile();
|
||||
assertFalse(file.exists());
|
||||
String absolutePath = file.getAbsolutePath();
|
||||
if (File.separatorChar == '\\') {
|
||||
absolutePath = absolutePath.replace('\\', '/');
|
||||
}
|
||||
assertTrue(absolutePath.endsWith(fileName));
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,7 +34,7 @@ public class ReaderEditorTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCtorWithNullResourceEditor() throws Exception {
|
||||
new InputStreamEditor(null);
|
||||
new ReaderEditor(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+11
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,15 +31,6 @@ import static org.junit.Assert.*;
|
||||
*/
|
||||
public class URIEditorTests {
|
||||
|
||||
private void doTestURI(String uriSpec) {
|
||||
PropertyEditor uriEditor = new URIEditor();
|
||||
uriEditor.setAsText(uriSpec);
|
||||
Object value = uriEditor.getValue();
|
||||
assertTrue(value instanceof URI);
|
||||
URI uri = (URI) value;
|
||||
assertEquals(uriSpec, uri.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void standardURI() throws Exception {
|
||||
doTestURI("mailto:juergen.hoeller@interface21.com");
|
||||
@@ -141,4 +132,14 @@ public class URIEditorTests {
|
||||
assertEquals("http://example.com/spaces%20and%20%E2%82%AC", uri.toASCIIString());
|
||||
}
|
||||
|
||||
|
||||
private void doTestURI(String uriSpec) {
|
||||
PropertyEditor uriEditor = new URIEditor();
|
||||
uriEditor.setAsText(uriSpec);
|
||||
Object value = uriEditor.getValue();
|
||||
assertTrue(value instanceof URI);
|
||||
URI uri = (URI) value;
|
||||
assertEquals(uriSpec, uri.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,7 +29,12 @@ import static org.junit.Assert.*;
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class URLEditorTests {
|
||||
public class URLEditorTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCtorWithNullResourceEditor() throws Exception {
|
||||
new URLEditor(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStandardURI() throws Exception {
|
||||
@@ -63,7 +68,7 @@ public final class URLEditorTests {
|
||||
assertTrue(!url.getProtocol().startsWith("classpath"));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWithNonExistentResource() throws Exception {
|
||||
PropertyEditor urlEditor = new URLEditor();
|
||||
urlEditor.setAsText("gonna:/freak/in/the/morning/freak/in/the.evening");
|
||||
@@ -83,9 +88,4 @@ public final class URLEditorTests {
|
||||
assertEquals("", urlEditor.getAsText());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testCtorWithNullResourceEditor() throws Exception {
|
||||
new URLEditor(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -223,7 +223,7 @@ public class TestBean implements BeanNameAware, BeanFactoryAware, ITestBean, IOt
|
||||
|
||||
@Override
|
||||
public ITestBean[] getSpouses() {
|
||||
return (spouse != null ? new ITestBean[]{spouse} : null);
|
||||
return (spouse != null ? new ITestBean[] {spouse} : null);
|
||||
}
|
||||
|
||||
public String getTouchy() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -98,7 +98,7 @@ public class EhCacheCache implements Cache {
|
||||
try {
|
||||
value = valueLoader.call();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new ValueRetrievalException(key, valueLoader, ex);
|
||||
}
|
||||
put(key, value);
|
||||
|
||||
+1
-1
@@ -7,6 +7,6 @@
|
||||
* <p>Note: EhCache 3.x lives in a different package namespace
|
||||
* and is not covered by the traditional support classes here.
|
||||
* Instead, consider using it through JCache (JSR-107), with
|
||||
* Spring's support in {@link org.springframework.cache.jcache}.
|
||||
* Spring's support in {@code org.springframework.cache.jcache}.
|
||||
*/
|
||||
package org.springframework.cache.ehcache;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user