mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
126 Commits
main
...
v3.2.4.RELEASE
| Author | SHA1 | Date | |
|---|---|---|---|
| fc73f6bb2c | |||
| 119364f326 | |||
| 434735fbf6 | |||
| 8f4221deb3 | |||
| 2d646ca79e | |||
| 1245919331 | |||
| bcbd338fe2 | |||
| 945463b826 | |||
| 3ba3dd61d1 | |||
| cd523c7051 | |||
| 20ddd3254b | |||
| e30b842316 | |||
| b0675c031e | |||
| 0f71da5be6 | |||
| 9035a97e18 | |||
| d32a77a5f0 | |||
| d8e3ef7640 | |||
| ccb02a2355 | |||
| d0948f1f03 | |||
| ae0f23e942 | |||
| b40263e06b | |||
| 2f8dfb3e52 | |||
| d5c78c953d | |||
| dfac1d0510 | |||
| 14b83c3fcc | |||
| ae6e84bc7d | |||
| 4213a31a7d | |||
| 22454c8edf | |||
| 98da5a7b2b | |||
| 0a37552beb | |||
| 1b702fa6a2 | |||
| a2e438b2be | |||
| 9ff9d45283 | |||
| 1fee4c0c0b | |||
| dc87a2211c | |||
| 77b7344530 | |||
| 7cde4f1503 | |||
| 6c11fd3b5e | |||
| eec4a37d1c | |||
| 1e3dc4aeae | |||
| d4b54d834e | |||
| 3562cd759b | |||
| c1dc4e2c75 | |||
| 8feeec4a60 | |||
| 440a63a3d0 | |||
| 274ed1fe67 | |||
| 1b47f6c0b0 | |||
| 66e4c9b2bb | |||
| e608055021 | |||
| 199be0ad3c | |||
| af7753eac6 | |||
| cce74b8ba2 | |||
| dd7508d606 | |||
| 3bf56dda56 | |||
| a72209aad3 | |||
| 67f41b15eb | |||
| 3515acfa3d | |||
| 7fdd0c22b2 | |||
| a0f8a894f2 | |||
| 55f02db18e | |||
| 71e88cbf30 | |||
| 514a2e9568 | |||
| abfb439bfe | |||
| 4ba43b4737 | |||
| 2655657a51 | |||
| 404671416a | |||
| 260eafc819 | |||
| ef8b5763e6 | |||
| 6b89af824d | |||
| 86b4b2ef23 | |||
| faa8430fd7 | |||
| 76f870caca | |||
| 615315728b | |||
| 115442242f | |||
| 10c0e8af01 | |||
| b6e20a4cc9 | |||
| a8adec7673 | |||
| 2ae61c503e | |||
| c2b2f30669 | |||
| 239a7cd85f | |||
| 6e4317ebfb | |||
| 325d8834e3 | |||
| 0c76cb7e80 | |||
| 940011e233 | |||
| 92bbd8103b | |||
| 9c194699c7 | |||
| 25701ef984 | |||
| 87ef99df5e | |||
| 13ca2752ae | |||
| ef363b0f7a | |||
| f9db59e730 | |||
| 0dcca2304f | |||
| ad272a0c87 | |||
| be224e1f30 | |||
| 4bb0916202 | |||
| d3eda09c01 | |||
| 399f887128 | |||
| 4d005b6987 | |||
| 532a7a3a02 | |||
| b2d416fd5f | |||
| 7298c3d669 | |||
| 7bbd38b9e0 | |||
| 64d83a550e | |||
| 0df1630ab9 | |||
| 7cbc115da6 | |||
| b962239e11 | |||
| 872cf6b076 | |||
| b2bd319d47 | |||
| e3fa49063e | |||
| c302efdbbf | |||
| 12699696f4 | |||
| c4f2566070 | |||
| 6458643f15 | |||
| 2145545e69 | |||
| f6545cde38 | |||
| 601c64a65c | |||
| 964f1a6213 | |||
| 886cc2cce8 | |||
| 5bdd2d245c | |||
| d0513f7521 | |||
| 265c0c1505 | |||
| 886cf825cb | |||
| 03033f6c06 | |||
| 5ff2dfbe13 | |||
| fa44ab6336 | |||
| eed1a58b81 |
+96
-58
@@ -3,8 +3,8 @@ buildscript {
|
||||
maven { url "http://repo.springsource.org/plugins-release" }
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.3")
|
||||
classpath("org.springframework.build.gradle:docbook-reference-plugin:0.2.6")
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.4")
|
||||
classpath("org.springframework.build.gradle:docbook-reference-plugin:0.2.7")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,11 @@ configure(allprojects) { project ->
|
||||
group = "org.springframework"
|
||||
version = qualifyVersionIfNecessary(version)
|
||||
|
||||
// The following is a work-around for allowing to build on JDK 8 until the
|
||||
// Gradle build uses Ant 1.9.x by default. This is necessary to avoid the
|
||||
// "Class not found: javac1.8" issue with Ant versions prior to 1.9.x
|
||||
ant.properties["build.compiler"] = "javac1.7"
|
||||
|
||||
ext.aspectjVersion = "1.7.2"
|
||||
ext.hsqldbVersion = "1.8.0.10"
|
||||
ext.junitVersion = "4.11"
|
||||
@@ -58,6 +63,9 @@ configure(allprojects) { project ->
|
||||
test {
|
||||
systemProperty("java.awt.headless", "true")
|
||||
systemProperty("testGroups", project.properties.get("testGroups"))
|
||||
scanForTestClasses = false
|
||||
include '**/*Tests.*'
|
||||
exclude '**/*Abstract*.*'
|
||||
}
|
||||
|
||||
repositories {
|
||||
@@ -71,25 +79,26 @@ configure(allprojects) { project ->
|
||||
}
|
||||
|
||||
ext.javadocLinks = [
|
||||
"http://docs.oracle.com/javase/6/docs/api",
|
||||
"http://docs.oracle.com/javaee/6/api",
|
||||
"http://portals.apache.org/pluto/portlet-2.0-apidocs/",
|
||||
"http://commons.apache.org/proper/commons-lang/javadocs/api-release/",
|
||||
"http://commons.apache.org/proper/commons-codec/apidocs/",
|
||||
"http://docs.oracle.com/javase/6/docs/api/",
|
||||
"http://docs.oracle.com/javaee/6/api/",
|
||||
"http://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/", // CommonJ
|
||||
"http://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/",
|
||||
"http://glassfish.java.net/nonav/docs/v3/api/",
|
||||
"http://docs.jboss.org/jbossas/javadoc/4.0.5/connector/",
|
||||
"http://docs.jboss.org/jbossas/javadoc/7.1.2.Final/",
|
||||
"http://aopalliance.sourceforge.net/doc/",
|
||||
"http://glassfish.java.net/nonav/docs/v3/api/",
|
||||
"http://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/", // commonj
|
||||
"http://quartz-scheduler.org/api/2.1.5/",
|
||||
"http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
|
||||
"http://hc.apache.org/httpclient-3.x/apidocs/",
|
||||
"http://fasterxml.github.com/jackson-core/javadoc/2.0.0/",
|
||||
"http://jackson.codehaus.org/1.4.2/javadoc/",
|
||||
"http://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/",
|
||||
"http://ibatis.apache.org/docs/java/dev/",
|
||||
"http://tiles.apache.org/framework/apidocs/",
|
||||
"http://commons.apache.org/proper/commons-lang/javadocs/api-2.5/",
|
||||
"http://commons.apache.org/proper/commons-codec/apidocs/",
|
||||
"http://commons.apache.org/proper/commons-dbcp/apidocs/",
|
||||
"http://portals.apache.org/pluto/portlet-2.0-apidocs/",
|
||||
"http://tiles.apache.org/framework/apidocs/",
|
||||
"http://ibatis.apache.org/docs/java/dev/",
|
||||
"http://hc.apache.org/httpclient-3.x/apidocs/",
|
||||
"http://aopalliance.sourceforge.net/doc/",
|
||||
"http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
|
||||
"http://ehcache.org/apidocs/",
|
||||
"http://quartz-scheduler.org/api/2.1.5/",
|
||||
"http://jackson.codehaus.org/1.4.2/javadoc/",
|
||||
"http://fasterxml.github.com/jackson-core/javadoc/2.0.1/",
|
||||
] as String[]
|
||||
}
|
||||
|
||||
@@ -118,6 +127,9 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
|
||||
options.author = true
|
||||
options.header = project.name
|
||||
options.links(project.ext.javadocLinks)
|
||||
if(JavaVersion.current().isJava8Compatible()) {
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
}
|
||||
|
||||
// suppress warnings due to cross-module @see and @link references;
|
||||
// note that global 'api' task does display all warnings.
|
||||
@@ -148,7 +160,7 @@ project("spring-build-src") {
|
||||
|
||||
dependencies {
|
||||
compile gradleApi()
|
||||
groovy localGroovy()
|
||||
compile localGroovy()
|
||||
}
|
||||
|
||||
configurations.archives.artifacts.clear()
|
||||
@@ -219,6 +231,7 @@ project("spring-core") {
|
||||
cglib("cglib:cglib:${cglibVersion}@jar")
|
||||
jarjar("com.googlecode.jarjar:jarjar:1.3")
|
||||
|
||||
compile(files(cglibRepackJar))
|
||||
compile(files(asmRepackJar))
|
||||
compile("commons-logging:commons-logging:1.1.1")
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
@@ -245,6 +258,7 @@ project("spring-core") {
|
||||
|
||||
project("spring-beans") {
|
||||
description = "Spring Beans"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(files(project(":spring-core").cglibRepackJar))
|
||||
@@ -256,6 +270,7 @@ project("spring-beans") {
|
||||
|
||||
project("spring-aop") {
|
||||
description = "Spring AOP"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(files(project(":spring-core").cglibRepackJar))
|
||||
@@ -269,6 +284,7 @@ project("spring-aop") {
|
||||
|
||||
project("spring-expression") {
|
||||
description = "Spring Expression Language (SpEL)"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
}
|
||||
@@ -276,17 +292,19 @@ project("spring-expression") {
|
||||
|
||||
project("spring-instrument") {
|
||||
description = "Spring Instrument"
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest.attributes["Premain-Class"] =
|
||||
"org.springframework.instrument.InstrumentationSavingAgent"
|
||||
manifest.attributes["Can-Redefine-Classes"] = "true"
|
||||
manifest.attributes["Can-Retransform-Classes"] = "true"
|
||||
manifest.attributes["Can-Set-Native-Method-Prefix"] = "false"
|
||||
}
|
||||
}
|
||||
|
||||
project("spring-instrument-tomcat") {
|
||||
description = "Spring Instrument Tomcat"
|
||||
|
||||
dependencies {
|
||||
provided("org.apache.tomcat:catalina:6.0.16")
|
||||
}
|
||||
@@ -294,6 +312,7 @@ project("spring-instrument-tomcat") {
|
||||
|
||||
project("spring-context") {
|
||||
description = "Spring Context"
|
||||
|
||||
dependencies {
|
||||
optional(project(":spring-instrument"))
|
||||
compile(project(":spring-aop"))
|
||||
@@ -306,12 +325,12 @@ project("spring-context") {
|
||||
optional("javax.inject:javax.inject:1")
|
||||
optional("org.apache.geronimo.specs:geronimo-jms_1.1_spec:1.1")
|
||||
optional("javax.persistence:persistence-api:1.0")
|
||||
optional("javax.validation:validation-api:1.0.0.GA")
|
||||
optional("org.beanshell:bsh:2.0b4")
|
||||
optional("org.codehaus.groovy:groovy-all:1.8.8")
|
||||
optional("org.jruby:jruby:1.6.5.1")
|
||||
optional("joda-time:joda-time:2.1")
|
||||
optional("org.slf4j:slf4j-api:${slf4jVersion}")
|
||||
optional("javax.validation:validation-api:1.0.0.GA")
|
||||
optional("org.hibernate:hibernate-validator:4.3.0.Final")
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1")
|
||||
@@ -319,6 +338,9 @@ project("spring-context") {
|
||||
testCompile("javax.inject:javax.inject-tck:1")
|
||||
}
|
||||
|
||||
// pick up RmiInvocationWrapperRTD.xml in src/main
|
||||
sourceSets.main.resources.srcDirs += "src/main/java"
|
||||
|
||||
test {
|
||||
jvmArgs = ["-disableassertions:org.aspectj.weaver.UnresolvedType"] // SPR-7989
|
||||
}
|
||||
@@ -326,6 +348,7 @@ project("spring-context") {
|
||||
|
||||
project("spring-tx") {
|
||||
description = "Spring Transaction"
|
||||
|
||||
dependencies {
|
||||
optional(project(":spring-context")) // for JCA, @EnableTransactionManagement
|
||||
optional(project(":spring-aop"))
|
||||
@@ -355,10 +378,8 @@ project("spring-oxm") {
|
||||
dependencies {
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-core"))
|
||||
optional(project(":spring-context")) // for Jaxb2Marshaller
|
||||
compile("commons-lang:commons-lang:2.5")
|
||||
testCompile(project(":spring-context"))
|
||||
optional("com.thoughtworks.xstream:xstream:1.3.1")
|
||||
optional("com.sun.xml.bind:jaxb-impl:2.1.7")
|
||||
optional("org.jibx:jibx-run:1.2.3")
|
||||
optional("org.apache.xmlbeans:xmlbeans:2.4.0")
|
||||
optional("org.codehaus.castor:castor-xml:1.3.2")
|
||||
@@ -373,6 +394,7 @@ project("spring-oxm") {
|
||||
|
||||
project("spring-jms") {
|
||||
description = "Spring JMS"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-beans"))
|
||||
@@ -391,6 +413,7 @@ project("spring-jms") {
|
||||
|
||||
project("spring-jdbc") {
|
||||
description = "Spring JDBC"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-beans"))
|
||||
@@ -407,6 +430,7 @@ project("spring-jdbc") {
|
||||
|
||||
project("spring-context-support") {
|
||||
description = "Spring Context Support"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-beans"))
|
||||
@@ -443,8 +467,6 @@ project("spring-web") {
|
||||
compile(project(":spring-context"))
|
||||
optional(project(":spring-oxm")) // for MarshallingHttpMessageConverter
|
||||
compile("aopalliance:aopalliance:1.0")
|
||||
optional("com.caucho:hessian:3.2.1")
|
||||
optional("rome:rome:1.0")
|
||||
optional("javax.el:el-api:1.0")
|
||||
optional("javax.faces:jsf-api:1.2_08")
|
||||
provided("javax.portlet:portlet-api:2.0")
|
||||
@@ -453,6 +475,8 @@ project("spring-web") {
|
||||
optional("javax.xml:jaxrpc-api:1.1")
|
||||
provided("javax.xml.soap:saaj-api:1.3")
|
||||
provided("javax.activation:activation:1.1")
|
||||
optional("com.caucho:hessian:3.2.1")
|
||||
optional("rome:rome:1.0")
|
||||
optional("commons-fileupload:commons-fileupload:1.2")
|
||||
optional("commons-io:commons-io:1.3")
|
||||
optional("commons-httpclient:commons-httpclient:3.1")
|
||||
@@ -487,16 +511,16 @@ project("spring-orm") {
|
||||
|
||||
dependencies {
|
||||
compile("aopalliance:aopalliance:1.0")
|
||||
optional("javax.persistence:persistence-api:1.0")
|
||||
optional("org.eclipse.persistence:org.eclipse.persistence.core:1.0.1")
|
||||
optional("org.eclipse.persistence:org.eclipse.persistence.jpa:1.0.1")
|
||||
optional("org.hibernate:hibernate-core:3.3.2.GA")
|
||||
optional("org.hibernate:hibernate-annotations:3.4.0.GA")
|
||||
optional("org.hibernate:hibernate-entitymanager:3.4.0.GA")
|
||||
optional("org.apache.openjpa:openjpa:1.1.0")
|
||||
optional("org.eclipse.persistence:org.eclipse.persistence.core:1.0.1")
|
||||
optional("org.eclipse.persistence:org.eclipse.persistence.jpa:1.0.1")
|
||||
optional("toplink.essentials:toplink-essentials:2.0-41b")
|
||||
optional("javax.jdo:jdo-api:3.0")
|
||||
optional("org.apache.ibatis:ibatis-sqlmap:2.3.4.726")
|
||||
optional("javax.persistence:persistence-api:1.0")
|
||||
provided("javax.servlet:servlet-api:2.5")
|
||||
testCompile("javax.servlet:javax.servlet-api:3.0.1")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
@@ -517,11 +541,12 @@ project("spring-orm") {
|
||||
project("spring-orm-hibernate4") {
|
||||
description = "Spring Object/Relational Mapping - Hibernate 4 support"
|
||||
merge.into = project(":spring-orm")
|
||||
|
||||
dependencies {
|
||||
provided(project(":spring-tx"))
|
||||
provided(project(":spring-jdbc"))
|
||||
optional("org.hibernate:hibernate-core:4.1.0.Final")
|
||||
optional("org.hibernate:hibernate-entitymanager:4.1.0.Final")
|
||||
optional("org.hibernate:hibernate-core:4.1.9.Final")
|
||||
optional("org.hibernate:hibernate-entitymanager:4.1.9.Final")
|
||||
optional(project(":spring-web"))
|
||||
optional("javax.servlet:servlet-api:2.5")
|
||||
}
|
||||
@@ -529,6 +554,7 @@ project("spring-orm-hibernate4") {
|
||||
|
||||
project("spring-webmvc") {
|
||||
description = "Spring Web MVC"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-expression"))
|
||||
@@ -541,7 +567,6 @@ project("spring-webmvc") {
|
||||
optional("org.apache.tiles:tiles-core:2.1.2")
|
||||
optional("org.apache.tiles:tiles-jsp:2.1.2")
|
||||
optional("org.apache.tiles:tiles-servlet:2.1.2")
|
||||
optional("velocity-tools:velocity-tools-view:1.4")
|
||||
optional("net.sourceforge.jexcelapi:jxl:2.6.3")
|
||||
optional("org.apache.poi:poi:3.0.2-FINAL")
|
||||
optional("com.lowagie:itext:2.1.7")
|
||||
@@ -550,6 +575,7 @@ project("spring-webmvc") {
|
||||
}
|
||||
optional("rome:rome:1.0")
|
||||
optional("velocity:velocity:1.5")
|
||||
optional("velocity-tools:velocity-tools-view:1.4")
|
||||
optional("org.freemarker:freemarker:2.3.15")
|
||||
optional("org.codehaus.jackson:jackson-mapper-asl:1.4.2")
|
||||
optional("com.fasterxml.jackson.core:jackson-databind:2.0.1")
|
||||
@@ -588,6 +614,7 @@ project("spring-webmvc") {
|
||||
project("spring-webmvc-tiles3") {
|
||||
description = "Spring Framework Tiles3 Integration"
|
||||
merge.into = project(":spring-webmvc")
|
||||
|
||||
dependencies {
|
||||
provided(project(":spring-context"))
|
||||
provided(project(":spring-web"))
|
||||
@@ -618,6 +645,7 @@ project("spring-webmvc-tiles3") {
|
||||
|
||||
project("spring-webmvc-portlet") {
|
||||
description = "Spring Web Portlet"
|
||||
|
||||
dependencies {
|
||||
provided("javax.servlet:servlet-api:2.5")
|
||||
provided("javax.portlet:portlet-api:2.0")
|
||||
@@ -636,21 +664,6 @@ project("spring-webmvc-portlet") {
|
||||
project("spring-test") {
|
||||
description = "Spring TestContext Framework"
|
||||
|
||||
task testNG(type: Test) {
|
||||
useTestNG()
|
||||
// "TestCase" classes are run by other test classes, not the build.
|
||||
exclude "**/*TestCase.class"
|
||||
// Generate TestNG reports alongside JUnit reports.
|
||||
testReport true
|
||||
}
|
||||
|
||||
test {
|
||||
dependsOn testNG
|
||||
useJUnit()
|
||||
// "TestCase" classes are run by other test classes, not the build.
|
||||
exclude(["**/*TestCase.class", "**/*TestSuite.class"])
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
optional(project(":spring-beans"))
|
||||
@@ -675,6 +688,26 @@ project("spring-test") {
|
||||
testCompile "org.slf4j:slf4j-jcl:${slf4jVersion}"
|
||||
testCompile("hsqldb:hsqldb:${hsqldbVersion}")
|
||||
}
|
||||
|
||||
task testNG(type: Test) {
|
||||
useTestNG()
|
||||
scanForTestClasses = false
|
||||
include "**/testng/*.*"
|
||||
exclude "**/FailingBeforeAndAfterMethodsTests.class"
|
||||
// "TestCase" classes are run by other test classes, not the build.
|
||||
exclude "**/*TestCase.class"
|
||||
// Generate TestNG reports alongside JUnit reports.
|
||||
testReport true
|
||||
}
|
||||
|
||||
test {
|
||||
dependsOn testNG
|
||||
useJUnit()
|
||||
exclude "**/testng/*.*"
|
||||
// "TestCase" classes are run by other test classes, not the build.
|
||||
exclude(["**/*TestCase.class", "**/*TestSuite.class"])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
project("spring-test-mvc") {
|
||||
@@ -695,11 +728,9 @@ project("spring-test-mvc") {
|
||||
testCompile(project(":spring-context-support"))
|
||||
testCompile(project(":spring-oxm"))
|
||||
testCompile("com.thoughtworks.xstream:xstream:1.3.1")
|
||||
testCompile("cglib:cglib-nodep:2.2")
|
||||
testCompile("rome:rome:1.0")
|
||||
testCompile("javax.activation:activation:1.1")
|
||||
testCompile("javax.mail:mail:1.4")
|
||||
testCompile("javax.xml.bind:jaxb-api:2.2.6")
|
||||
testCompile("org.apache.tiles:tiles-request-api:1.0.1")
|
||||
testCompile("org.apache.tiles:tiles-api:3.0.1")
|
||||
testCompile("org.apache.tiles:tiles-core:3.0.1") {
|
||||
@@ -730,6 +761,7 @@ project("spring-struts") {
|
||||
project("spring-aspects") {
|
||||
description = "Spring Aspects"
|
||||
apply from: "aspects.gradle"
|
||||
|
||||
dependencies {
|
||||
optional(project(":spring-beans")) // for @Configurable support
|
||||
optional(project(":spring-aop")) // for @Async support
|
||||
@@ -747,6 +779,7 @@ project("spring-aspects") {
|
||||
compile(project(":spring-beans")) // for "p" namespace visibility
|
||||
testCompile(project(":spring-test"))
|
||||
}
|
||||
|
||||
eclipse.project {
|
||||
natures += "org.eclipse.ajdt.ui.ajnature"
|
||||
buildCommands = [new org.gradle.plugins.ide.eclipse.model.
|
||||
@@ -759,7 +792,7 @@ configure(rootProject) {
|
||||
|
||||
apply plugin: "docbook-reference"
|
||||
apply plugin: "groovy"
|
||||
apply plugin: "detect-split-packages"
|
||||
// apply plugin: "detect-split-packages"
|
||||
apply from: "${gradleScriptDir}/jdiff.gradle"
|
||||
|
||||
reference {
|
||||
@@ -767,9 +800,11 @@ configure(rootProject) {
|
||||
pdfFilename = "spring-framework-reference.pdf"
|
||||
}
|
||||
|
||||
detectSplitPackages {
|
||||
projectsToScan -= project(":spring-instrument-tomcat")
|
||||
}
|
||||
// TODO: DetectSplitPackagesPlugin fails in line 154 due to method not found on java.io.File.
|
||||
// TODO: Possibly related to user rights or OS differences on OpenJDK 8; works fine on JDK 7.
|
||||
// detectSplitPackages {
|
||||
// projectsToScan -= project(":spring-instrument-tomcat")
|
||||
// }
|
||||
|
||||
// don't publish the default jar for the root project
|
||||
configurations.archives.artifacts.clear()
|
||||
@@ -786,7 +821,7 @@ configure(rootProject) {
|
||||
testCompile(project(":spring-web"))
|
||||
testCompile(project(":spring-webmvc-portlet"))
|
||||
testCompile(project(":spring-orm"))
|
||||
testCompile("org.hibernate:hibernate-core:4.1.0.Final")
|
||||
testCompile("org.hibernate:hibernate-core:4.1.9.Final")
|
||||
testCompile("javax.servlet:servlet-api:2.5")
|
||||
testCompile("javax.portlet:portlet-api:2.0")
|
||||
testCompile("javax.inject:javax.inject:1")
|
||||
@@ -812,6 +847,9 @@ configure(rootProject) {
|
||||
options.stylesheetFile = file("src/api/stylesheet.css")
|
||||
options.splitIndex = true
|
||||
options.links(project.ext.javadocLinks)
|
||||
if(JavaVersion.current().isJava8Compatible()) {
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
}
|
||||
|
||||
source subprojects.collect { project ->
|
||||
project.sourceSets.main.allJava
|
||||
@@ -822,7 +860,7 @@ configure(rootProject) {
|
||||
|
||||
doFirst {
|
||||
classpath = files(
|
||||
// ensure servlet 3.x and Hibernate 4.x have precedence on the Javadoc
|
||||
// ensure Servlet 3.x and Hibernate 4.x have precedence on the Javadoc
|
||||
// classpath over their respective 2.5 and 3.x variants
|
||||
project(":spring-webmvc").sourceSets.main.compileClasspath.files.find { it =~ "servlet-api" },
|
||||
rootProject.sourceSets.test.compileClasspath.files.find { it =~ "hibernate-core" },
|
||||
@@ -959,7 +997,7 @@ configure(rootProject) {
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
description = "Generates gradlew[.bat] scripts"
|
||||
gradleVersion = "1.3"
|
||||
gradleVersion = "1.6"
|
||||
|
||||
doLast() {
|
||||
def gradleOpts = "-XX:MaxPermSize=1024m -Xmx1024m"
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ import org.gradle.api.tasks.TaskAction
|
||||
public class DetectSplitPackagesPlugin implements Plugin<Project> {
|
||||
public void apply(Project project) {
|
||||
def tasks = project.tasks
|
||||
Task detectSplitPackages = tasks.add("detectSplitPackages", DetectSplitPackagesTask.class)
|
||||
Task detectSplitPackages = tasks.create("detectSplitPackages", DetectSplitPackagesTask.class)
|
||||
if (tasks.asMap.containsKey("check")) {
|
||||
tasks.getByName("check").dependsOn detectSplitPackages
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ class MergePlugin implements Plugin<Project> {
|
||||
project.plugins.apply(IdeaPlugin)
|
||||
|
||||
MergeModel model = project.extensions.create("merge", MergeModel)
|
||||
project.configurations.add("merging")
|
||||
Configuration runtimeMerge = project.configurations.add("runtimeMerge")
|
||||
project.configurations.create("merging")
|
||||
Configuration runtimeMerge = project.configurations.create("runtimeMerge")
|
||||
|
||||
// Ensure the IDE can reference merged projects
|
||||
project.eclipse.classpath.plusConfigurations += [runtimeMerge]
|
||||
@@ -121,7 +121,7 @@ class MergePlugin implements Plugin<Project> {
|
||||
project.configurations.each { configuration ->
|
||||
Conf2ScopeMapping mapping = project.conf2ScopeMappings.getMapping([configuration])
|
||||
if(mapping.scope) {
|
||||
Configuration intoConfiguration = project.merge.into.configurations.add(
|
||||
Configuration intoConfiguration = project.merge.into.configurations.create(
|
||||
project.name + "-" + configuration.name)
|
||||
configuration.excludeRules.each {
|
||||
configuration.exclude([
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=3.2.3.BUILD-SNAPSHOT
|
||||
version=3.2.4.RELEASE
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+4
-4
@@ -1,6 +1,6 @@
|
||||
#Wed Nov 28 09:14:59 PST 2012
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
#Tue Jul 30 09:29:28 PDT 2013
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.6-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.3-bin.zip
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
|
||||
+12
-14
@@ -45,43 +45,41 @@ public class AspectJWeaverMessageHandler implements IMessageHandler {
|
||||
|
||||
private static final String AJ_ID = "[AspectJ] ";
|
||||
|
||||
private static final Log LOGGER = LogFactory.getLog("AspectJ Weaver");
|
||||
private static final Log logger = LogFactory.getLog("AspectJ Weaver");
|
||||
|
||||
|
||||
public boolean handleMessage(IMessage message) throws AbortException {
|
||||
Kind messageKind = message.getKind();
|
||||
|
||||
if (messageKind == IMessage.DEBUG) {
|
||||
if (LOGGER.isDebugEnabled() || LOGGER.isTraceEnabled()) {
|
||||
LOGGER.debug(makeMessageFor(message));
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if ((messageKind == IMessage.INFO) || (messageKind == IMessage.WEAVEINFO)) {
|
||||
if (LOGGER.isInfoEnabled()) {
|
||||
LOGGER.info(makeMessageFor(message));
|
||||
else if (messageKind == IMessage.INFO || messageKind == IMessage.WEAVEINFO) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (messageKind == IMessage.WARNING) {
|
||||
if (LOGGER.isWarnEnabled()) {
|
||||
LOGGER.warn(makeMessageFor(message));
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (messageKind == IMessage.ERROR) {
|
||||
if (LOGGER.isErrorEnabled()) {
|
||||
LOGGER.error(makeMessageFor(message));
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (messageKind == IMessage.ABORT) {
|
||||
if (LOGGER.isFatalEnabled()) {
|
||||
LOGGER.fatal(makeMessageFor(message));
|
||||
if (logger.isFatalEnabled()) {
|
||||
logger.fatal(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.aop.aspectj.annotation;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -105,7 +106,7 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
|
||||
if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) {
|
||||
return ((Ordered) this.beanFactory.getBean(this.name)).getOrder();
|
||||
}
|
||||
Order order = type.getAnnotation(Order.class);
|
||||
Order order = AnnotationUtils.findAnnotation(type, Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.springframework.aop.aspectj.SimpleAspectInstanceFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
/**
|
||||
@@ -58,7 +59,7 @@ public class SimpleMetadataAwareAspectInstanceFactory extends SimpleAspectInstan
|
||||
*/
|
||||
@Override
|
||||
protected int getOrderForAspectClass(Class<?> aspectClass) {
|
||||
Order order = aspectClass.getAnnotation(Order.class);
|
||||
Order order = AnnotationUtils.findAnnotation(aspectClass, Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.springframework.aop.aspectj.SingletonAspectInstanceFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
/**
|
||||
@@ -59,7 +60,7 @@ public class SingletonMetadataAwareAspectInstanceFactory extends SingletonAspect
|
||||
*/
|
||||
@Override
|
||||
protected int getOrderForAspectClass(Class<?> aspectClass) {
|
||||
Order order = aspectClass.getAnnotation(Order.class);
|
||||
Order order = AnnotationUtils.findAnnotation(aspectClass, Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,7 +34,7 @@ import org.springframework.cglib.proxy.Factory;
|
||||
import org.springframework.cglib.proxy.MethodInterceptor;
|
||||
import org.springframework.cglib.proxy.MethodProxy;
|
||||
import org.springframework.cglib.proxy.NoOp;
|
||||
import org.springframework.cglib.transform.impl.UndeclaredThrowableStrategy;
|
||||
import org.springframework.cglib.transform.impl.MemorySafeUndeclaredThrowableStrategy;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
@@ -181,7 +181,7 @@ final class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
}
|
||||
enhancer.setSuperclass(proxySuperClass);
|
||||
enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
|
||||
enhancer.setStrategy(new MemorySafeUndeclaredThrowableStrategy(UndeclaredThrowableException.class));
|
||||
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
|
||||
enhancer.setInterceptDuringConstruction(false);
|
||||
|
||||
|
||||
+2
-3
@@ -87,7 +87,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
|
||||
/**
|
||||
* Determine the specific executor to use when executing the given method.
|
||||
* @return the executor to use (never {@code null})
|
||||
* @return the executor to use (or {@code null}, but just if no default executor has been set)
|
||||
*/
|
||||
protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
|
||||
AsyncTaskExecutor executor = this.executors.get(method);
|
||||
@@ -101,8 +101,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
this.beanFactory, Executor.class, qualifier);
|
||||
}
|
||||
else if (executorToUse == null) {
|
||||
throw new IllegalStateException("No executor qualifier specified and no default executor set on " +
|
||||
getClass().getSimpleName() + " either");
|
||||
return null;
|
||||
}
|
||||
executor = (executorToUse instanceof AsyncTaskExecutor ?
|
||||
(AsyncTaskExecutor) executorToUse : new TaskExecutorAdapter(executorToUse));
|
||||
|
||||
+7
-1
@@ -82,7 +82,13 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport
|
||||
Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
|
||||
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
|
||||
|
||||
Future<?> result = determineAsyncExecutor(specificMethod).submit(
|
||||
AsyncTaskExecutor executor = determineAsyncExecutor(specificMethod);
|
||||
if (executor == null) {
|
||||
throw new IllegalStateException(
|
||||
"No executor specified and no default executor set on AsyncExecutionInterceptor either");
|
||||
}
|
||||
|
||||
Future<?> result = executor.submit(
|
||||
new Callable<Object>() {
|
||||
public Object call() throws Exception {
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -102,8 +102,9 @@ public abstract class MethodMatchers {
|
||||
@SuppressWarnings("serial")
|
||||
private static class UnionMethodMatcher implements IntroductionAwareMethodMatcher, Serializable {
|
||||
|
||||
private MethodMatcher mm1;
|
||||
private MethodMatcher mm2;
|
||||
private final MethodMatcher mm1;
|
||||
|
||||
private final MethodMatcher mm2;
|
||||
|
||||
public UnionMethodMatcher(MethodMatcher mm1, MethodMatcher mm2) {
|
||||
Assert.notNull(mm1, "First MethodMatcher must not be null");
|
||||
@@ -168,6 +169,7 @@ public abstract class MethodMatchers {
|
||||
private static class ClassFilterAwareUnionMethodMatcher extends UnionMethodMatcher {
|
||||
|
||||
private final ClassFilter cf1;
|
||||
|
||||
private final ClassFilter cf2;
|
||||
|
||||
public ClassFilterAwareUnionMethodMatcher(MethodMatcher mm1, ClassFilter cf1, MethodMatcher mm2, ClassFilter cf2) {
|
||||
@@ -191,11 +193,17 @@ public abstract class MethodMatchers {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof ClassFilterAwareUnionMethodMatcher)) {
|
||||
if (!super.equals(other)) {
|
||||
return false;
|
||||
}
|
||||
ClassFilterAwareUnionMethodMatcher that = (ClassFilterAwareUnionMethodMatcher) other;
|
||||
return (this.cf1.equals(that.cf1) && this.cf2.equals(that.cf2) && super.equals(other));
|
||||
ClassFilter otherCf1 = ClassFilter.TRUE;
|
||||
ClassFilter otherCf2 = ClassFilter.TRUE;
|
||||
if (other instanceof ClassFilterAwareUnionMethodMatcher) {
|
||||
ClassFilterAwareUnionMethodMatcher cfa = (ClassFilterAwareUnionMethodMatcher) other;
|
||||
otherCf1 = cfa.cf1;
|
||||
otherCf2 = cfa.cf2;
|
||||
}
|
||||
return (this.cf1.equals(otherCf1) && this.cf2.equals(otherCf2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,8 +214,9 @@ public abstract class MethodMatchers {
|
||||
@SuppressWarnings("serial")
|
||||
private static class IntersectionMethodMatcher implements IntroductionAwareMethodMatcher, Serializable {
|
||||
|
||||
private MethodMatcher mm1;
|
||||
private MethodMatcher mm2;
|
||||
private final MethodMatcher mm1;
|
||||
|
||||
private final MethodMatcher mm2;
|
||||
|
||||
public IntersectionMethodMatcher(MethodMatcher mm1, MethodMatcher mm2) {
|
||||
Assert.notNull(mm1, "First MethodMatcher must not be null");
|
||||
|
||||
@@ -43,6 +43,7 @@ public final class MethodMatchersTests {
|
||||
|
||||
private final Method IOTHER_ABSQUATULATE;
|
||||
|
||||
|
||||
public MethodMatchersTests() throws Exception {
|
||||
EXCEPTION_GETMESSAGE = Exception.class.getMethod("getMessage", (Class[]) null);
|
||||
ITESTBEAN_GETAGE = ITestBean.class.getMethod("getAge", (Class[]) null);
|
||||
@@ -50,6 +51,7 @@ public final class MethodMatchersTests {
|
||||
IOTHER_ABSQUATULATE = IOther.class.getMethod("absquatulate", (Class[]) null);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDefaultMatchesAll() throws Exception {
|
||||
MethodMatcher defaultMm = MethodMatcher.TRUE;
|
||||
@@ -99,23 +101,33 @@ public final class MethodMatchersTests {
|
||||
assertTrue("Matched setAge method", union.matches(ITESTBEAN_SETAGE, TestBean.class));
|
||||
assertTrue("Matched getAge method", union.matches(ITESTBEAN_GETAGE, TestBean.class));
|
||||
assertFalse("Didn't matched absquatulate method", union.matches(IOTHER_ABSQUATULATE, TestBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionEquals() {
|
||||
MethodMatcher first = MethodMatchers.union(MethodMatcher.TRUE, MethodMatcher.TRUE);
|
||||
MethodMatcher second = new ComposablePointcut(MethodMatcher.TRUE).union(new ComposablePointcut(MethodMatcher.TRUE)).getMethodMatcher();
|
||||
assertTrue(first.equals(second));
|
||||
assertTrue(second.equals(first));
|
||||
}
|
||||
|
||||
|
||||
public static class StartsWithMatcher extends StaticMethodMatcher {
|
||||
private String prefix;
|
||||
|
||||
private final String prefix;
|
||||
|
||||
public StartsWithMatcher(String s) {
|
||||
this.prefix = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method m, Class<?> targetClass) {
|
||||
return m.getName().startsWith(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class TestDynamicMethodMatcherWhichMatches extends DynamicMethodMatcher {
|
||||
|
||||
@Override
|
||||
public boolean matches(Method m, Class<?> targetClass, Object[] args) {
|
||||
return true;
|
||||
@@ -123,6 +135,7 @@ public final class MethodMatchersTests {
|
||||
}
|
||||
|
||||
private static class TestDynamicMethodMatcherWhichDoesNotMatch extends DynamicMethodMatcher {
|
||||
|
||||
@Override
|
||||
public boolean matches(Method m, Class<?> targetClass, Object[] args) {
|
||||
return false;
|
||||
|
||||
@@ -12,8 +12,8 @@ configurations {
|
||||
tasks.getByName("idea").onlyIf { false }
|
||||
tasks.getByName("ideaModule").onlyIf { false }
|
||||
|
||||
task compileJava(overwrite: true) {
|
||||
dependsOn JavaPlugin.PROCESS_RESOURCES_TASK_NAME
|
||||
compileJava {
|
||||
actions = []
|
||||
dependsOn configurations.ajc.getTaskDependencyFromProjectDependency(true, "compileJava")
|
||||
|
||||
def outputDir = project.sourceSets.main.output.classesDir
|
||||
@@ -44,8 +44,8 @@ task compileJava(overwrite: true) {
|
||||
}
|
||||
}
|
||||
|
||||
task compileTestJava(overwrite: true) {
|
||||
dependsOn JavaPlugin.PROCESS_TEST_RESOURCES_TASK_NAME
|
||||
compileTestJava {
|
||||
actions = []
|
||||
dependsOn configurations.ajc.getTaskDependencyFromProjectDependency(true, "compileTestJava")
|
||||
dependsOn jar
|
||||
|
||||
|
||||
+9
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -58,15 +58,19 @@ public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implem
|
||||
* allowing for ASM-based processing and avoidance of early loading of the bean class.
|
||||
* Note that this constructor is functionally equivalent to
|
||||
* {@link org.springframework.context.annotation.ScannedGenericBeanDefinition
|
||||
* ScannedGenericBeanDefinition}, however the semantics of the latter indicate that
|
||||
* a bean was discovered specifically via component-scanning as opposed to other
|
||||
* means.
|
||||
* ScannedGenericBeanDefinition}, however the semantics of the latter indicate that a
|
||||
* bean was discovered specifically via component-scanning as opposed to other means.
|
||||
* @param metadata the annotation metadata for the bean class in question
|
||||
* @since 3.1.1
|
||||
*/
|
||||
public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata) {
|
||||
Assert.notNull(metadata, "AnnotationMetadata must not be null");
|
||||
setBeanClassName(metadata.getClassName());
|
||||
if (metadata instanceof StandardAnnotationMetadata) {
|
||||
setBeanClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass());
|
||||
}
|
||||
else {
|
||||
setBeanClassName(metadata.getClassName());
|
||||
}
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -185,7 +185,7 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
* @see #AUTOWIRE_BY_TYPE
|
||||
* @see #AUTOWIRE_CONSTRUCTOR
|
||||
*/
|
||||
Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
|
||||
Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
|
||||
|
||||
/**
|
||||
* Instantiate a new bean instance of the given class with the specified autowire
|
||||
@@ -213,7 +213,7 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
* @see #applyBeanPostProcessorsBeforeInitialization
|
||||
* @see #applyBeanPostProcessorsAfterInitialization
|
||||
*/
|
||||
Object autowire(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
|
||||
Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
|
||||
|
||||
/**
|
||||
* Autowire the bean properties of the given bean instance by name or type.
|
||||
|
||||
+25
-31
@@ -171,6 +171,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
setParentBeanFactory(parentBeanFactory);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the instantiation strategy to use for creating bean instances.
|
||||
* Default is CglibSubclassingInstantiationStrategy.
|
||||
@@ -243,7 +244,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* Ignore the given dependency type for autowiring:
|
||||
* for example, String. Default is none.
|
||||
*/
|
||||
public void ignoreDependencyType(Class type) {
|
||||
public void ignoreDependencyType(Class<?> type) {
|
||||
this.ignoredDependencyTypes.add(type);
|
||||
}
|
||||
|
||||
@@ -257,11 +258,10 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.context.ApplicationContextAware
|
||||
*/
|
||||
public void ignoreDependencyInterface(Class ifc) {
|
||||
public void ignoreDependencyInterface(Class<?> ifc) {
|
||||
this.ignoredDependencyInterfaces.add(ifc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
|
||||
super.copyConfigurationFrom(otherFactory);
|
||||
@@ -305,12 +305,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
RootBeanDefinition bd = null;
|
||||
if (mbd instanceof RootBeanDefinition) {
|
||||
RootBeanDefinition rbd = (RootBeanDefinition) mbd;
|
||||
if (rbd.isPrototype()) {
|
||||
bd = rbd;
|
||||
}
|
||||
bd = (rbd.isPrototype() ? rbd : rbd.cloneBeanDefinition());
|
||||
}
|
||||
if (bd == null) {
|
||||
bd = new RootBeanDefinition(mbd);
|
||||
if (!mbd.isPrototype()) {
|
||||
if (bd == null) {
|
||||
bd = new RootBeanDefinition(mbd);
|
||||
}
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
bd.allowCaching = false;
|
||||
}
|
||||
@@ -329,14 +329,14 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
// Specialized methods for fine-grained control over the bean lifecycle
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
public Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
|
||||
public Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
|
||||
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
|
||||
RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
return createBean(beanClass.getName(), bd, null);
|
||||
}
|
||||
|
||||
public Object autowire(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
|
||||
public Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
|
||||
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
|
||||
final RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
@@ -346,10 +346,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
else {
|
||||
Object bean;
|
||||
final BeanFactory parent = this;
|
||||
|
||||
if (System.getSecurityManager() != null) {
|
||||
bean = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
|
||||
public Object run() {
|
||||
return getInstantiationStrategy().instantiate(bd, null, parent);
|
||||
}
|
||||
@@ -358,7 +356,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
else {
|
||||
bean = getInstantiationStrategy().instantiate(bd, null, parent);
|
||||
}
|
||||
|
||||
populateBean(beanClass.getName(), bd, new BeanWrapperImpl(bean));
|
||||
return bean;
|
||||
}
|
||||
@@ -490,7 +487,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
instanceWrapper = createBeanInstance(beanName, mbd, args);
|
||||
}
|
||||
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
|
||||
Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
|
||||
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
|
||||
|
||||
// Allow post-processors to modify the merged bean definition.
|
||||
synchronized (mbd.postProcessingLock) {
|
||||
@@ -587,7 +584,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
|
||||
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
|
||||
Class predicted = ibp.predictBeanType(targetType, beanName);
|
||||
Class<?> predicted = ibp.predictBeanType(targetType, beanName);
|
||||
if (predicted != null && (typesToMatch.length != 1 || !FactoryBean.class.equals(typesToMatch[0]) ||
|
||||
FactoryBean.class.isAssignableFrom(predicted))) {
|
||||
return predicted;
|
||||
@@ -688,22 +685,19 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
// Try to obtain the FactoryBean's object type without instantiating it at all.
|
||||
BeanDefinition fbDef = getBeanDefinition(factoryBeanName);
|
||||
if (fbDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) fbDef).hasBeanClass()) {
|
||||
Class<?> fbClass = ((AbstractBeanDefinition) fbDef).getBeanClass();
|
||||
if (ClassUtils.isCglibProxyClass(fbClass)) {
|
||||
// CGLIB subclass methods hide generic parameters. look at the superclass.
|
||||
fbClass = fbClass.getSuperclass();
|
||||
}
|
||||
// CGLIB subclass methods hide generic parameters; look at the original user class.
|
||||
Class<?> fbClass = ClassUtils.getUserClass(((AbstractBeanDefinition) fbDef).getBeanClass());
|
||||
// Find the given factory method, taking into account that in the case of
|
||||
// @Bean methods, there may be parameters present.
|
||||
ReflectionUtils.doWithMethods(fbClass,
|
||||
new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
if (method.getName().equals(factoryMethodName) &&
|
||||
FactoryBean.class.isAssignableFrom(method.getReturnType())) {
|
||||
objectType.value = GenericTypeResolver.resolveReturnTypeArgument(method, FactoryBean.class);
|
||||
new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
if (method.getName().equals(factoryMethodName) &&
|
||||
FactoryBean.class.isAssignableFrom(method.getReturnType())) {
|
||||
objectType.value = GenericTypeResolver.resolveReturnTypeArgument(method, FactoryBean.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
if (objectType.value != null) {
|
||||
return objectType.value;
|
||||
}
|
||||
@@ -836,7 +830,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @throws BeansException if any post-processing failed
|
||||
* @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
|
||||
*/
|
||||
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class beanType, String beanName)
|
||||
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)
|
||||
throws BeansException {
|
||||
|
||||
try {
|
||||
@@ -887,7 +881,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @throws BeansException if any post-processing failed
|
||||
* @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
|
||||
*/
|
||||
protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName)
|
||||
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
|
||||
throws BeansException {
|
||||
|
||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||
@@ -916,7 +910,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
*/
|
||||
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
|
||||
// Make sure bean class is actually resolved at this point.
|
||||
Class beanClass = resolveBeanClass(mbd, beanName);
|
||||
Class<?> beanClass = resolveBeanClass(mbd, beanName);
|
||||
|
||||
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
@@ -968,7 +962,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @throws org.springframework.beans.BeansException in case of errors
|
||||
* @see org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
|
||||
*/
|
||||
protected Constructor[] determineConstructorsFromBeanPostProcessors(Class beanClass, String beanName)
|
||||
protected Constructor[] determineConstructorsFromBeanPostProcessors(Class<?> beanClass, String beanName)
|
||||
throws BeansException {
|
||||
|
||||
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -54,7 +54,7 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
private Environment environment = new StandardEnvironment();
|
||||
private Environment environment;
|
||||
|
||||
private BeanNameGenerator beanNameGenerator = new DefaultBeanNameGenerator();
|
||||
|
||||
@@ -90,7 +90,7 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable
|
||||
|
||||
// Inherit Environment if possible
|
||||
if (this.registry instanceof EnvironmentCapable) {
|
||||
this.environment = ((EnvironmentCapable)this.registry).getEnvironment();
|
||||
this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
|
||||
}
|
||||
else {
|
||||
this.environment = new StandardEnvironment();
|
||||
|
||||
+19
-13
@@ -511,26 +511,32 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> beanClass = predictBeanType(beanName, mbd, typesToMatch);
|
||||
if (beanClass == null) {
|
||||
Class<?> beanType = predictBeanType(beanName, mbd, typesToMatch);
|
||||
if (beanType == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check bean class whether we're dealing with a FactoryBean.
|
||||
if (FactoryBean.class.isAssignableFrom(beanClass)) {
|
||||
if (FactoryBean.class.isAssignableFrom(beanType)) {
|
||||
if (!BeanFactoryUtils.isFactoryDereference(name)) {
|
||||
// If it's a FactoryBean, we want to look at what it creates, not the factory class.
|
||||
Class<?> type = getTypeForFactoryBean(beanName, mbd);
|
||||
return (type != null && typeToMatch.isAssignableFrom(type));
|
||||
}
|
||||
else {
|
||||
return typeToMatch.isAssignableFrom(beanClass);
|
||||
beanType = getTypeForFactoryBean(beanName, mbd);
|
||||
if (beanType == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return !BeanFactoryUtils.isFactoryDereference(name) &&
|
||||
typeToMatch.isAssignableFrom(beanClass);
|
||||
else if (BeanFactoryUtils.isFactoryDereference(name)) {
|
||||
// Special case: A SmartInstantiationAwareBeanPostProcessor returned a non-FactoryBean
|
||||
// type but we nevertheless are being asked to dereference a FactoryBean...
|
||||
// Let's check the original bean class and proceed with it if it is a FactoryBean.
|
||||
beanType = predictBeanType(beanName, mbd, FactoryBean.class);
|
||||
if (beanType == null || !FactoryBean.class.isAssignableFrom(beanType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return typeToMatch.isAssignableFrom(beanType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1335,8 +1341,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
* @param mbd the corresponding bean definition
|
||||
*/
|
||||
protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
|
||||
Class<?> beanClass = predictBeanType(beanName, mbd, FactoryBean.class);
|
||||
return (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass));
|
||||
Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
|
||||
return (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
@@ -98,7 +97,7 @@ public class ChildBeanDefinition extends AbstractBeanDefinition {
|
||||
* @param pvs the property values to apply
|
||||
*/
|
||||
public ChildBeanDefinition(
|
||||
String parentName, Class beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
|
||||
String parentName, Class<?> beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
|
||||
|
||||
super(cargs, pvs);
|
||||
this.parentName = parentName;
|
||||
@@ -128,7 +127,7 @@ public class ChildBeanDefinition extends AbstractBeanDefinition {
|
||||
* @param original the original bean definition to copy from
|
||||
*/
|
||||
public ChildBeanDefinition(ChildBeanDefinition original) {
|
||||
super((BeanDefinition) original);
|
||||
super(original);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+8
-6
@@ -31,7 +31,6 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -460,12 +459,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
|
||||
public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) {
|
||||
Set<String> beanNames = new LinkedHashSet<String>(getBeanDefinitionCount());
|
||||
beanNames.addAll(Arrays.asList(getBeanDefinitionNames()));
|
||||
beanNames.addAll(Arrays.asList(getSingletonNames()));
|
||||
Map<String, Object> results = new LinkedHashMap<String, Object>();
|
||||
for (String beanName : beanNames) {
|
||||
if (findAnnotationOnBean(beanName, annotationType) != null) {
|
||||
for (String beanName : getBeanDefinitionNames()) {
|
||||
BeanDefinition beanDefinition = getBeanDefinition(beanName);
|
||||
if (!beanDefinition.isAbstract() && findAnnotationOnBean(beanName, annotationType) != null) {
|
||||
results.put(beanName, getBean(beanName));
|
||||
}
|
||||
}
|
||||
for (String beanName : getSingletonNames()) {
|
||||
if (!results.containsKey(beanName) && findAnnotationOnBean(beanName, annotationType) != null) {
|
||||
results.put(beanName, getBean(beanName));
|
||||
}
|
||||
}
|
||||
|
||||
+8
-11
@@ -107,7 +107,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
* Create a new RootBeanDefinition for a singleton.
|
||||
* @param beanClass the class of the bean to instantiate
|
||||
*/
|
||||
public RootBeanDefinition(Class beanClass) {
|
||||
public RootBeanDefinition(Class<?> beanClass) {
|
||||
super();
|
||||
setBeanClass(beanClass);
|
||||
}
|
||||
@@ -147,7 +147,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
* @param dependencyCheck whether to perform a dependency check for objects
|
||||
* (not applicable to autowiring a constructor, thus ignored there)
|
||||
*/
|
||||
public RootBeanDefinition(Class beanClass, int autowireMode, boolean dependencyCheck) {
|
||||
public RootBeanDefinition(Class<?> beanClass, int autowireMode, boolean dependencyCheck) {
|
||||
super();
|
||||
setBeanClass(beanClass);
|
||||
setAutowireMode(autowireMode);
|
||||
@@ -191,7 +191,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
* @param cargs the constructor argument values to apply
|
||||
* @param pvs the property values to apply
|
||||
*/
|
||||
public RootBeanDefinition(Class beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
|
||||
public RootBeanDefinition(Class<?> beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
|
||||
super(cargs, pvs);
|
||||
setBeanClass(beanClass);
|
||||
}
|
||||
@@ -225,7 +225,11 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
* @param original the original bean definition to copy from
|
||||
*/
|
||||
public RootBeanDefinition(RootBeanDefinition original) {
|
||||
this((BeanDefinition) original);
|
||||
super(original);
|
||||
this.decoratedDefinition = original.decoratedDefinition;
|
||||
this.allowCaching = original.allowCaching;
|
||||
this.targetType = original.targetType;
|
||||
this.isFactoryMethodUnique = original.isFactoryMethodUnique;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,13 +239,6 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
*/
|
||||
RootBeanDefinition(BeanDefinition original) {
|
||||
super(original);
|
||||
if (original instanceof RootBeanDefinition) {
|
||||
RootBeanDefinition originalRbd = (RootBeanDefinition) original;
|
||||
this.decoratedDefinition = originalRbd.decoratedDefinition;
|
||||
this.allowCaching = originalRbd.allowCaching;
|
||||
this.targetType = originalRbd.targetType;
|
||||
this.isFactoryMethodUnique = originalRbd.isFactoryMethodUnique;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+5
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -78,9 +78,12 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ResourceEditorRegistrar for the given ResourceLoader
|
||||
* Create a new ResourceEditorRegistrar for the given {@link ResourceLoader}
|
||||
* and {@link PropertyResolver}.
|
||||
* @param resourceLoader the ResourceLoader (or ResourcePatternResolver)
|
||||
* to create editors for (usually an ApplicationContext)
|
||||
* @param propertyResolver the PropertyResolver (usually an Environment)
|
||||
* @see org.springframework.core.env.Environment
|
||||
* @see org.springframework.core.io.support.ResourcePatternResolver
|
||||
* @see org.springframework.context.ApplicationContext
|
||||
*/
|
||||
|
||||
+14
@@ -712,6 +712,20 @@ public class DefaultListableBeanFactoryTests {
|
||||
factory.getMergedBeanDefinition("child"), factory.getMergedBeanDefinition("child"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTypeWorksAfterParentChildMerging() {
|
||||
RootBeanDefinition parentDefinition = new RootBeanDefinition(TestBean.class);
|
||||
ChildBeanDefinition childDefinition = new ChildBeanDefinition("parent", DerivedTestBean.class, null, null);
|
||||
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
factory.registerBeanDefinition("parent", parentDefinition);
|
||||
factory.registerBeanDefinition("child", childDefinition);
|
||||
factory.freezeConfiguration();
|
||||
|
||||
assertEquals(TestBean.class, factory.getType("parent"));
|
||||
assertEquals(DerivedTestBean.class, factory.getType("child"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameAlreadyBound() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="abstractFactoryBean" class="org.springframework.beans.factory.FactoryBeanTests$AbstractFactoryBean" abstract="true"/>
|
||||
|
||||
</beans>
|
||||
@@ -26,6 +26,7 @@ import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -38,6 +39,7 @@ public final class FactoryBeanTests {
|
||||
private static final Class<?> CLASS = FactoryBeanTests.class;
|
||||
private static final Resource RETURNS_NULL_CONTEXT = qualifiedResource(CLASS, "returnsNull.xml");
|
||||
private static final Resource WITH_AUTOWIRING_CONTEXT = qualifiedResource(CLASS, "withAutowiring.xml");
|
||||
private static final Resource ABSTRACT_CONTEXT = qualifiedResource(CLASS, "abstract.xml");
|
||||
|
||||
@Test
|
||||
public void testFactoryBeanReturnsNull() throws Exception {
|
||||
@@ -80,6 +82,20 @@ public final class FactoryBeanTests {
|
||||
assertSame(gamma, beta.getGamma());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbstractFactoryBeanViaAnnotation() throws Exception {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(ABSTRACT_CONTEXT);
|
||||
factory.getBeansWithAnnotation(Component.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbstractFactoryBeanViaType() throws Exception {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(ABSTRACT_CONTEXT);
|
||||
factory.getBeansOfType(AbstractFactoryBean.class);
|
||||
}
|
||||
|
||||
|
||||
public static class NullReturningFactoryBean implements FactoryBean<Object> {
|
||||
|
||||
@@ -152,6 +168,7 @@ public final class FactoryBeanTests {
|
||||
}
|
||||
|
||||
|
||||
@Component
|
||||
public static class BetaFactoryBean implements FactoryBean<Object> {
|
||||
|
||||
private Beta beta;
|
||||
@@ -176,4 +193,7 @@ public final class FactoryBeanTests {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class AbstractFactoryBean implements FactoryBean<Object> {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+37
-25
@@ -16,59 +16,59 @@
|
||||
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Unit tests for SPR-8954, in which a custom {@link InstantiationAwareBeanPostProcessor}
|
||||
* forces the predicted type of a FactoryBean, effectively preventing retrieval of the
|
||||
* bean from calls to #getBeansOfType(FactoryBean.class). The implementation of
|
||||
* {@link AbstractBeanFactory#isFactoryBean(String, RootBeanDefinition)} now ensures
|
||||
* that not only the predicted bean type is considered, but also the original bean
|
||||
* definition's beanClass.
|
||||
* {@link AbstractBeanFactory#isFactoryBean(String, RootBeanDefinition)} now ensures that
|
||||
* not only the predicted bean type is considered, but also the original bean definition's
|
||||
* beanClass.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class Spr8954Tests {
|
||||
|
||||
@Test
|
||||
public void repro() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
private DefaultListableBeanFactory bf;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("foo", new RootBeanDefinition(FooFactoryBean.class));
|
||||
bf.addBeanPostProcessor(new PredictingBPP());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void repro() {
|
||||
assertThat(bf.getBean("foo"), instanceOf(Foo.class));
|
||||
assertThat(bf.getBean("&foo"), instanceOf(FooFactoryBean.class));
|
||||
|
||||
assertThat(bf.isTypeMatch("&foo", FactoryBean.class), is(true));
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map<String, FactoryBean> fbBeans = bf.getBeansOfType(FactoryBean.class);
|
||||
assertThat(1, equalTo(fbBeans.size()));
|
||||
assertThat("&foo", equalTo(fbBeans.keySet().iterator().next()));
|
||||
assertThat(fbBeans.size(), is(1));
|
||||
assertThat(fbBeans.keySet(), hasItem("&foo"));
|
||||
|
||||
Map<String, AnInterface> aiBeans = bf.getBeansOfType(AnInterface.class);
|
||||
assertThat(1, equalTo(aiBeans.size()));
|
||||
assertThat("&foo", equalTo(aiBeans.keySet().iterator().next()));
|
||||
assertThat(aiBeans.size(), is(1));
|
||||
assertThat(aiBeans.keySet(), hasItem("&foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsBeansByTypeIfNotInstantiated() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("foo", new RootBeanDefinition(FooFactoryBean.class));
|
||||
bf.addBeanPostProcessor(new PredictingBPP());
|
||||
|
||||
assertThat(bf.isTypeMatch("&foo", FactoryBean.class), is(true));
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@@ -77,8 +77,21 @@ public class Spr8954Tests {
|
||||
assertThat("&foo", equalTo(fbBeans.keySet().iterator().next()));
|
||||
|
||||
Map<String, AnInterface> aiBeans = bf.getBeansOfType(AnInterface.class);
|
||||
assertThat(1, equalTo(aiBeans.size()));
|
||||
assertThat("&foo", equalTo(aiBeans.keySet().iterator().next()));
|
||||
assertThat(aiBeans.size(), is(1));
|
||||
assertThat(aiBeans.keySet(), hasItem("&foo"));
|
||||
}
|
||||
|
||||
/**
|
||||
* SPR-10517
|
||||
*/
|
||||
@Test
|
||||
public void findsFactoryBeanNameByTypeWithoutInstantiation() {
|
||||
String[] names = bf.getBeanNamesForType(AnInterface.class, false, false);
|
||||
assertThat(Arrays.asList(names), hasItem("&foo"));
|
||||
|
||||
Map<String, AnInterface> beans = bf.getBeansOfType(AnInterface.class, false, false);
|
||||
assertThat(beans.size(), is(1));
|
||||
assertThat(beans.keySet(), hasItem("&foo"));
|
||||
}
|
||||
|
||||
|
||||
@@ -116,8 +129,7 @@ public class Spr8954Tests {
|
||||
|
||||
@Override
|
||||
public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
|
||||
return FactoryBean.class.isAssignableFrom(beanClass) ?
|
||||
PredictedType.class : null;
|
||||
return FactoryBean.class.isAssignableFrom(beanClass) ? PredictedType.class : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-15
@@ -29,7 +29,7 @@ import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* @author Rick Evans
|
||||
@@ -38,13 +38,13 @@ import org.springframework.tests.sample.beans.TestBean;
|
||||
public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
|
||||
public void testSetParserClassSunnyDay() {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
new XmlBeanDefinitionReader(registry).setDocumentReaderClass(DefaultBeanDefinitionDocumentReader.class);
|
||||
}
|
||||
|
||||
public void testSetParserClassToNull() {
|
||||
try {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
new XmlBeanDefinitionReader(registry).setDocumentReaderClass(null);
|
||||
fail("Should have thrown IllegalArgumentException (null parserClass)");
|
||||
}
|
||||
@@ -54,7 +54,7 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
|
||||
public void testSetParserClassToUnsupportedParserType() throws Exception {
|
||||
try {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
new XmlBeanDefinitionReader(registry).setDocumentReaderClass(String.class);
|
||||
fail("Should have thrown IllegalArgumentException (unsupported parserClass)");
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
|
||||
public void testWithOpenInputStream() {
|
||||
try {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
Resource resource = new InputStreamResource(getClass().getResourceAsStream("test.xml"));
|
||||
new XmlBeanDefinitionReader(registry).loadBeanDefinitions(resource);
|
||||
fail("Should have thrown BeanDefinitionStoreException (can't determine validation mode)");
|
||||
@@ -74,7 +74,7 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testWithOpenInputStreamAndExplicitValidationMode() {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
Resource resource = new InputStreamResource(getClass().getResourceAsStream("test.xml"));
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
|
||||
reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_DTD);
|
||||
@@ -83,14 +83,14 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testWithImport() {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
Resource resource = new ClassPathResource("import.xml", getClass());
|
||||
new XmlBeanDefinitionReader(registry).loadBeanDefinitions(resource);
|
||||
testBeanDefinitions(registry);
|
||||
}
|
||||
|
||||
public void testWithWildcardImport() {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
Resource resource = new ClassPathResource("importPattern.xml", getClass());
|
||||
new XmlBeanDefinitionReader(registry).loadBeanDefinitions(resource);
|
||||
testBeanDefinitions(registry);
|
||||
@@ -98,7 +98,7 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
|
||||
public void testWithInputSource() {
|
||||
try {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
InputSource resource = new InputSource(getClass().getResourceAsStream("test.xml"));
|
||||
new XmlBeanDefinitionReader(registry).loadBeanDefinitions(resource);
|
||||
fail("Should have thrown BeanDefinitionStoreException (can't determine validation mode)");
|
||||
@@ -108,7 +108,7 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testWithInputSourceAndExplicitValidationMode() {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
InputSource resource = new InputSource(getClass().getResourceAsStream("test.xml"));
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
|
||||
reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_DTD);
|
||||
@@ -117,7 +117,7 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testWithFreshInputStream() {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
Resource resource = new ClassPathResource("test.xml", getClass());
|
||||
new XmlBeanDefinitionReader(registry).loadBeanDefinitions(resource);
|
||||
testBeanDefinitions(registry);
|
||||
@@ -133,9 +133,10 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
assertEquals(TestBean.class.getName(), registry.getBeanDefinition("rod").getBeanClassName());
|
||||
assertEquals(TestBean.class.getName(), registry.getBeanDefinition("aliased").getBeanClassName());
|
||||
assertTrue(registry.isAlias("youralias"));
|
||||
assertEquals(2, registry.getAliases("aliased").length);
|
||||
assertEquals("myalias", registry.getAliases("aliased")[0]);
|
||||
assertEquals("youralias", registry.getAliases("aliased")[1]);
|
||||
String[] aliases = registry.getAliases("aliased");
|
||||
assertEquals(2, aliases.length);
|
||||
assertTrue(ObjectUtils.containsElement(aliases, "myalias"));
|
||||
assertTrue(ObjectUtils.containsElement(aliases, "youralias"));
|
||||
}
|
||||
|
||||
public void testDtdValidationAutodetect() throws Exception {
|
||||
@@ -147,7 +148,7 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
}
|
||||
|
||||
private void doTestValidation(String resourceName) throws Exception {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();;
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
Resource resource = new ClassPathResource(resourceName, getClass());
|
||||
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(resource);
|
||||
TestBean bean = (TestBean) factory.getBean("testBean");
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2013 the original author 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,7 +30,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* JobFactory implementation that supports {@link java.lang.Runnable}
|
||||
* objects as well as standard Quartz {@link org.quartz.Job} instances.
|
||||
*
|
||||
* <p>Compatible with Quartz 1.5+ as well as Quartz 2.0/2.1, as of Spring 3.1.
|
||||
* <p>Compatible with Quartz 1.5+ as well as Quartz 2.0-2.2, as of Spring 3.2.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author 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,7 +47,7 @@ import org.springframework.util.Assert;
|
||||
* Use Quartz 2.0's native {@code JobDetailImpl} class or the new Quartz 2.0
|
||||
* builder API instead. Alternatively, switch to Spring's {@link CronTriggerFactoryBean}
|
||||
* which largely is a drop-in replacement for this class and its properties and
|
||||
* consistently works against Quartz 1.x as well as Quartz 2.0/2.1.
|
||||
* consistently works against Quartz 1.x as well as Quartz 2.x.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 18.02.2004
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -49,7 +49,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* to automatically register a trigger for the corresponding JobDetail,
|
||||
* instead of registering the JobDetail separately.
|
||||
*
|
||||
* <p><b>NOTE:</b> This FactoryBean works against both Quartz 1.x and Quartz 2.0/2.1,
|
||||
* <p><b>NOTE:</b> This FactoryBean works against both Quartz 1.x and Quartz 2.x,
|
||||
* in contrast to the older {@link CronTriggerBean} class.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author 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.context.ApplicationContextAware;
|
||||
* Use Quartz 2.0's native {@code JobDetailImpl} class or the new Quartz 2.0
|
||||
* builder API instead. Alternatively, switch to Spring's {@link JobDetailFactoryBean}
|
||||
* which largely is a drop-in replacement for this class and its properties and
|
||||
* consistently works against Quartz 1.x as well as Quartz 2.0/2.1.
|
||||
* consistently works against Quartz 1.x as well as Quartz 2.x.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 18.02.2004
|
||||
|
||||
+13
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author 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.context.ApplicationContextAware;
|
||||
* sensible defaults. This class uses the Spring bean name as job name,
|
||||
* and the Quartz default group ("DEFAULT") as job group if not specified.
|
||||
*
|
||||
* <p><b>NOTE:</b> This FactoryBean works against both Quartz 1.x and Quartz 2.0/2.1,
|
||||
* <p><b>NOTE:</b> This FactoryBean works against both Quartz 1.x and Quartz 2.x,
|
||||
* in contrast to the older {@link JobDetailBean} class.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
@@ -62,6 +62,8 @@ public class JobDetailFactoryBean
|
||||
|
||||
private boolean durability = false;
|
||||
|
||||
private boolean requestsRecovery = false;
|
||||
|
||||
private String description;
|
||||
|
||||
private String beanName;
|
||||
@@ -132,6 +134,14 @@ public class JobDetailFactoryBean
|
||||
this.durability = durability;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the recovery flag for this job, i.e. whether or not the job should
|
||||
* get re-executed if a 'recovery' or 'fail-over' situation is encountered.
|
||||
*/
|
||||
public void setRequestsRecovery(boolean requestsRecovery) {
|
||||
this.requestsRecovery = requestsRecovery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a textual description for this job.
|
||||
*/
|
||||
@@ -209,6 +219,7 @@ public class JobDetailFactoryBean
|
||||
pvs.add("jobClass", this.jobClass);
|
||||
pvs.add("jobDataMap", this.jobDataMap);
|
||||
pvs.add("durability", this.durability);
|
||||
pvs.add("requestsRecovery", this.requestsRecovery);
|
||||
pvs.add("description", this.description);
|
||||
bw.setPropertyValues(pvs);
|
||||
this.jobDetail = (JobDetail) bw.getWrappedInstance();
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -67,7 +67,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* You need to implement your own Quartz Job as a thin wrapper for each case
|
||||
* where you want a persistent job to delegate to a specific service method.
|
||||
*
|
||||
* <p>Compatible with Quartz 1.5+ as well as Quartz 2.0/2.1, as of Spring 3.1.
|
||||
* <p>Compatible with Quartz 1.5+ as well as Quartz 2.0-2.2, as of Spring 3.2.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Alef Arendsen
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -51,7 +51,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* <p>For concrete usage, check out the {@link SchedulerFactoryBean} and
|
||||
* {@link SchedulerAccessorBean} classes.
|
||||
*
|
||||
* <p>Compatible with Quartz 1.5+ as well as Quartz 2.0/2.1, as of Spring 3.1.
|
||||
* <p>Compatible with Quartz 1.5+ as well as Quartz 2.0-2.2, as of Spring 3.2.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5.6
|
||||
@@ -397,7 +397,7 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
|
||||
else {
|
||||
try {
|
||||
Map jobDataMap = (Map) ReflectionUtils.invokeMethod(Trigger.class.getMethod("getJobDataMap"), trigger);
|
||||
return (JobDetail) jobDataMap.get(JobDetailAwareTrigger.JOB_DETAIL_KEY);
|
||||
return (JobDetail) jobDataMap.remove(JobDetailAwareTrigger.JOB_DETAIL_KEY);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new IllegalStateException("Inconsistent Quartz API: " + ex);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author 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,7 @@ import org.springframework.beans.factory.ListableBeanFactory;
|
||||
* Spring bean-style class for accessing a Quartz Scheduler, i.e. for registering jobs,
|
||||
* triggers and listeners on a given {@link org.quartz.Scheduler} instance.
|
||||
*
|
||||
* <p>Compatible with Quartz 1.5+ as well as Quartz 2.0/2.1, as of Spring 3.1.
|
||||
* <p>Compatible with Quartz 1.5+ as well as Quartz 2.0-2.2, as of Spring 3.2.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5.6
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -74,7 +74,7 @@ import org.springframework.util.CollectionUtils;
|
||||
* automatically apply to Scheduler operations performed within those scopes.
|
||||
* Alternatively, you may add transactional advice for the Scheduler itself.
|
||||
*
|
||||
* <p>Compatible with Quartz 1.5+ as well as Quartz 2.0/2.1, as of Spring 3.1.
|
||||
* <p>Compatible with Quartz 1.5+ as well as Quartz 2.0-2.2, as of Spring 3.2.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 18.02.2004
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,7 +46,7 @@ import org.springframework.core.Constants;
|
||||
* Use Quartz 2.0's native {@code JobDetailImpl} class or the new Quartz 2.0
|
||||
* builder API instead. Alternatively, switch to Spring's {@link SimpleTriggerFactoryBean}
|
||||
* which largely is a drop-in replacement for this class and its properties and
|
||||
* consistently works against Quartz 1.x as well as Quartz 2.0/2.1.
|
||||
* consistently works against Quartz 1.x as well as Quartz 2.x.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 18.02.2004
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -49,7 +49,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* to automatically register a trigger for the corresponding JobDetail,
|
||||
* instead of registering the JobDetail separately.
|
||||
*
|
||||
* <p><b>NOTE:</b> This FactoryBean works against both Quartz 1.x and Quartz 2.0/2.1,
|
||||
* <p><b>NOTE:</b> This FactoryBean works against both Quartz 1.x and Quartz 2.x,
|
||||
* in contrast to the older {@link SimpleTriggerBean} class.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,7 +37,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* as bean property values. If no matching bean property is found, the entry
|
||||
* is by default simply ignored. This is analogous to QuartzJobBean's behavior.
|
||||
*
|
||||
* <p>Compatible with Quartz 1.5+ as well as Quartz 2.0/2.1, as of Spring 3.1.
|
||||
* <p>Compatible with Quartz 1.5+ as well as Quartz 2.0-2.2, as of Spring 3.2.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
|
||||
+72
-93
@@ -25,6 +25,7 @@ import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aop.framework.AopProxyUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.cache.Cache;
|
||||
@@ -61,23 +62,25 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public abstract class CacheAspectSupport implements InitializingBean {
|
||||
|
||||
public interface Invoker {
|
||||
Object invoke();
|
||||
}
|
||||
private static final String CACHEABLE = "cacheable";
|
||||
|
||||
private static final String UPDATE = "cacheupdate";
|
||||
|
||||
private static final String EVICT = "cacheevict";
|
||||
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final ExpressionEvaluator evaluator = new ExpressionEvaluator();
|
||||
|
||||
private CacheManager cacheManager;
|
||||
|
||||
private CacheOperationSource cacheOperationSource;
|
||||
|
||||
private final ExpressionEvaluator evaluator = new ExpressionEvaluator();
|
||||
|
||||
private KeyGenerator keyGenerator = new DefaultKeyGenerator();
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
private static final String CACHEABLE = "cacheable", UPDATE = "cacheupdate", EVICT = "cacheevict";
|
||||
|
||||
/**
|
||||
* Set the CacheManager that this cache aspect should delegate to.
|
||||
@@ -101,10 +104,8 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
*/
|
||||
public void setCacheOperationSources(CacheOperationSource... cacheOperationSources) {
|
||||
Assert.notEmpty(cacheOperationSources);
|
||||
this.cacheOperationSource =
|
||||
(cacheOperationSources.length > 1 ?
|
||||
new CompositeCacheOperationSource(cacheOperationSources) :
|
||||
cacheOperationSources[0]);
|
||||
this.cacheOperationSource = (cacheOperationSources.length > 1 ?
|
||||
new CompositeCacheOperationSource(cacheOperationSources) : cacheOperationSources[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,13 +135,14 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
throw new IllegalStateException("'cacheManager' is required");
|
||||
}
|
||||
if (this.cacheOperationSource == null) {
|
||||
throw new IllegalStateException("The 'cacheOperationSources' property is required: "
|
||||
+ "If there are no cacheable methods, then don't use a cache aspect.");
|
||||
throw new IllegalStateException("The 'cacheOperationSources' property is required: " +
|
||||
"If there are no cacheable methods, then don't use a cache aspect.");
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to return a String representation of this Method
|
||||
* for use in logging. Can be overridden in subclasses to provide a
|
||||
@@ -161,7 +163,7 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
for (String cacheName : cacheNames) {
|
||||
Cache cache = this.cacheManager.getCache(cacheName);
|
||||
if (cache == null) {
|
||||
throw new IllegalArgumentException("Cannot find cache named [" + cacheName + "] for " + operation);
|
||||
throw new IllegalArgumentException("Cannot find cache named '" + cacheName + "' for " + operation);
|
||||
}
|
||||
caches.add(cache);
|
||||
}
|
||||
@@ -186,39 +188,31 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
if (targetClass == null && target != null) {
|
||||
targetClass = target.getClass();
|
||||
}
|
||||
final Collection<CacheOperation> cacheOp = getCacheOperationSource().getCacheOperations(method, targetClass);
|
||||
Collection<CacheOperation> cacheOp = getCacheOperationSource().getCacheOperations(method, targetClass);
|
||||
|
||||
// analyze caching information
|
||||
if (!CollectionUtils.isEmpty(cacheOp)) {
|
||||
Map<String, Collection<CacheOperationContext>> ops = createOperationContext(cacheOp, method, args, target, targetClass);
|
||||
|
||||
// start with evictions
|
||||
inspectBeforeCacheEvicts(ops.get(EVICT));
|
||||
|
||||
// follow up with cacheable
|
||||
CacheStatus status = inspectCacheables(ops.get(CACHEABLE));
|
||||
|
||||
Object retVal = null;
|
||||
Object retVal;
|
||||
Map<CacheOperationContext, Object> updates = inspectCacheUpdates(ops.get(UPDATE));
|
||||
|
||||
if (status != null) {
|
||||
if (status.updateRequired) {
|
||||
updates.putAll(status.cUpdates);
|
||||
updates.putAll(status.cacheUpdates);
|
||||
}
|
||||
// return cached object
|
||||
else {
|
||||
return status.retVal;
|
||||
}
|
||||
}
|
||||
|
||||
retVal = invoker.invoke();
|
||||
|
||||
inspectAfterCacheEvicts(ops.get(EVICT), retVal);
|
||||
|
||||
if (!updates.isEmpty()) {
|
||||
update(updates, retVal);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@@ -229,27 +223,20 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
inspectCacheEvicts(evictions, true, ExpressionEvaluator.NO_RESULT);
|
||||
}
|
||||
|
||||
private void inspectAfterCacheEvicts(Collection<CacheOperationContext> evictions,
|
||||
Object result) {
|
||||
private void inspectAfterCacheEvicts(Collection<CacheOperationContext> evictions, Object result) {
|
||||
inspectCacheEvicts(evictions, false, result);
|
||||
}
|
||||
|
||||
private void inspectCacheEvicts(Collection<CacheOperationContext> evictions,
|
||||
boolean beforeInvocation, Object result) {
|
||||
|
||||
private void inspectCacheEvicts(Collection<CacheOperationContext> evictions, boolean beforeInvocation, Object result) {
|
||||
if (!evictions.isEmpty()) {
|
||||
|
||||
boolean log = logger.isTraceEnabled();
|
||||
|
||||
for (CacheOperationContext context : evictions) {
|
||||
CacheEvictOperation evictOp = (CacheEvictOperation) context.operation;
|
||||
|
||||
if (beforeInvocation == evictOp.isBeforeInvocation()) {
|
||||
if (context.isConditionPassing(result)) {
|
||||
// for each cache
|
||||
// lazy key initialization
|
||||
Object key = null;
|
||||
|
||||
for (Cache cache : context.getCaches()) {
|
||||
// cache-wide flush
|
||||
if (evictOp.isCacheWide()) {
|
||||
@@ -257,7 +244,8 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
if (log) {
|
||||
logger.trace("Invalidating entire cache for operation " + evictOp + " on method " + context.method);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// check key
|
||||
if (key == null) {
|
||||
key = context.generateKey();
|
||||
@@ -268,7 +256,8 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
cache.evict(key);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (log) {
|
||||
logger.trace("Cache condition failed on method " + context.method + " for operation " + context.operation);
|
||||
}
|
||||
@@ -279,34 +268,27 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
}
|
||||
|
||||
private CacheStatus inspectCacheables(Collection<CacheOperationContext> cacheables) {
|
||||
Map<CacheOperationContext, Object> cUpdates = new LinkedHashMap<CacheOperationContext, Object>(cacheables.size());
|
||||
|
||||
Map<CacheOperationContext, Object> cacheUpdates = new LinkedHashMap<CacheOperationContext, Object>(cacheables.size());
|
||||
boolean updateRequired = false;
|
||||
Object retVal = null;
|
||||
|
||||
if (!cacheables.isEmpty()) {
|
||||
boolean log = logger.isTraceEnabled();
|
||||
boolean atLeastOnePassed = false;
|
||||
|
||||
for (CacheOperationContext context : cacheables) {
|
||||
if (context.isConditionPassing()) {
|
||||
atLeastOnePassed = true;
|
||||
Object key = context.generateKey();
|
||||
|
||||
if (log) {
|
||||
logger.trace("Computed cache key " + key + " for operation " + context.operation);
|
||||
}
|
||||
if (key == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Null key returned for cache operation (maybe you are using named params on classes without debug info?) "
|
||||
+ context.operation);
|
||||
throw new IllegalArgumentException("Null key returned for cache operation (maybe you " +
|
||||
"are using named params on classes without debug info?) " + context.operation);
|
||||
}
|
||||
|
||||
// add op/key (in case an update is discovered later on)
|
||||
cUpdates.put(context, key);
|
||||
|
||||
cacheUpdates.put(context, key);
|
||||
boolean localCacheHit = false;
|
||||
|
||||
// check whether the cache needs to be inspected or not (the method will be invoked anyway)
|
||||
if (!updateRequired) {
|
||||
for (Cache cache : context.getCaches()) {
|
||||
@@ -318,7 +300,6 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!localCacheHit) {
|
||||
updateRequired = true;
|
||||
}
|
||||
@@ -330,51 +311,31 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
}
|
||||
}
|
||||
|
||||
// return a status only if at least on cacheable matched
|
||||
// return a status only if at least one cacheable matched
|
||||
if (atLeastOnePassed) {
|
||||
return new CacheStatus(cUpdates, updateRequired, retVal);
|
||||
return new CacheStatus(cacheUpdates, updateRequired, retVal);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class CacheStatus {
|
||||
// caches/key
|
||||
final Map<CacheOperationContext, Object> cUpdates;
|
||||
final boolean updateRequired;
|
||||
final Object retVal;
|
||||
|
||||
CacheStatus(Map<CacheOperationContext, Object> cUpdates, boolean updateRequired, Object retVal) {
|
||||
this.cUpdates = cUpdates;
|
||||
this.updateRequired = updateRequired;
|
||||
this.retVal = retVal;
|
||||
}
|
||||
}
|
||||
|
||||
private Map<CacheOperationContext, Object> inspectCacheUpdates(Collection<CacheOperationContext> updates) {
|
||||
|
||||
Map<CacheOperationContext, Object> cUpdates = new LinkedHashMap<CacheOperationContext, Object>(updates.size());
|
||||
|
||||
Map<CacheOperationContext, Object> cacheUpdates = new LinkedHashMap<CacheOperationContext, Object>(updates.size());
|
||||
if (!updates.isEmpty()) {
|
||||
boolean log = logger.isTraceEnabled();
|
||||
|
||||
for (CacheOperationContext context : updates) {
|
||||
if (context.isConditionPassing()) {
|
||||
|
||||
Object key = context.generateKey();
|
||||
|
||||
if (log) {
|
||||
logger.trace("Computed cache key " + key + " for operation " + context.operation);
|
||||
}
|
||||
if (key == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Null key returned for cache operation (maybe you are using named params on classes without debug info?) "
|
||||
+ context.operation);
|
||||
throw new IllegalArgumentException("Null key returned for cache operation (maybe you " +
|
||||
"are using named params on classes without debug info?) " + context.operation);
|
||||
}
|
||||
|
||||
// add op/key (in case an update is discovered later on)
|
||||
cUpdates.put(context, key);
|
||||
cacheUpdates.put(context, key);
|
||||
}
|
||||
else {
|
||||
if (log) {
|
||||
@@ -383,14 +344,13 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cUpdates;
|
||||
return cacheUpdates;
|
||||
}
|
||||
|
||||
private void update(Map<CacheOperationContext, Object> updates, Object retVal) {
|
||||
for (Map.Entry<CacheOperationContext, Object> entry : updates.entrySet()) {
|
||||
CacheOperationContext operationContext = entry.getKey();
|
||||
if(operationContext.canPutToCache(retVal)) {
|
||||
if (operationContext.canPutToCache(retVal)) {
|
||||
for (Cache cache : operationContext.getCaches()) {
|
||||
cache.put(entry.getValue(), retVal);
|
||||
}
|
||||
@@ -398,37 +358,40 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Collection<CacheOperationContext>> createOperationContext(Collection<CacheOperation> cacheOp,
|
||||
Method method, Object[] args, Object target, Class<?> targetClass) {
|
||||
Map<String, Collection<CacheOperationContext>> map = new LinkedHashMap<String, Collection<CacheOperationContext>>(3);
|
||||
private Map<String, Collection<CacheOperationContext>> createOperationContext(
|
||||
Collection<CacheOperation> cacheOperations, Method method, Object[] args, Object target, Class<?> targetClass) {
|
||||
|
||||
Map<String, Collection<CacheOperationContext>> result = new LinkedHashMap<String, Collection<CacheOperationContext>>(3);
|
||||
Collection<CacheOperationContext> cacheables = new ArrayList<CacheOperationContext>();
|
||||
Collection<CacheOperationContext> evicts = new ArrayList<CacheOperationContext>();
|
||||
Collection<CacheOperationContext> updates = new ArrayList<CacheOperationContext>();
|
||||
|
||||
for (CacheOperation cacheOperation : cacheOp) {
|
||||
for (CacheOperation cacheOperation : cacheOperations) {
|
||||
CacheOperationContext opContext = getOperationContext(cacheOperation, method, args, target, targetClass);
|
||||
|
||||
if (cacheOperation instanceof CacheableOperation) {
|
||||
cacheables.add(opContext);
|
||||
}
|
||||
|
||||
if (cacheOperation instanceof CacheEvictOperation) {
|
||||
evicts.add(opContext);
|
||||
}
|
||||
|
||||
if (cacheOperation instanceof CachePutOperation) {
|
||||
updates.add(opContext);
|
||||
}
|
||||
}
|
||||
|
||||
map.put(CACHEABLE, cacheables);
|
||||
map.put(EVICT, evicts);
|
||||
map.put(UPDATE, updates);
|
||||
|
||||
return map;
|
||||
result.put(CACHEABLE, cacheables);
|
||||
result.put(EVICT, evicts);
|
||||
result.put(UPDATE, updates);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public interface Invoker {
|
||||
|
||||
Object invoke();
|
||||
}
|
||||
|
||||
|
||||
protected class CacheOperationContext {
|
||||
|
||||
private final CacheOperation operation;
|
||||
@@ -459,8 +422,7 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
protected boolean isConditionPassing(Object result) {
|
||||
if (StringUtils.hasText(this.operation.getCondition())) {
|
||||
EvaluationContext evaluationContext = createEvaluationContext(result);
|
||||
return evaluator.condition(this.operation.getCondition(), this.method,
|
||||
evaluationContext);
|
||||
return evaluator.condition(this.operation.getCondition(), this.method, evaluationContext);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -473,7 +435,7 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
else if (this.operation instanceof CachePutOperation) {
|
||||
unless = ((CachePutOperation) this.operation).getUnless();
|
||||
}
|
||||
if(StringUtils.hasText(unless)) {
|
||||
if (StringUtils.hasText(unless)) {
|
||||
EvaluationContext evaluationContext = createEvaluationContext(value);
|
||||
return !evaluator.unless(unless, this.method, evaluationContext);
|
||||
}
|
||||
@@ -493,12 +455,29 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||
}
|
||||
|
||||
private EvaluationContext createEvaluationContext(Object result) {
|
||||
return evaluator.createEvaluationContext(this.caches, this.method, this.args,
|
||||
this.target, this.targetClass, result);
|
||||
return evaluator.createEvaluationContext(this.caches, this.method, this.args, this.target, this.targetClass, result);
|
||||
}
|
||||
|
||||
protected Collection<Cache> getCaches() {
|
||||
return this.caches;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class CacheStatus {
|
||||
|
||||
// caches/key
|
||||
final Map<CacheOperationContext, Object> cacheUpdates;
|
||||
|
||||
final boolean updateRequired;
|
||||
|
||||
final Object retVal;
|
||||
|
||||
CacheStatus(Map<CacheOperationContext, Object> cacheUpdates, boolean updateRequired, Object retVal) {
|
||||
this.cacheUpdates = cacheUpdates;
|
||||
this.updateRequired = updateRequired;
|
||||
this.retVal = retVal;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -116,7 +116,10 @@ public class AnnotationBeanNameGenerator implements BeanNameGenerator {
|
||||
(metaAnnotationTypes != null && metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME)) ||
|
||||
annotationType.equals("javax.annotation.ManagedBean") ||
|
||||
annotationType.equals("javax.inject.Named");
|
||||
return (isStereotype && attributes != null && attributes.containsKey("value"));
|
||||
|
||||
return (isStereotype && attributes != null &&
|
||||
attributes.containsKey("value") &&
|
||||
attributes.get("value") instanceof String);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+11
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -90,7 +90,7 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC
|
||||
|
||||
|
||||
/**
|
||||
* Create a ClassPathScanningCandidateComponentProvider.
|
||||
* Create a ClassPathScanningCandidateComponentProvider with a {@link StandardEnvironment}.
|
||||
* @param useDefaultFilters whether to register the default filters for the
|
||||
* {@link Component @Component}, {@link Repository @Repository},
|
||||
* {@link Service @Service}, and {@link Controller @Controller}
|
||||
@@ -101,6 +101,15 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC
|
||||
this(useDefaultFilters, new StandardEnvironment());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ClassPathScanningCandidateComponentProvider with the given {@link Environment}.
|
||||
* @param useDefaultFilters whether to register the default filters for the
|
||||
* {@link Component @Component}, {@link Repository @Repository},
|
||||
* {@link Service @Service}, and {@link Controller @Controller}
|
||||
* stereotype annotations
|
||||
* @param environment the Environment to use
|
||||
* @see #registerDefaultFilters()
|
||||
*/
|
||||
public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters, Environment environment) {
|
||||
if (useDefaultFilters) {
|
||||
registerDefaultFilters();
|
||||
|
||||
+39
-42
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,8 +36,8 @@ import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Represents a user-defined {@link Configuration @Configuration} class.
|
||||
* Includes a set of {@link Bean} methods, including all such methods defined in the
|
||||
* ancestry of the class, in a 'flattened-out' manner.
|
||||
* Includes a set of {@link Bean} methods, including all such methods
|
||||
* defined in the ancestry of the class, in a 'flattened-out' manner.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
@@ -51,15 +51,15 @@ final class ConfigurationClass {
|
||||
|
||||
private final Resource resource;
|
||||
|
||||
private final Map<String, Class<? extends BeanDefinitionReader>> importedResources =
|
||||
new LinkedHashMap<String, Class<? extends BeanDefinitionReader>>();
|
||||
|
||||
private final Set<BeanMethod> beanMethods = new LinkedHashSet<BeanMethod>();
|
||||
|
||||
private String beanName;
|
||||
|
||||
private final boolean imported;
|
||||
|
||||
private final Set<BeanMethod> beanMethods = new LinkedHashSet<BeanMethod>();
|
||||
|
||||
private final Map<String, Class<? extends BeanDefinitionReader>> importedResources =
|
||||
new LinkedHashMap<String, Class<? extends BeanDefinitionReader>>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigurationClass} with the given name.
|
||||
@@ -81,7 +81,7 @@ final class ConfigurationClass {
|
||||
* using the {@link Import} annotation or automatically processed as a nested
|
||||
* configuration class (if imported is {@code true}).
|
||||
* @param metadataReader reader used to parse the underlying {@link Class}
|
||||
* @param beanName name of the {@code @Configuration} class bean
|
||||
* @param imported whether the given configuration class is being imported
|
||||
* @since 3.1.1
|
||||
*/
|
||||
public ConfigurationClass(MetadataReader metadataReader, boolean imported) {
|
||||
@@ -98,7 +98,7 @@ final class ConfigurationClass {
|
||||
* @see ConfigurationClass#ConfigurationClass(Class, boolean)
|
||||
*/
|
||||
public ConfigurationClass(Class<?> clazz, String beanName) {
|
||||
Assert.hasText(beanName, "bean name must not be null");
|
||||
Assert.hasText(beanName, "Bean name must not be null");
|
||||
this.metadata = new StandardAnnotationMetadata(clazz, true);
|
||||
this.resource = new DescriptiveResource(clazz.toString());
|
||||
this.beanName = beanName;
|
||||
@@ -110,7 +110,7 @@ final class ConfigurationClass {
|
||||
* using the {@link Import} annotation or automatically processed as a nested
|
||||
* configuration class (if imported is {@code true}).
|
||||
* @param clazz the underlying {@link Class} to represent
|
||||
* @param beanName name of the {@code @Configuration} class bean
|
||||
* @param imported whether the given configuration class is being imported
|
||||
* @since 3.1.1
|
||||
*/
|
||||
public ConfigurationClass(Class<?> clazz, boolean imported) {
|
||||
@@ -119,6 +119,7 @@ final class ConfigurationClass {
|
||||
this.imported = imported;
|
||||
}
|
||||
|
||||
|
||||
public AnnotationMetadata getMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
@@ -131,6 +132,14 @@ final class ConfigurationClass {
|
||||
return ClassUtils.getShortName(getMetadata().getClassName());
|
||||
}
|
||||
|
||||
public void setBeanName(String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
public String getBeanName() {
|
||||
return this.beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this configuration class was registered via @{@link Import} or
|
||||
* automatically registered due to being nested within another configuration class.
|
||||
@@ -140,14 +149,6 @@ final class ConfigurationClass {
|
||||
return this.imported;
|
||||
}
|
||||
|
||||
public void setBeanName(String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
public String getBeanName() {
|
||||
return this.beanName;
|
||||
}
|
||||
|
||||
public void addBeanMethod(BeanMethod method) {
|
||||
this.beanMethods.add(method);
|
||||
}
|
||||
@@ -156,8 +157,7 @@ final class ConfigurationClass {
|
||||
return this.beanMethods;
|
||||
}
|
||||
|
||||
public void addImportedResource(
|
||||
String importedResource, Class<? extends BeanDefinitionReader> readerClass) {
|
||||
public void addImportedResource(String importedResource, Class<? extends BeanDefinitionReader> readerClass) {
|
||||
this.importedResources.put(importedResource, readerClass);
|
||||
}
|
||||
|
||||
@@ -165,28 +165,8 @@ final class ConfigurationClass {
|
||||
return this.importedResources;
|
||||
}
|
||||
|
||||
|
||||
public void validate(ProblemReporter problemReporter) {
|
||||
// An @Bean method may only be overloaded through inheritance. No single
|
||||
// @Configuration class may declare two @Bean methods with the same name.
|
||||
final char hashDelim = '#';
|
||||
Map<String, Integer> methodNameCounts = new HashMap<String, Integer>();
|
||||
for (BeanMethod beanMethod : beanMethods) {
|
||||
String dClassName = beanMethod.getMetadata().getDeclaringClassName();
|
||||
String methodName = beanMethod.getMetadata().getMethodName();
|
||||
String fqMethodName = dClassName + hashDelim + methodName;
|
||||
Integer currentCount = methodNameCounts.get(fqMethodName);
|
||||
int newCount = currentCount != null ? currentCount + 1 : 1;
|
||||
methodNameCounts.put(fqMethodName, newCount);
|
||||
}
|
||||
|
||||
for (String methodName : methodNameCounts.keySet()) {
|
||||
int count = methodNameCounts.get(methodName);
|
||||
if (count > 1) {
|
||||
String shortMethodName = methodName.substring(methodName.indexOf(hashDelim)+1);
|
||||
problemReporter.error(new BeanMethodOverloadingProblem(shortMethodName, count));
|
||||
}
|
||||
}
|
||||
|
||||
// A configuration class may not be final (CGLIB limitation)
|
||||
if (getMetadata().isAnnotated(Configuration.class.getName())) {
|
||||
if (getMetadata().isFinal()) {
|
||||
@@ -194,6 +174,23 @@ final class ConfigurationClass {
|
||||
}
|
||||
}
|
||||
|
||||
// An @Bean method may only be overloaded through inheritance. No single
|
||||
// @Configuration class may declare two @Bean methods with the same name.
|
||||
Map<String, Integer> methodNameCounts = new HashMap<String, Integer>();
|
||||
for (BeanMethod beanMethod : this.beanMethods) {
|
||||
String fqMethodName = beanMethod.getFullyQualifiedMethodName();
|
||||
Integer currentCount = methodNameCounts.get(fqMethodName);
|
||||
int newCount = currentCount != null ? currentCount + 1 : 1;
|
||||
methodNameCounts.put(fqMethodName, newCount);
|
||||
}
|
||||
for (String fqMethodName : methodNameCounts.keySet()) {
|
||||
int count = methodNameCounts.get(fqMethodName);
|
||||
if (count > 1) {
|
||||
String shortMethodName = ConfigurationMethod.getShortMethodName(fqMethodName);
|
||||
problemReporter.error(new BeanMethodOverloadingProblem(shortMethodName, count));
|
||||
}
|
||||
}
|
||||
|
||||
for (BeanMethod beanMethod : this.beanMethods) {
|
||||
beanMethod.validate(problemReporter);
|
||||
}
|
||||
|
||||
+1
-3
@@ -134,8 +134,6 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
|
||||
AnnotationMetadata metadata = configClass.getMetadata();
|
||||
BeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
|
||||
String className = metadata.getClassName();
|
||||
configBeanDef.setBeanClassName(className);
|
||||
if (ConfigurationClassUtils.checkConfigurationClassCandidate(configBeanDef, this.metadataReaderFactory)) {
|
||||
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
|
||||
this.registry.registerBeanDefinition(configBeanName, configBeanDef);
|
||||
@@ -146,7 +144,7 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
}
|
||||
else {
|
||||
this.problemReporter.error(
|
||||
new InvalidConfigurationImportProblem(className, configClass.getResource(), metadata));
|
||||
new InvalidConfigurationImportProblem(metadata.getClassName(), configClass.getResource(), metadata));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+175
-106
@@ -17,11 +17,12 @@
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
@@ -42,6 +43,7 @@ import org.springframework.beans.factory.support.BeanDefinitionReader;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.NestedIOException;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.env.CompositePropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
@@ -54,7 +56,7 @@ import org.springframework.core.type.StandardAnnotationMetadata;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.springframework.context.annotation.MetadataUtils.*;
|
||||
@@ -83,16 +85,6 @@ class ConfigurationClassParser {
|
||||
|
||||
private final ProblemReporter problemReporter;
|
||||
|
||||
private final ImportStack importStack = new ImportStack();
|
||||
|
||||
private final Set<String> knownSuperclasses = new LinkedHashSet<String>();
|
||||
|
||||
private final Set<ConfigurationClass> configurationClasses =
|
||||
new LinkedHashSet<ConfigurationClass>();
|
||||
|
||||
private final Stack<PropertySource<?>> propertySources =
|
||||
new Stack<PropertySource<?>>();
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
private final ResourceLoader resourceLoader;
|
||||
@@ -101,6 +93,14 @@ class ConfigurationClassParser {
|
||||
|
||||
private final ComponentScanAnnotationParser componentScanParser;
|
||||
|
||||
private final Set<ConfigurationClass> configurationClasses = new LinkedHashSet<ConfigurationClass>();
|
||||
|
||||
private final Map<String, ConfigurationClass> knownSuperclasses = new HashMap<String, ConfigurationClass>();
|
||||
|
||||
private final Stack<PropertySource<?>> propertySources = new Stack<PropertySource<?>>();
|
||||
|
||||
private final ImportStack importStack = new ImportStack();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigurationClassParser} instance that will be used
|
||||
@@ -149,70 +149,42 @@ class ConfigurationClassParser {
|
||||
}
|
||||
}
|
||||
|
||||
// recursively process the configuration class and its superclass hierarchy
|
||||
if (this.configurationClasses.contains(configClass) && configClass.getBeanName() != null) {
|
||||
// Explicit bean definition found, probably replacing an import.
|
||||
// Let's remove the old one and go with the new one.
|
||||
this.configurationClasses.remove(configClass);
|
||||
for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext();) {
|
||||
if (configClass.equals(it.next())) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively process the configuration class and its superclass hierarchy.
|
||||
do {
|
||||
metadata = doProcessConfigurationClass(configClass, metadata);
|
||||
}
|
||||
while (metadata != null);
|
||||
|
||||
if (this.configurationClasses.contains(configClass) && configClass.getBeanName() != null) {
|
||||
// Explicit bean definition found, probably replacing an import.
|
||||
// Let's remove the old one and go with the new one.
|
||||
this.configurationClasses.remove(configClass);
|
||||
}
|
||||
|
||||
this.configurationClasses.add(configClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return annotation metadata of superclass, null if none found or previously processed
|
||||
* @return annotation metadata of superclass, {@code null} if none found or previously processed
|
||||
*/
|
||||
protected AnnotationMetadata doProcessConfigurationClass(
|
||||
ConfigurationClass configClass, AnnotationMetadata metadata) throws IOException {
|
||||
|
||||
// recursively process any member (nested) classes first
|
||||
for (String memberClassName : metadata.getMemberClassNames()) {
|
||||
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(memberClassName);
|
||||
AnnotationMetadata memberClassMetadata = reader.getAnnotationMetadata();
|
||||
if (ConfigurationClassUtils.isConfigurationCandidate(memberClassMetadata)) {
|
||||
processConfigurationClass(new ConfigurationClass(reader, true));
|
||||
}
|
||||
}
|
||||
processMemberClasses(metadata);
|
||||
|
||||
// process any @PropertySource annotations
|
||||
AnnotationAttributes propertySource =
|
||||
attributesFor(metadata, org.springframework.context.annotation.PropertySource.class);
|
||||
AnnotationAttributes propertySource = attributesFor(metadata, org.springframework.context.annotation.PropertySource.class);
|
||||
if (propertySource != null) {
|
||||
String name = propertySource.getString("name");
|
||||
String[] locations = propertySource.getStringArray("value");
|
||||
int nLocations = locations.length;
|
||||
if (nLocations == 0) {
|
||||
throw new IllegalArgumentException("At least one @PropertySource(value) location is required");
|
||||
}
|
||||
for (int i = 0; i < nLocations; i++) {
|
||||
locations[i] = this.environment.resolveRequiredPlaceholders(locations[i]);
|
||||
}
|
||||
ClassLoader classLoader = this.resourceLoader.getClassLoader();
|
||||
if (!StringUtils.hasText(name)) {
|
||||
for (String location : locations) {
|
||||
this.propertySources.push(new ResourcePropertySource(location, classLoader));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (nLocations == 1) {
|
||||
this.propertySources.push(new ResourcePropertySource(name, locations[0], classLoader));
|
||||
}
|
||||
else {
|
||||
CompositePropertySource ps = new CompositePropertySource(name);
|
||||
for (String location : locations) {
|
||||
ps.addPropertySource(new ResourcePropertySource(location, classLoader));
|
||||
}
|
||||
this.propertySources.push(ps);
|
||||
}
|
||||
}
|
||||
processPropertySource(propertySource);
|
||||
}
|
||||
|
||||
// process any @ComponentScan annotions
|
||||
// process any @ComponentScan annotations
|
||||
AnnotationAttributes componentScan = attributesFor(metadata, ComponentScan.class);
|
||||
if (componentScan != null) {
|
||||
// the config class is annotated with @ComponentScan -> perform the scan immediately
|
||||
@@ -228,9 +200,11 @@ class ConfigurationClassParser {
|
||||
}
|
||||
|
||||
// process any @Import annotations
|
||||
Set<String> imports = getImports(metadata.getClassName(), null, new HashSet<String>());
|
||||
if (!CollectionUtils.isEmpty(imports)) {
|
||||
processImport(configClass, imports.toArray(new String[imports.size()]), true);
|
||||
Set<Object> imports = new LinkedHashSet<Object>();
|
||||
Set<Object> visited = new LinkedHashSet<Object>();
|
||||
collectImports(metadata, imports, visited);
|
||||
if (!imports.isEmpty()) {
|
||||
processImport(configClass, imports, true);
|
||||
}
|
||||
|
||||
// process any @ImportResource annotations
|
||||
@@ -239,7 +213,8 @@ class ConfigurationClassParser {
|
||||
String[] resources = importResource.getStringArray("value");
|
||||
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
|
||||
for (String resource : resources) {
|
||||
configClass.addImportedResource(resource, readerClass);
|
||||
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
|
||||
configClass.addImportedResource(resolvedResource, readerClass);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,7 +227,8 @@ class ConfigurationClassParser {
|
||||
// process superclass, if any
|
||||
if (metadata.hasSuperClass()) {
|
||||
String superclass = metadata.getSuperClassName();
|
||||
if (this.knownSuperclasses.add(superclass)) {
|
||||
if (!this.knownSuperclasses.containsKey(superclass)) {
|
||||
this.knownSuperclasses.put(superclass, configClass);
|
||||
// superclass found, return its annotation metadata and recurse
|
||||
if (metadata instanceof StandardAnnotationMetadata) {
|
||||
Class<?> clazz = ((StandardAnnotationMetadata) metadata).getIntrospectedClass();
|
||||
@@ -279,6 +255,65 @@ class ConfigurationClassParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register member (nested) classes that happen to be configuration classes themselves.
|
||||
* @param metadata the metadata representation of the containing class
|
||||
* @throws IOException if there is any problem reading metadata from a member class
|
||||
*/
|
||||
private void processMemberClasses(AnnotationMetadata metadata) throws IOException {
|
||||
if (metadata instanceof StandardAnnotationMetadata) {
|
||||
for (Class<?> memberClass : ((StandardAnnotationMetadata) metadata).getIntrospectedClass().getDeclaredClasses()) {
|
||||
if (ConfigurationClassUtils.isConfigurationCandidate(new StandardAnnotationMetadata(memberClass))) {
|
||||
processConfigurationClass(new ConfigurationClass(memberClass, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (String memberClassName : metadata.getMemberClassNames()) {
|
||||
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(memberClassName);
|
||||
AnnotationMetadata memberClassMetadata = reader.getAnnotationMetadata();
|
||||
if (ConfigurationClassUtils.isConfigurationCandidate(memberClassMetadata)) {
|
||||
processConfigurationClass(new ConfigurationClass(reader, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the given <code>@PropertySource</code> annotation metadata.
|
||||
* @param propertySource metadata for the <code>@PropertySource</code> annotation found
|
||||
* @throws IOException if loading a property source failed
|
||||
*/
|
||||
private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
|
||||
String name = propertySource.getString("name");
|
||||
String[] locations = propertySource.getStringArray("value");
|
||||
int nLocations = locations.length;
|
||||
if (nLocations == 0) {
|
||||
throw new IllegalArgumentException("At least one @PropertySource(value) location is required");
|
||||
}
|
||||
for (int i = 0; i < nLocations; i++) {
|
||||
locations[i] = this.environment.resolveRequiredPlaceholders(locations[i]);
|
||||
}
|
||||
ClassLoader classLoader = this.resourceLoader.getClassLoader();
|
||||
if (!StringUtils.hasText(name)) {
|
||||
for (String location : locations) {
|
||||
this.propertySources.push(new ResourcePropertySource(location, classLoader));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (nLocations == 1) {
|
||||
this.propertySources.push(new ResourcePropertySource(name, locations[0], classLoader));
|
||||
}
|
||||
else {
|
||||
CompositePropertySource ps = new CompositePropertySource(name);
|
||||
for (String location : locations) {
|
||||
ps.addPropertySource(new ResourcePropertySource(location, classLoader));
|
||||
}
|
||||
this.propertySources.push(ps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively collect all declared {@code @Import} values. Unlike most
|
||||
* meta-annotations it is valid to have several {@code @Import}s declared with
|
||||
@@ -287,69 +322,103 @@ class ConfigurationClassParser {
|
||||
* <p>For example, it is common for a {@code @Configuration} class to declare direct
|
||||
* {@code @Import}s in addition to meta-imports originating from an {@code @Enable}
|
||||
* annotation.
|
||||
* @param className the class name to search
|
||||
* @param imports the imports collected so far or {@code null}
|
||||
* @param visited used to track visited classes to prevent infinite recursion (must not be null)
|
||||
* @return a set of all {@link Import#value() import values} or {@code null}
|
||||
* @param metadata the metadata representation of the class to search
|
||||
* @param imports the imports collected so far
|
||||
* @param visited used to track visited classes to prevent infinite recursion
|
||||
* @throws IOException if there is any problem reading metadata from the named class
|
||||
*/
|
||||
private Set<String> getImports(String className, Set<String> imports, Set<String> visited) throws IOException {
|
||||
if (visited.add(className) && !className.startsWith("java")) {
|
||||
AnnotationMetadata metadata = metadataReaderFactory.getMetadataReader(className).getAnnotationMetadata();
|
||||
for (String annotationType : metadata.getAnnotationTypes()) {
|
||||
imports = getImports(annotationType, imports, visited);
|
||||
private void collectImports(AnnotationMetadata metadata, Set<Object> imports, Set<Object> visited) throws IOException {
|
||||
String className = metadata.getClassName();
|
||||
if (visited.add(className)) {
|
||||
if (metadata instanceof StandardAnnotationMetadata) {
|
||||
StandardAnnotationMetadata stdMetadata = (StandardAnnotationMetadata) metadata;
|
||||
for (Annotation ann : stdMetadata.getIntrospectedClass().getAnnotations()) {
|
||||
if (!ann.annotationType().getName().startsWith("java") && !(ann instanceof Import)) {
|
||||
collectImports(new StandardAnnotationMetadata(ann.annotationType()), imports, visited);
|
||||
}
|
||||
}
|
||||
Map<String, Object> attributes = stdMetadata.getAnnotationAttributes(Import.class.getName(), false);
|
||||
if (attributes != null) {
|
||||
Class[] value = (Class[]) attributes.get("value");
|
||||
if (!ObjectUtils.isEmpty(value)) {
|
||||
imports.addAll(Arrays.asList(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
Map<String, Object> attributes = metadata.getAnnotationAttributes(Import.class.getName(), true);
|
||||
if (attributes != null) {
|
||||
String[] value = (String[]) attributes.get("value");
|
||||
if (value != null && value.length > 0) {
|
||||
imports = (imports == null ? new LinkedHashSet<String>() : imports);
|
||||
imports.addAll(Arrays.asList(value));
|
||||
else {
|
||||
for (String annotationType : metadata.getAnnotationTypes()) {
|
||||
if (!className.startsWith("java") && !className.equals(Import.class.getName())) {
|
||||
try {
|
||||
collectImports(
|
||||
new StandardAnnotationMetadata(this.resourceLoader.getClassLoader().loadClass(annotationType)),
|
||||
imports, visited);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
Map<String, Object> attributes = metadata.getAnnotationAttributes(Import.class.getName(), true);
|
||||
if (attributes != null) {
|
||||
String[] value = (String[]) attributes.get("value");
|
||||
if (!ObjectUtils.isEmpty(value)) {
|
||||
imports.addAll(Arrays.asList(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return imports;
|
||||
}
|
||||
|
||||
private void processImport(ConfigurationClass configClass, String[] classesToImport, boolean checkForCircularImports) throws IOException {
|
||||
private void processImport(ConfigurationClass configClass, Collection<?> classesToImport, boolean checkForCircularImports) throws IOException {
|
||||
if (checkForCircularImports && this.importStack.contains(configClass)) {
|
||||
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack, configClass.getMetadata()));
|
||||
}
|
||||
else {
|
||||
this.importStack.push(configClass);
|
||||
AnnotationMetadata importingClassMetadata = configClass.getMetadata();
|
||||
for (String candidate : classesToImport) {
|
||||
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(candidate);
|
||||
if (new AssignableTypeFilter(ImportSelector.class).match(reader, this.metadataReaderFactory)) {
|
||||
// the candidate class is an ImportSelector -> delegate to it to determine imports
|
||||
try {
|
||||
ImportSelector selector = BeanUtils.instantiateClass(
|
||||
this.resourceLoader.getClassLoader().loadClass(candidate), ImportSelector.class);
|
||||
processImport(configClass, selector.selectImports(importingClassMetadata), false);
|
||||
try {
|
||||
for (Object candidate : classesToImport) {
|
||||
Object candidateToCheck = (candidate instanceof Class ? (Class) candidate :
|
||||
this.metadataReaderFactory.getMetadataReader((String) candidate));
|
||||
if (checkAssignability(ImportSelector.class, candidateToCheck)) {
|
||||
// the candidate class is an ImportSelector -> delegate to it to determine imports
|
||||
Class<?> candidateClass = (candidate instanceof Class ? (Class) candidate :
|
||||
this.resourceLoader.getClassLoader().loadClass((String) candidate));
|
||||
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
|
||||
processImport(configClass, Arrays.asList(selector.selectImports(importingClassMetadata)), false);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
else if (new AssignableTypeFilter(ImportBeanDefinitionRegistrar.class).match(reader, this.metadataReaderFactory)) {
|
||||
// the candidate class is an ImportBeanDefinitionRegistrar -> delegate to it to register additional bean definitions
|
||||
try {
|
||||
ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(
|
||||
this.resourceLoader.getClassLoader().loadClass(candidate), ImportBeanDefinitionRegistrar.class);
|
||||
else if (checkAssignability(ImportBeanDefinitionRegistrar.class, candidateToCheck)) {
|
||||
// the candidate class is an ImportBeanDefinitionRegistrar -> delegate to it to register additional bean definitions
|
||||
Class<?> candidateClass = (candidate instanceof Class ? (Class) candidate :
|
||||
this.resourceLoader.getClassLoader().loadClass((String) candidate));
|
||||
ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
|
||||
invokeAwareMethods(registrar);
|
||||
registrar.registerBeanDefinitions(importingClassMetadata, registry);
|
||||
registrar.registerBeanDefinitions(importingClassMetadata, this.registry);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
else {
|
||||
// candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> process it as a @Configuration class
|
||||
this.importStack.registerImport(importingClassMetadata.getClassName(),
|
||||
(candidate instanceof Class ? ((Class) candidate).getName() : (String) candidate));
|
||||
processConfigurationClass(candidateToCheck instanceof Class ? new ConfigurationClass((Class) candidateToCheck, true) :
|
||||
new ConfigurationClass((MetadataReader) candidateToCheck, true));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// the candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> process it as a @Configuration class
|
||||
this.importStack.registerImport(importingClassMetadata.getClassName(), candidate);
|
||||
processConfigurationClass(new ConfigurationClass(reader, true));
|
||||
}
|
||||
}
|
||||
this.importStack.pop();
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new NestedIOException("Failed to load import candidate class", ex);
|
||||
}
|
||||
finally {
|
||||
this.importStack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkAssignability(Class<?> clazz, Object candidate) throws IOException {
|
||||
if (candidate instanceof Class) {
|
||||
return clazz.isAssignableFrom((Class) candidate);
|
||||
}
|
||||
else {
|
||||
return new AssignableTypeFilter(clazz).match((MetadataReader) candidate, this.metadataReaderFactory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,7 +462,7 @@ class ConfigurationClassParser {
|
||||
return this.propertySources;
|
||||
}
|
||||
|
||||
public ImportRegistry getImportRegistry() {
|
||||
ImportRegistry getImportRegistry() {
|
||||
return this.importStack;
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -85,7 +85,7 @@ import static org.springframework.context.annotation.AnnotationConfigUtils.*;
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
|
||||
ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
|
||||
ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware, Ordered {
|
||||
|
||||
private static final String IMPORT_AWARE_PROCESSOR_BEAN_NAME =
|
||||
ConfigurationClassPostProcessor.class.getName() + ".importAwareProcessor";
|
||||
@@ -368,6 +368,11 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.HIGHEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
|
||||
private static class ImportAwareBeanPostProcessor implements PriorityOrdered, BeanFactoryAware, BeanPostProcessor {
|
||||
|
||||
|
||||
+9
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,7 @@ import java.io.IOException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.core.Conventions;
|
||||
@@ -37,14 +38,14 @@ import org.springframework.stereotype.Component;
|
||||
*/
|
||||
abstract class ConfigurationClassUtils {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ConfigurationClassUtils.class);
|
||||
|
||||
private static final String CONFIGURATION_CLASS_FULL = "full";
|
||||
|
||||
private static final String CONFIGURATION_CLASS_LITE = "lite";
|
||||
|
||||
private static final String CONFIGURATION_CLASS_ATTRIBUTE =
|
||||
Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "configurationClass");
|
||||
Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "configurationClass");
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ConfigurationClassUtils.class);
|
||||
|
||||
|
||||
/**
|
||||
@@ -93,7 +94,7 @@ abstract class ConfigurationClassUtils {
|
||||
}
|
||||
|
||||
public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
|
||||
return isFullConfigurationCandidate(metadata) || isLiteConfigurationCandidate(metadata);
|
||||
return (isFullConfigurationCandidate(metadata) || isLiteConfigurationCandidate(metadata));
|
||||
}
|
||||
|
||||
public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) {
|
||||
@@ -101,12 +102,11 @@ abstract class ConfigurationClassUtils {
|
||||
}
|
||||
|
||||
public static boolean isLiteConfigurationCandidate(AnnotationMetadata metadata) {
|
||||
return !metadata.isInterface() && // not an interface or an annotation
|
||||
(metadata.isAnnotated(Component.class.getName()) ||
|
||||
metadata.hasAnnotatedMethods(Bean.class.getName()));
|
||||
// Do not consider an interface or an annotation...
|
||||
return (!metadata.isInterface() && (
|
||||
metadata.isAnnotated(Component.class.getName()) || metadata.hasAnnotatedMethods(Bean.class.getName())));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether the given bean definition indicates a full @Configuration class.
|
||||
*/
|
||||
|
||||
+12
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,6 +36,7 @@ abstract class ConfigurationMethod {
|
||||
this.configurationClass = configurationClass;
|
||||
}
|
||||
|
||||
|
||||
public MethodMetadata getMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
@@ -48,13 +49,22 @@ abstract class ConfigurationMethod {
|
||||
return new Location(this.configurationClass.getResource(), this.metadata);
|
||||
}
|
||||
|
||||
String getFullyQualifiedMethodName() {
|
||||
return this.metadata.getDeclaringClassName() + "#" + this.metadata.getMethodName();
|
||||
}
|
||||
|
||||
static String getShortMethodName(String fullyQualifiedMethodName) {
|
||||
return fullyQualifiedMethodName.substring(fullyQualifiedMethodName.indexOf('#') + 1);
|
||||
}
|
||||
|
||||
public void validate(ProblemReporter problemReporter) {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[%s:name=%s,declaringClass=%s]",
|
||||
this.getClass().getSimpleName(), this.getMetadata().getMethodName(), this.getMetadata().getDeclaringClassName());
|
||||
getClass().getSimpleName(), getMetadata().getMethodName(), getMetadata().getDeclaringClassName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,9 +52,9 @@ public class GenericApplicationListenerAdapter implements SmartApplicationListen
|
||||
}
|
||||
|
||||
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
|
||||
Class typeArg = GenericTypeResolver.resolveTypeArgument(this.delegate.getClass(), ApplicationListener.class);
|
||||
Class<?> typeArg = GenericTypeResolver.resolveTypeArgument(this.delegate.getClass(), ApplicationListener.class);
|
||||
if (typeArg == null || typeArg.equals(ApplicationEvent.class)) {
|
||||
Class targetClass = AopUtils.getTargetClass(this.delegate);
|
||||
Class<?> targetClass = AopUtils.getTargetClass(this.delegate);
|
||||
if (targetClass != this.delegate.getClass()) {
|
||||
typeArg = GenericTypeResolver.resolveTypeArgument(targetClass, ApplicationListener.class);
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -108,8 +108,8 @@ public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerS
|
||||
* <p>Processing occurs by replacing ${...} placeholders in bean definitions by resolving each
|
||||
* against this configurer's set of {@link PropertySources}, which includes:
|
||||
* <ul>
|
||||
* <li>all {@linkplain org.springframework.core.env.ConfigurableEnvironment#getPropertySources environment property sources}, if an
|
||||
* {@code Environment} {@linkplain #setEnvironment is present}
|
||||
* <li>all {@linkplain org.springframework.core.env.ConfigurableEnvironment#getPropertySources
|
||||
* environment property sources}, if an {@code Environment} {@linkplain #setEnvironment is present}
|
||||
* <li>{@linkplain #mergeProperties merged local properties}, if {@linkplain #setLocation any}
|
||||
* {@linkplain #setLocations have} {@linkplain #setProperties been}
|
||||
* {@linkplain #setPropertiesArray specified}
|
||||
@@ -135,7 +135,7 @@ public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerS
|
||||
}
|
||||
try {
|
||||
PropertySource<?> localPropertySource =
|
||||
new PropertiesPropertySource(LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME, this.mergeProperties());
|
||||
new PropertiesPropertySource(LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME, mergeProperties());
|
||||
if (this.localOverride) {
|
||||
this.propertySources.addFirst(localPropertySource);
|
||||
}
|
||||
@@ -148,7 +148,7 @@ public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerS
|
||||
}
|
||||
}
|
||||
|
||||
this.processProperties(beanFactory, new PropertySourcesPropertyResolver(this.propertySources));
|
||||
processProperties(beanFactory, new PropertySourcesPropertyResolver(this.propertySources));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+30
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,22 +23,26 @@ import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Declares that a field should be formatted as a date time.
|
||||
* Supports formatting by style pattern, ISO date time pattern, or custom format pattern string.
|
||||
* Can be applied to {@code java.util.Date}, {@code java.util.Calendar}, {@code java.long.Long}, or Joda Time fields.
|
||||
* <p>
|
||||
* For style-based formatting, set the {@link #style()} attribute to be the style pattern code.
|
||||
*
|
||||
* <p>Supports formatting by style pattern, ISO date time pattern, or custom format pattern string.
|
||||
* Can be applied to {@code java.util.Date}, {@code java.util.Calendar}, {@code java.long.Long},
|
||||
* Joda-Time value types; and as of Spring 4 and JDK 8, to JSR-310 <code>java.time</code> types too.
|
||||
*
|
||||
* <p>For style-based formatting, set the {@link #style()} attribute to be the style pattern code.
|
||||
* The first character of the code is the date style, and the second character is the time style.
|
||||
* Specify a character of 'S' for short style, 'M' for medium, 'L' for long, and 'F' for full.
|
||||
* A date or time may be omitted by specifying the style character '-'.
|
||||
* <p>
|
||||
* For ISO-based formatting, set the {@link #iso()} attribute to be the desired {@link ISO} format, such as {@link ISO#DATE}.
|
||||
<p>
|
||||
* For custom formatting, set the {@link #pattern()} attribute to be the DateTime pattern, such as {@code yyyy/MM/dd hh:mm:ss a}.
|
||||
* <p>
|
||||
* Each attribute is mutually exclusive, so only set one attribute per annotation instance (the one most convenient one for your formatting needs).
|
||||
*
|
||||
* <p>For ISO-based formatting, set the {@link #iso()} attribute to be the desired {@link ISO} format,
|
||||
* such as {@link ISO#DATE}. For custom formatting, set the {@link #pattern()} attribute to be the
|
||||
* DateTime pattern, such as {@code yyyy/MM/dd hh:mm:ss a}.
|
||||
*
|
||||
* <p>Each attribute is mutually exclusive, so only set one attribute per annotation instance
|
||||
* (the one most convenient one for your formatting needs).
|
||||
* When the pattern attribute is specified, it takes precedence over both the style and ISO attribute.
|
||||
* When the iso attribute is specified, if takes precedence over the style attribute.
|
||||
* When no annotation attributes are specified, the default format applied is style-based with a style code of 'SS' (short date, short time).
|
||||
* When no annotation attributes are specified, the default format applied is style-based
|
||||
* with a style code of 'SS' (short date, short time).
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
@@ -51,23 +55,24 @@ public @interface DateTimeFormat {
|
||||
|
||||
/**
|
||||
* The style pattern to use to format the field.
|
||||
* Defaults to 'SS' for short date time.
|
||||
* Set this attribute when you wish to format your field in accordance with a common style other than the default style.
|
||||
* <p>Defaults to 'SS' for short date time. Set this attribute when you wish to format
|
||||
* your field in accordance with a common style other than the default style.
|
||||
*/
|
||||
String style() default "SS";
|
||||
|
||||
/**
|
||||
* The ISO pattern to use to format the field.
|
||||
* The possible ISO patterns are defined in the {@link ISO} enum.
|
||||
* Defaults to ISO.NONE, indicating this attribute should be ignored.
|
||||
* Set this attribute when you wish to format your field in accordance with an ISO date time format.
|
||||
* <p>Defaults to {@link ISO#NONE}, indicating this attribute should be ignored.
|
||||
* Set this attribute when you wish to format your field in accordance with an ISO format.
|
||||
*/
|
||||
ISO iso() default ISO.NONE;
|
||||
|
||||
/**
|
||||
* The custom pattern to use to format the field.
|
||||
* Defaults to empty String, indicating no custom pattern String has been specified.
|
||||
* Set this attribute when you wish to format your field in accordance with a custom date time pattern not represented by a style or ISO format.
|
||||
* <p>Defaults to empty String, indicating no custom pattern String has been specified.
|
||||
* Set this attribute when you wish to format your field in accordance with a custom
|
||||
* date time pattern not represented by a style or ISO format.
|
||||
*/
|
||||
String pattern() default "";
|
||||
|
||||
@@ -78,18 +83,21 @@ public @interface DateTimeFormat {
|
||||
public enum ISO {
|
||||
|
||||
/**
|
||||
* The most common ISO Date Format {@code yyyy-MM-dd} e.g. 2000-10-31.
|
||||
* The most common ISO Date Format {@code yyyy-MM-dd},
|
||||
* e.g. 2000-10-31.
|
||||
*/
|
||||
DATE,
|
||||
|
||||
/**
|
||||
* The most common ISO Time Format {@code HH:mm:ss.SSSZ} e.g. 01:30:00.000-05:00.
|
||||
* The most common ISO Time Format {@code HH:mm:ss.SSSZ},
|
||||
* e.g. 01:30:00.000-05:00.
|
||||
*/
|
||||
TIME,
|
||||
|
||||
/**
|
||||
* The most common ISO DateTime Format {@code yyyy-MM-dd'T'HH:mm:ss.SSSZ} e.g. 2000-10-31 01:30:00.000-05:00.
|
||||
* The default if no annotation value is specified.
|
||||
* The most common ISO DateTime Format {@code yyyy-MM-dd'T'HH:mm:ss.SSSZ},
|
||||
* e.g. 2000-10-31 01:30:00.000-05:00.
|
||||
* <p>This is the default if no annotation value is specified.
|
||||
*/
|
||||
DATE_TIME,
|
||||
|
||||
|
||||
+13
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,7 +46,7 @@ public class DateFormatter implements Formatter<Date> {
|
||||
|
||||
private static final Map<ISO, String> ISO_PATTERNS;
|
||||
static {
|
||||
Map<ISO, String> formats = new HashMap<DateTimeFormat.ISO, String>();
|
||||
Map<ISO, String> formats = new HashMap<DateTimeFormat.ISO, String>(4);
|
||||
formats.put(ISO.DATE, "yyyy-MM-dd");
|
||||
formats.put(ISO.TIME, "HH:mm:ss.SSSZ");
|
||||
formats.put(ISO.DATE_TIME, "yyyy-MM-dd'T'HH:mm:ss.SSSZ");
|
||||
@@ -89,6 +89,15 @@ public class DateFormatter implements Formatter<Date> {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ISO format used for this date.
|
||||
* @param iso the {@link ISO} format
|
||||
* @since 3.2
|
||||
*/
|
||||
public void setIso(ISO iso) {
|
||||
this.iso = iso;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the style to use to format date values.
|
||||
* <p>If not specified, DateFormat's default style will be used.
|
||||
@@ -112,7 +121,7 @@ public class DateFormatter implements Formatter<Date> {
|
||||
* <li>'F' = Full</li>
|
||||
* <li>'-' = Omitted</li>
|
||||
* <ul>
|
||||
* This method mimics the styles supported by Joda Time.
|
||||
* This method mimics the styles supported by Joda-Time.
|
||||
* @param stylePattern two characters from the set {"S", "M", "L", "F", "-"}
|
||||
* @since 3.2
|
||||
*/
|
||||
@@ -120,14 +129,6 @@ public class DateFormatter implements Formatter<Date> {
|
||||
this.stylePattern = stylePattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ISO format used for this date.
|
||||
* @param iso the {@link ISO} format
|
||||
* @since 3.2
|
||||
*/
|
||||
public void setIso(ISO iso) {
|
||||
this.iso = iso;
|
||||
}
|
||||
/**
|
||||
* Set the TimeZone to normalize the date values into, if any.
|
||||
*/
|
||||
@@ -204,4 +205,5 @@ public class DateFormatter implements Formatter<Date> {
|
||||
}
|
||||
throw new IllegalStateException("Unsupported style pattern '"+ stylePattern+ "'");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+20
-14
@@ -27,8 +27,8 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Configures Date formatting for use with Spring.
|
||||
* <p>
|
||||
* Designed for direct instantiation but also exposes the static
|
||||
*
|
||||
* <p>Designed for direct instantiation but also exposes the static
|
||||
* {@link #addDateConverters(ConverterRegistry)} utility method for ad hoc use
|
||||
* against any {@code ConverterRegistry} instance.
|
||||
*
|
||||
@@ -39,10 +39,20 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
|
||||
private DateFormatter dateFormatter;
|
||||
|
||||
|
||||
/**
|
||||
* Set the date formatter to register. If not specified no formatter is registered.
|
||||
* This method can be used if global formatter configuration is required.
|
||||
* @param dateFormatter the date formatter
|
||||
*/
|
||||
public void setFormatter(DateFormatter dateFormatter) {
|
||||
Assert.notNull(dateFormatter, "DateFormatter must not be null");
|
||||
this.dateFormatter = dateFormatter;
|
||||
}
|
||||
|
||||
|
||||
public void registerFormatters(FormatterRegistry registry) {
|
||||
addDateConverters(registry);
|
||||
registry.addFormatterForFieldAnnotation(new DateTimeFormatAnnotationFormatterFactory());
|
||||
@@ -55,16 +65,6 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the date formatter to register. If not specified no formatter is registered.
|
||||
* This method can be used if global formatter configuration is required.
|
||||
* @param dateFormatter the date formatter
|
||||
*/
|
||||
public void setFormatter(DateFormatter dateFormatter) {
|
||||
Assert.notNull(dateFormatter, "DateFormatter must not be null");
|
||||
this.dateFormatter = dateFormatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add date converters to the specified registry.
|
||||
* @param converterRegistry the registry of converters to add to
|
||||
@@ -80,6 +80,7 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
|
||||
private static class DateToLongConverter implements Converter<Date, Long> {
|
||||
|
||||
public Long convert(Date source) {
|
||||
return source.getTime();
|
||||
}
|
||||
@@ -87,6 +88,7 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
|
||||
private static class DateToCalendarConverter implements Converter<Date, Calendar> {
|
||||
|
||||
public Calendar convert(Date source) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(source);
|
||||
@@ -96,6 +98,7 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
|
||||
private static class CalendarToDateConverter implements Converter<Calendar, Date> {
|
||||
|
||||
public Date convert(Calendar source) {
|
||||
return source.getTime();
|
||||
}
|
||||
@@ -103,6 +106,7 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
|
||||
private static class CalendarToLongConverter implements Converter<Calendar, Long> {
|
||||
|
||||
public Long convert(Calendar source) {
|
||||
return source.getTime().getTime();
|
||||
}
|
||||
@@ -110,6 +114,7 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
|
||||
private static class LongToDateConverter implements Converter<Long, Date> {
|
||||
|
||||
public Date convert(Long source) {
|
||||
return new Date(source);
|
||||
}
|
||||
@@ -118,10 +123,11 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
private static class LongToCalendarConverter implements Converter<Long, Calendar> {
|
||||
|
||||
private DateToCalendarConverter dateToCalendarConverter = new DateToCalendarConverter();
|
||||
private final DateToCalendarConverter dateToCalendarConverter = new DateToCalendarConverter();
|
||||
|
||||
public Calendar convert(Long source) {
|
||||
return this.dateToCalendarConverter.convert(new Date(source));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -44,7 +44,7 @@ public class DateTimeFormatAnnotationFormatterFactory implements
|
||||
|
||||
private static final Set<Class<?>> FIELD_TYPES;
|
||||
static {
|
||||
Set<Class<?>> fieldTypes = new HashSet<Class<?>>();
|
||||
Set<Class<?>> fieldTypes = new HashSet<Class<?>>(4);
|
||||
fieldTypes.add(Date.class);
|
||||
fieldTypes.add(Calendar.class);
|
||||
fieldTypes.add(Long.class);
|
||||
@@ -82,4 +82,5 @@ public class DateTimeFormatAnnotationFormatterFactory implements
|
||||
protected String resolveEmbeddedValue(String value) {
|
||||
return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+66
-64
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,32 +22,34 @@ import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.joda.time.format.ISODateTimeFormat;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Factory that creates a Joda {@link DateTimeFormatter}. Formatters will be
|
||||
* created using the defined {@link #setPattern(String) pattern}, {@link #setIso ISO},
|
||||
* or {@link #setStyle(String) style} (considered in that order).
|
||||
* Factory that creates a Joda-Time {@link DateTimeFormatter}.
|
||||
*
|
||||
* <p>Formatters will be created using the defined {@link #setPattern pattern},
|
||||
* {@link #setIso ISO}, and {@link #setStyle style} methods (considered in that order).
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
* @since 3.2
|
||||
* @see #createDateTimeFormatter()
|
||||
* @see #createDateTimeFormatter(DateTimeFormatter)
|
||||
* @see #setPattern(String)
|
||||
* @see #setPattern
|
||||
* @see #setStyle
|
||||
* @see #setIso
|
||||
* @see #setStyle(String)
|
||||
* @see DateTimeFormatterFactoryBean
|
||||
*/
|
||||
public class DateTimeFormatterFactory {
|
||||
|
||||
private String pattern;
|
||||
|
||||
private ISO iso;
|
||||
|
||||
private String style;
|
||||
|
||||
private String pattern;
|
||||
|
||||
private TimeZone timeZone;
|
||||
|
||||
|
||||
@@ -67,9 +69,50 @@ public class DateTimeFormatterFactory {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code DateTimeFormatter} using this factory. If no specific
|
||||
* {@link #setStyle(String) style}, {@link #setIso ISO}, or
|
||||
* {@link #setPattern(String) pattern} have been defined the
|
||||
* Set the pattern to use to format date values.
|
||||
* @param pattern the format pattern
|
||||
*/
|
||||
public void setPattern(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ISO format used to format date values.
|
||||
* @param iso the ISO format
|
||||
*/
|
||||
public void setIso(ISO iso) {
|
||||
this.iso = iso;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the two characters to use to format date values, in Joda-Time style.
|
||||
* <p>The first character is used for the date style; the second is for
|
||||
* the time style. Supported characters are:
|
||||
* <ul>
|
||||
* <li>'S' = Small</li>
|
||||
* <li>'M' = Medium</li>
|
||||
* <li>'L' = Long</li>
|
||||
* <li>'F' = Full</li>
|
||||
* <li>'-' = Omitted</li>
|
||||
* </ul>
|
||||
* @param style two characters from the set {"S", "M", "L", "F", "-"}
|
||||
*/
|
||||
public void setStyle(String style) {
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@code TimeZone} to normalize the date values into, if any.
|
||||
* @param timeZone the time zone
|
||||
*/
|
||||
public void setTimeZone(TimeZone timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code DateTimeFormatter} using this factory.
|
||||
* <p>If no specific pattern or style has been defined,
|
||||
* {@link DateTimeFormat#mediumDateTime() medium date time format} will be used.
|
||||
* @return a new date time formatter
|
||||
* @see #createDateTimeFormatter(DateTimeFormatter)
|
||||
@@ -79,21 +122,20 @@ public class DateTimeFormatterFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code DateTimeFormatter} using this factory. If no specific
|
||||
* {@link #setStyle(String) style}, {@link #setIso ISO}, or
|
||||
* {@link #setPattern(String) pattern} have been defined the supplied
|
||||
* {@code fallbackFormatter} will be used.
|
||||
* @param fallbackFormatter the fall-back formatter to use when no specific factory
|
||||
* properties have been set (can be {@code null}).
|
||||
* Create a new {@code DateTimeFormatter} using this factory.
|
||||
* <p>If no specific pattern or style has been defined,
|
||||
* the supplied {@code fallbackFormatter} will be used.
|
||||
* @param fallbackFormatter the fall-back formatter to use when no specific
|
||||
* factory properties have been set (can be {@code null}).
|
||||
* @return a new date time formatter
|
||||
*/
|
||||
public DateTimeFormatter createDateTimeFormatter(DateTimeFormatter fallbackFormatter) {
|
||||
DateTimeFormatter dateTimeFormatter = null;
|
||||
if (StringUtils.hasLength(pattern)) {
|
||||
dateTimeFormatter = DateTimeFormat.forPattern(pattern);
|
||||
if (StringUtils.hasLength(this.pattern)) {
|
||||
dateTimeFormatter = DateTimeFormat.forPattern(this.pattern);
|
||||
}
|
||||
else if (iso != null && iso != ISO.NONE) {
|
||||
switch (iso) {
|
||||
else if (this.iso != null && this.iso != ISO.NONE) {
|
||||
switch (this.iso) {
|
||||
case DATE:
|
||||
dateTimeFormatter = ISODateTimeFormat.date();
|
||||
break;
|
||||
@@ -107,11 +149,11 @@ public class DateTimeFormatterFactory {
|
||||
/* no-op */
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported ISO format: " + iso);
|
||||
throw new IllegalStateException("Unsupported ISO format: " + this.iso);
|
||||
}
|
||||
}
|
||||
else if (StringUtils.hasLength(style)) {
|
||||
dateTimeFormatter = DateTimeFormat.forStyle(style);
|
||||
else if (StringUtils.hasLength(this.style)) {
|
||||
dateTimeFormatter = DateTimeFormat.forStyle(this.style);
|
||||
}
|
||||
|
||||
if (dateTimeFormatter != null && this.timeZone != null) {
|
||||
@@ -120,44 +162,4 @@ public class DateTimeFormatterFactory {
|
||||
return (dateTimeFormatter != null ? dateTimeFormatter : fallbackFormatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@code TimeZone} to normalize the date values into, if any.
|
||||
* @param timeZone the time zone
|
||||
*/
|
||||
public void setTimeZone(TimeZone timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the two characters to use to format date values. The first character is used for
|
||||
* the date style; the second is for the time style. Supported characters are:
|
||||
* <ul>
|
||||
* <li>'S' = Small</li>
|
||||
* <li>'M' = Medium</li>
|
||||
* <li>'L' = Long</li>
|
||||
* <li>'F' = Full</li>
|
||||
* <li>'-' = Omitted</li>
|
||||
* </ul>
|
||||
* <p>This method mimics the styles supported by Joda Time.
|
||||
* @param style two characters from the set {"S", "M", "L", "F", "-"}
|
||||
*/
|
||||
public void setStyle(String style) {
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ISO format used to format date values.
|
||||
* @param iso the ISO format
|
||||
*/
|
||||
public void setIso(ISO iso) {
|
||||
this.iso = iso;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the pattern to use to format date values.
|
||||
* @param pattern the format pattern
|
||||
*/
|
||||
public void setPattern(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,15 +22,15 @@ import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} that creates a Joda {@link DateTimeFormatter}. See the
|
||||
* {@linkplain DateTimeFormatterFactory base class} for configuration details.
|
||||
* {@link FactoryBean} that creates a Joda-Time {@link DateTimeFormatter}.
|
||||
* See the {@link DateTimeFormatterFactory base class} for configuration details.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
* @since 3.2
|
||||
* @see #setPattern(String)
|
||||
* @see #setIso(org.springframework.format.annotation.DateTimeFormat.ISO)
|
||||
* @see #setStyle(String)
|
||||
* @see #setPattern
|
||||
* @see #setIso
|
||||
* @see #setStyle
|
||||
* @see DateTimeFormatterFactory
|
||||
*/
|
||||
public class DateTimeFormatterFactoryBean extends DateTimeFormatterFactory
|
||||
|
||||
+12
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -56,7 +56,7 @@ public class JodaDateTimeFormatAnnotationFormatterFactory
|
||||
// (if we did not do this, the default byType rules for LocalDate, LocalTime,
|
||||
// and LocalDateTime would take precedence over the annotation rule, which
|
||||
// is not what we want)
|
||||
Set<Class<?>> fieldTypes = new HashSet<Class<?>>(7);
|
||||
Set<Class<?>> fieldTypes = new HashSet<Class<?>>(8);
|
||||
fieldTypes.add(ReadableInstant.class);
|
||||
fieldTypes.add(LocalDate.class);
|
||||
fieldTypes.add(LocalTime.class);
|
||||
@@ -71,10 +71,6 @@ public class JodaDateTimeFormatAnnotationFormatterFactory
|
||||
private StringValueResolver embeddedValueResolver;
|
||||
|
||||
|
||||
public final Set<Class<?>> getFieldTypes() {
|
||||
return FIELD_TYPES;
|
||||
}
|
||||
|
||||
public void setEmbeddedValueResolver(StringValueResolver resolver) {
|
||||
this.embeddedValueResolver = resolver;
|
||||
}
|
||||
@@ -83,20 +79,24 @@ public class JodaDateTimeFormatAnnotationFormatterFactory
|
||||
return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value);
|
||||
}
|
||||
|
||||
|
||||
public final Set<Class<?>> getFieldTypes() {
|
||||
return FIELD_TYPES;
|
||||
}
|
||||
|
||||
public Printer<?> getPrinter(DateTimeFormat annotation, Class<?> fieldType) {
|
||||
DateTimeFormatter formatter = getFormatter(annotation, fieldType);
|
||||
if (ReadableInstant.class.isAssignableFrom(fieldType)) {
|
||||
return new ReadableInstantPrinter(formatter);
|
||||
}
|
||||
if (ReadablePartial.class.isAssignableFrom(fieldType)) {
|
||||
return new ReadablePartialPrinter(formatter);
|
||||
}
|
||||
if (Calendar.class.isAssignableFrom(fieldType)) {
|
||||
else if (ReadableInstant.class.isAssignableFrom(fieldType) || Calendar.class.isAssignableFrom(fieldType)) {
|
||||
// assumes Calendar->ReadableInstant converter is registered
|
||||
return new ReadableInstantPrinter(formatter);
|
||||
}
|
||||
// assumes Date->Long converter is registered
|
||||
return new MillisecondInstantPrinter(formatter);
|
||||
else {
|
||||
// assumes Date->Long converter is registered
|
||||
return new MillisecondInstantPrinter(formatter);
|
||||
}
|
||||
}
|
||||
|
||||
public Parser<DateTime> getParser(DateTimeFormat annotation, Class<?> fieldType) {
|
||||
|
||||
+12
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,8 +21,10 @@ import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* A context that holds user-specific Joda Time settings such as the user's Chronology (calendar system) and time zone.
|
||||
* A {@code null} property value indicate the user has not specified a setting.
|
||||
* A context that holds user-specific Joda-Time settings such as the user's
|
||||
* Chronology (calendar system) and time zone.
|
||||
*
|
||||
* <p>A {@code null} property value indicate the user has not specified a setting.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
@@ -43,8 +45,7 @@ public class JodaTimeContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* The user's chronology (calendar system).
|
||||
* Null if not specified.
|
||||
* The user's chronology (calendar system), if any.
|
||||
*/
|
||||
public Chronology getChronology() {
|
||||
return this.chronology;
|
||||
@@ -58,8 +59,7 @@ public class JodaTimeContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* The user's timezone.
|
||||
* Null if not specified.
|
||||
* The user's timezone, if any.
|
||||
*/
|
||||
public DateTimeZone getTimeZone() {
|
||||
return timeZone;
|
||||
@@ -67,9 +67,11 @@ public class JodaTimeContext {
|
||||
|
||||
|
||||
/**
|
||||
* Gets the Formatter with the this context's settings applied to the base {@code formatter}.
|
||||
* @param formatter the base formatter that establishes default formatting rules, generally context independent
|
||||
* @return the context DateTimeFormatter
|
||||
* Get the DateTimeFormatter with the this context's settings
|
||||
* applied to the base {@code formatter}.
|
||||
* @param formatter the base formatter that establishes default
|
||||
* formatting rules, generally context-independent
|
||||
* @return the contextual DateTimeFormatter
|
||||
*/
|
||||
public DateTimeFormatter getFormatter(DateTimeFormatter formatter) {
|
||||
if (this.chronology != null) {
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,7 +23,8 @@ import org.joda.time.format.DateTimeFormatter;
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
|
||||
/**
|
||||
* A holder for a thread-local user {@link JodaTimeContext}.
|
||||
* A holder for a thread-local {@link JodaTimeContext}
|
||||
* with user-specific Joda-Time settings.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+42
-54
@@ -27,12 +27,14 @@ import org.joda.time.LocalDateTime;
|
||||
import org.joda.time.LocalTime;
|
||||
import org.joda.time.MutableDateTime;
|
||||
import org.joda.time.ReadableInstant;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterRegistry;
|
||||
import org.springframework.format.datetime.DateFormatterRegistrar;
|
||||
|
||||
/**
|
||||
* Installs lower-level type converters required to integrate Joda Time support into Spring's field formatting system.
|
||||
* Installs lower-level type converters required to integrate
|
||||
* Joda-Time support into Spring's field formatting system.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Phillip Webb
|
||||
@@ -50,116 +52,87 @@ final class JodaTimeConverters {
|
||||
registry.addConverter(new DateTimeToLocalTimeConverter());
|
||||
registry.addConverter(new DateTimeToLocalDateTimeConverter());
|
||||
registry.addConverter(new DateTimeToDateMidnightConverter());
|
||||
registry.addConverter(new DateTimeToInstantConverter());
|
||||
registry.addConverter(new DateTimeToMutableDateTimeConverter());
|
||||
registry.addConverter(new DateTimeToInstantConverter());
|
||||
registry.addConverter(new DateTimeToDateConverter());
|
||||
registry.addConverter(new DateTimeToCalendarConverter());
|
||||
registry.addConverter(new DateTimeToLongConverter());
|
||||
registry.addConverter(new CalendarToReadableInstantConverter());
|
||||
registry.addConverter(new DateToReadableInstantConverter());
|
||||
registry.addConverter(new CalendarToReadableInstantConverter());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a LocalDate field.
|
||||
* @see DateTimeParser
|
||||
**/
|
||||
private static class DateTimeToLocalDateConverter implements Converter<DateTime, LocalDate> {
|
||||
|
||||
public LocalDate convert(DateTime source) {
|
||||
return source.toLocalDate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a LocalTime field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
|
||||
private static class DateTimeToLocalTimeConverter implements Converter<DateTime, LocalTime> {
|
||||
|
||||
public LocalTime convert(DateTime source) {
|
||||
return source.toLocalTime();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a LocalDateTime field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
|
||||
private static class DateTimeToLocalDateTimeConverter implements Converter<DateTime, LocalDateTime> {
|
||||
|
||||
public LocalDateTime convert(DateTime source) {
|
||||
return source.toLocalDateTime();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a DateMidnight field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
|
||||
private static class DateTimeToDateMidnightConverter implements Converter<DateTime, DateMidnight> {
|
||||
|
||||
public DateMidnight convert(DateTime source) {
|
||||
return source.toDateMidnight();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to an Instant field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
private static class DateTimeToInstantConverter implements Converter<DateTime, Instant> {
|
||||
public Instant convert(DateTime source) {
|
||||
return source.toInstant();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a MutableDateTime field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
private static class DateTimeToMutableDateTimeConverter implements Converter<DateTime, MutableDateTime> {
|
||||
|
||||
public MutableDateTime convert(DateTime source) {
|
||||
return source.toMutableDateTime();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a java.util.Date field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
|
||||
private static class DateTimeToInstantConverter implements Converter<DateTime, Instant> {
|
||||
|
||||
public Instant convert(DateTime source) {
|
||||
return source.toInstant();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class DateTimeToDateConverter implements Converter<DateTime, Date> {
|
||||
|
||||
public Date convert(DateTime source) {
|
||||
return source.toDate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a java.util.Calendar field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
|
||||
private static class DateTimeToCalendarConverter implements Converter<DateTime, Calendar> {
|
||||
|
||||
public Calendar convert(DateTime source) {
|
||||
return source.toGregorianCalendar();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a java.lang.Long field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
|
||||
private static class DateTimeToLongConverter implements Converter<DateTime, Long> {
|
||||
|
||||
public Long convert(DateTime source) {
|
||||
return source.getMillis();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when printing a java.util.Calendar field with a ReadableInstantPrinter.
|
||||
* @see MillisecondInstantPrinter
|
||||
* @see JodaDateTimeFormatAnnotationFormatterFactory
|
||||
*/
|
||||
private static class CalendarToReadableInstantConverter implements Converter<Calendar, ReadableInstant> {
|
||||
public ReadableInstant convert(Calendar source) {
|
||||
return new DateTime(source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when printing a java.util.Date field with a ReadableInstantPrinter.
|
||||
@@ -167,8 +140,23 @@ final class JodaTimeConverters {
|
||||
* @see JodaDateTimeFormatAnnotationFormatterFactory
|
||||
*/
|
||||
private static class DateToReadableInstantConverter implements Converter<Date, ReadableInstant> {
|
||||
|
||||
public ReadableInstant convert(Date source) {
|
||||
return new DateTime(source);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used when printing a java.util.Calendar field with a ReadableInstantPrinter.
|
||||
* @see MillisecondInstantPrinter
|
||||
* @see JodaDateTimeFormatAnnotationFormatterFactory
|
||||
*/
|
||||
private static class CalendarToReadableInstantConverter implements Converter<Calendar, ReadableInstant> {
|
||||
|
||||
public ReadableInstant convert(Calendar source) {
|
||||
return new DateTime(source);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+35
-30
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author 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.format.datetime.joda;
|
||||
|
||||
import java.util.Calendar;
|
||||
@@ -35,7 +36,7 @@ import org.springframework.format.Printer;
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
|
||||
/**
|
||||
* Configures Joda Time's formatting system for use with Spring.
|
||||
* Configures Joda-Time's formatting system for use with Spring.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
@@ -51,15 +52,18 @@ import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
*/
|
||||
public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
private static enum Type {DATE, TIME, DATE_TIME}
|
||||
|
||||
|
||||
/**
|
||||
* User defined formatters.
|
||||
*/
|
||||
private Map<Type, DateTimeFormatter> formatters = new HashMap<Type, DateTimeFormatter>();
|
||||
private final Map<Type, DateTimeFormatter> formatters = new HashMap<Type, DateTimeFormatter>();
|
||||
|
||||
/**
|
||||
* Factories used when specific formatters have not been specified.
|
||||
*/
|
||||
private Map<Type, DateTimeFormatterFactory> factories;
|
||||
private final Map<Type, DateTimeFormatterFactory> factories;
|
||||
|
||||
|
||||
public JodaTimeFormatterRegistrar() {
|
||||
@@ -70,12 +74,24 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set whether standard ISO formatting should be applied to all date/time types.
|
||||
* Default is "false" (no).
|
||||
* <p>If set to "true", the "dateStyle", "timeStyle" and "dateTimeStyle"
|
||||
* properties are effectively ignored.
|
||||
*/
|
||||
public void setUseIsoFormat(boolean useIsoFormat) {
|
||||
this.factories.get(Type.DATE).setIso(useIsoFormat ? ISO.DATE : null);
|
||||
this.factories.get(Type.TIME).setIso(useIsoFormat ? ISO.TIME : null);
|
||||
this.factories.get(Type.DATE_TIME).setIso(useIsoFormat ? ISO.DATE_TIME : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default format style of Joda {@link LocalDate} objects.
|
||||
* Default is {@link DateTimeFormat#shortDate()}.
|
||||
*/
|
||||
public void setDateStyle(String dateStyle) {
|
||||
this.factories.get(Type.DATE).setStyle(dateStyle+"-");
|
||||
this.factories.get(Type.DATE).setStyle(dateStyle + "-");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +99,7 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
* Default is {@link DateTimeFormat#shortTime()}.
|
||||
*/
|
||||
public void setTimeStyle(String timeStyle) {
|
||||
this.factories.get(Type.TIME).setStyle("-"+timeStyle);
|
||||
this.factories.get(Type.TIME).setStyle("-" + timeStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,25 +111,14 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
this.factories.get(Type.DATE_TIME).setStyle(dateTimeStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether standard ISO formatting should be applied to all Date/Time types.
|
||||
* Default is false (no).
|
||||
* If set to true, the dateStyle, timeStyle, and dateTimeStyle properties are ignored.
|
||||
*/
|
||||
public void setUseIsoFormat(boolean useIsoFormat) {
|
||||
this.factories.get(Type.DATE).setIso(useIsoFormat ? ISO.DATE : null);
|
||||
this.factories.get(Type.TIME).setIso(useIsoFormat ? ISO.TIME : null);
|
||||
this.factories.get(Type.DATE_TIME).setIso(useIsoFormat ? ISO.DATE_TIME : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the formatter that will be used for objects representing date values.
|
||||
* <p>This formatter will be used for the {@link LocalDate} type. When specified
|
||||
* the {@link #setDateStyle(String) dateStyle} and
|
||||
* {@link #setUseIsoFormat(boolean) useIsoFormat} properties will be ignored.
|
||||
* @param formatter the formatter to use
|
||||
* @see #setTimeFormatter(DateTimeFormatter)
|
||||
* @see #setDateTimeFormatter(DateTimeFormatter)
|
||||
* @see #setTimeFormatter
|
||||
* @see #setDateTimeFormatter
|
||||
* @since 3.2
|
||||
*/
|
||||
public void setDateFormatter(DateTimeFormatter formatter) {
|
||||
@@ -126,8 +131,8 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
* the {@link #setTimeStyle(String) timeStyle} and
|
||||
* {@link #setUseIsoFormat(boolean) useIsoFormat} properties will be ignored.
|
||||
* @param formatter the formatter to use
|
||||
* @see #setDateFormatter(DateTimeFormatter)
|
||||
* @see #setDateTimeFormatter(DateTimeFormatter)
|
||||
* @see #setDateFormatter
|
||||
* @see #setDateTimeFormatter
|
||||
* @since 3.2
|
||||
*/
|
||||
public void setTimeFormatter(DateTimeFormatter formatter) {
|
||||
@@ -141,14 +146,15 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
* the {@link #setDateTimeStyle(String) dateTimeStyle} and
|
||||
* {@link #setUseIsoFormat(boolean) useIsoFormat} properties will be ignored.
|
||||
* @param formatter the formatter to use
|
||||
* @see #setDateFormatter(DateTimeFormatter)
|
||||
* @see #setTimeFormatter(DateTimeFormatter)
|
||||
* @see #setDateFormatter
|
||||
* @see #setTimeFormatter
|
||||
* @since 3.2
|
||||
*/
|
||||
public void setDateTimeFormatter(DateTimeFormatter formatter) {
|
||||
this.formatters.put(Type.DATE_TIME, formatter);
|
||||
}
|
||||
|
||||
|
||||
public void registerFormatters(FormatterRegistry registry) {
|
||||
JodaTimeConverters.registerConverters(registry);
|
||||
|
||||
@@ -176,26 +182,25 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
new DateTimeParser(dateTimeFormatter),
|
||||
ReadableInstant.class);
|
||||
|
||||
// In order to retain back compatibility we only register Date/Calendar
|
||||
// In order to retain backwards compatibility we only register Date/Calendar
|
||||
// types when a user defined formatter is specified (see SPR-10105)
|
||||
if(this.formatters.containsKey(Type.DATE_TIME)) {
|
||||
if( this.formatters.containsKey(Type.DATE_TIME)) {
|
||||
addFormatterForFields(registry,
|
||||
new ReadableInstantPrinter(dateTimeFormatter),
|
||||
new DateTimeParser(dateTimeFormatter),
|
||||
Date.class, Calendar.class);
|
||||
}
|
||||
|
||||
registry.addFormatterForFieldAnnotation(
|
||||
new JodaDateTimeFormatAnnotationFormatterFactory());
|
||||
registry.addFormatterForFieldAnnotation(new JodaDateTimeFormatAnnotationFormatterFactory());
|
||||
}
|
||||
|
||||
private DateTimeFormatter getFormatter(Type type) {
|
||||
DateTimeFormatter formatter = this.formatters.get(type);
|
||||
if(formatter != null) {
|
||||
if (formatter != null) {
|
||||
return formatter;
|
||||
}
|
||||
DateTimeFormatter fallbackFormatter = getFallbackFormatter(type);
|
||||
return this.factories.get(type).createDateTimeFormatter(fallbackFormatter );
|
||||
return this.factories.get(type).createDateTimeFormatter(fallbackFormatter);
|
||||
}
|
||||
|
||||
private DateTimeFormatter getFallbackFormatter(Type type) {
|
||||
@@ -208,10 +213,10 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
private void addFormatterForFields(FormatterRegistry registry, Printer<?> printer,
|
||||
Parser<?> parser, Class<?>... fieldTypes) {
|
||||
|
||||
for (Class<?> fieldType : fieldTypes) {
|
||||
registry.addFormatterForFieldType(fieldType, printer, parser);
|
||||
}
|
||||
}
|
||||
|
||||
private static enum Type {DATE, TIME, DATE_TIME}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* Integration with the Joda Time for formatting Joda types as well as standard JDK Date types.
|
||||
* Integration with Joda-Time for formatting Joda date and time types as well as standard JDK Date types.
|
||||
*/
|
||||
package org.springframework.format.datetime.joda;
|
||||
|
||||
+6
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -98,15 +98,14 @@ public class ReflectiveLoadTimeWeaver implements LoadTimeWeaver {
|
||||
this.classLoader = classLoader;
|
||||
this.addTransformerMethod = ClassUtils.getMethodIfAvailable(
|
||||
this.classLoader.getClass(), ADD_TRANSFORMER_METHOD_NAME,
|
||||
new Class [] {ClassFileTransformer.class});
|
||||
new Class[] {ClassFileTransformer.class});
|
||||
if (this.addTransformerMethod == null) {
|
||||
throw new IllegalStateException(
|
||||
"ClassLoader [" + classLoader.getClass().getName() + "] does NOT provide an " +
|
||||
"'addTransformer(ClassFileTransformer)' method.");
|
||||
}
|
||||
this.getThrowawayClassLoaderMethod = ClassUtils.getMethodIfAvailable(
|
||||
this.classLoader.getClass(), GET_THROWAWAY_CLASS_LOADER_METHOD_NAME,
|
||||
new Class[0]);
|
||||
this.classLoader.getClass(), GET_THROWAWAY_CLASS_LOADER_METHOD_NAME, new Class[0]);
|
||||
// getThrowawayClassLoader method is optional
|
||||
if (this.getThrowawayClassLoaderMethod == null) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
@@ -119,7 +118,7 @@ public class ReflectiveLoadTimeWeaver implements LoadTimeWeaver {
|
||||
|
||||
public void addTransformer(ClassFileTransformer transformer) {
|
||||
Assert.notNull(transformer, "Transformer must not be null");
|
||||
ReflectionUtils.invokeMethod(this.addTransformerMethod, this.classLoader, new Object[] {transformer});
|
||||
ReflectionUtils.invokeMethod(this.addTransformerMethod, this.classLoader, transformer);
|
||||
}
|
||||
|
||||
public ClassLoader getInstrumentableClassLoader() {
|
||||
@@ -128,11 +127,11 @@ public class ReflectiveLoadTimeWeaver implements LoadTimeWeaver {
|
||||
|
||||
public ClassLoader getThrowawayClassLoader() {
|
||||
if (this.getThrowawayClassLoaderMethod != null) {
|
||||
return (ClassLoader) ReflectionUtils.invokeMethod(this.getThrowawayClassLoaderMethod, this.classLoader,
|
||||
new Object[0]);
|
||||
return (ClassLoader) ReflectionUtils.invokeMethod(this.getThrowawayClassLoaderMethod, this.classLoader);
|
||||
}
|
||||
else {
|
||||
return new SimpleThrowawayClassLoader(this.classLoader);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-3
@@ -16,12 +16,12 @@
|
||||
|
||||
package org.springframework.scheduling.support;
|
||||
|
||||
import org.springframework.scheduling.Trigger;
|
||||
import org.springframework.scheduling.TriggerContext;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.springframework.scheduling.Trigger;
|
||||
import org.springframework.scheduling.TriggerContext;
|
||||
|
||||
/**
|
||||
* {@link Trigger} implementation for cron expressions.
|
||||
* Wraps a {@link CronSequenceGenerator}.
|
||||
@@ -55,6 +55,12 @@ public class CronTrigger implements Trigger {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine the next execution time according to the given trigger context.
|
||||
* <p>Next execution times are calculated based on the
|
||||
* {@linkplain TriggerContext#lastCompletionTime completion time} of the
|
||||
* previous execution; therefore, overlapping executions won't occur.
|
||||
*/
|
||||
public Date nextExecutionTime(TriggerContext triggerContext) {
|
||||
Date date = triggerContext.lastCompletionTime();
|
||||
if (date != null) {
|
||||
|
||||
+21
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -51,6 +51,12 @@ import org.springframework.util.CollectionUtils;
|
||||
* you will almost always use the default Validator anyway. This can also be injected directly
|
||||
* into any target dependency of type {@link org.springframework.validation.Validator}!
|
||||
*
|
||||
* <p><b>NOTE: This class is based on Bean Validation 1.0 and (optionally) Hibernate Validator 4.x.</b>
|
||||
* Nevertheless, its core functionality does work against Bean Validation 1.1 at runtime.
|
||||
* However, there is no special support for Hibernate Validator 5.0 yet; as a consequence,
|
||||
* {@link #setValidationMessageSource} won't work in that scenario. Please stick with
|
||||
* Hibernate Validator 4.3 for the time being, or upgrade to Spring Framework 4.0.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see javax.validation.ValidatorFactory
|
||||
@@ -217,10 +223,23 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
|
||||
configuration.addProperty(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
// Allow for custom post-processing before we actually build the ValidatorFactory.
|
||||
postProcessConfiguration(configuration);
|
||||
|
||||
this.validatorFactory = configuration.buildValidatorFactory();
|
||||
setTargetValidator(this.validatorFactory.getValidator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the given Bean Validation configuration,
|
||||
* adding to or overriding any of its settings.
|
||||
* <p>Invoked right before building the {@link ValidatorFactory}.
|
||||
* @param configuration the Configuration object, pre-populated with
|
||||
* settings driven by LocalValidatorFactoryBean's properties
|
||||
*/
|
||||
protected void postProcessConfiguration(Configuration configuration) {
|
||||
}
|
||||
|
||||
|
||||
public Validator getValidator() {
|
||||
return this.validatorFactory.getValidator();
|
||||
@@ -244,7 +263,7 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid a hard-coded Hibernate Validator 4.1 dependency.
|
||||
* Inner class to avoid a hard-coded Hibernate Validator 4.1+ dependency.
|
||||
*/
|
||||
private static class HibernateValidatorDelegate {
|
||||
|
||||
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -48,9 +48,10 @@ import org.springframework.validation.annotation.Validated;
|
||||
* inline constraint annotations. Validation groups can be specified through {@code @Validated}
|
||||
* as well. By default, JSR-303 will validate against its default group only.
|
||||
*
|
||||
* <p>As of Spring 3.1, this functionality requires Hibernate Validator 4.2 or higher.
|
||||
* In a future version of Spring, this class will autodetect a Bean Validation 1.1 compliant
|
||||
* provider and automatically use the standard method validation support when available.
|
||||
* <p>As of Spring 3.1, this functionality requires Hibernate Validator 4.2 or 4.3.
|
||||
* In Spring 4.0, this class will autodetect a Bean Validation 1.1 compliant provider
|
||||
* (such as Hibernate Validator 5.0) and automatically use the standard method
|
||||
* validation support when available.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
|
||||
+39
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author 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,16 +16,21 @@
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import example.scannable.DefaultNamedComponent;
|
||||
import org.junit.Test;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import example.scannable.DefaultNamedComponent;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
@@ -81,6 +86,22 @@ public class AnnotationBeanNameGeneratorTests {
|
||||
assertEquals(expectedGeneratedBeanName, beanName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateBeanNameFromMetaComponentWithStringValue() {
|
||||
BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(ComponentFromStringMeta.class);
|
||||
String beanName = this.beanNameGenerator.generateBeanName(bd, registry);
|
||||
assertEquals("henry", beanName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateBeanNameFromMetaComponentWithNonStringValue() {
|
||||
BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(ComponentFromNonStringMeta.class);
|
||||
String beanName = this.beanNameGenerator.generateBeanName(bd, registry);
|
||||
assertEquals("annotationBeanNameGeneratorTests.ComponentFromNonStringMeta", beanName);
|
||||
}
|
||||
|
||||
|
||||
@Component("walden")
|
||||
private static class ComponentWithName {
|
||||
@@ -96,4 +117,19 @@ public class AnnotationBeanNameGeneratorTests {
|
||||
private static class AnonymousComponent {
|
||||
}
|
||||
|
||||
@Service("henry")
|
||||
private static class ComponentFromStringMeta {
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Component
|
||||
public @interface NonStringMetaComponent {
|
||||
long value();
|
||||
}
|
||||
|
||||
@NonStringMetaComponent(123)
|
||||
private static class ComponentFromNonStringMeta {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+24
-1
@@ -16,14 +16,17 @@
|
||||
|
||||
package org.springframework.context.annotation.configuration;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -34,6 +37,8 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ImportResource} support.
|
||||
@@ -178,4 +183,22 @@ public class ImportResourceTests {
|
||||
reader=XmlBeanDefinitionReader.class)
|
||||
static class SubResourceConfig extends ImportNonXmlResourceConfig {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void importWithPlaceHolder() throws Exception {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
PropertySource<?> propertySource = new MapPropertySource("test",
|
||||
Collections.<String, Object> singletonMap("test", "springframework"));
|
||||
ctx.getEnvironment().getPropertySources().addFirst(propertySource);
|
||||
ctx.register(ImportXmlConfig.class);
|
||||
ctx.refresh();
|
||||
assertTrue("did not contain xml-declared bean", ctx.containsBean("xmlDeclaredBean"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ImportResource("classpath:org/${test}/context/annotation/configuration/ImportXmlConfig-context.xml")
|
||||
static class ImportWithPlaceHolder {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -79,7 +79,7 @@ public class ImportedConfigurationClassEnhancementTests {
|
||||
|
||||
|
||||
@Test(expected=BeanDefinitionParsingException.class)
|
||||
public void importingAnNonConfigurationClassCausesIllegalArgumentException() {
|
||||
public void importingNonConfigurationClassCausesBeanDefinitionParsingException() {
|
||||
new AnnotationConfigApplicationContext(ConfigThatImportsNonConfigClass.class);
|
||||
}
|
||||
}
|
||||
@@ -103,5 +103,5 @@ class ConfigThatDoesImport extends Config { }
|
||||
class ConfigThatDoesNotImport extends Config { }
|
||||
|
||||
@Configuration
|
||||
@Import(Void.class)
|
||||
@Import(TestBean.class)
|
||||
class ConfigThatImportsNonConfigClass { }
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author 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.context.annotation.spr10546;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
public class ImportedConfig {
|
||||
@Bean
|
||||
public String myBean() {
|
||||
return "myBean";
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author 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.context.annotation.spr10546;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
public class ParentConfig {
|
||||
@Bean
|
||||
public String myBean() {
|
||||
return "myBean";
|
||||
}
|
||||
}
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author 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.context.annotation.spr10546;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.spr10546.scanpackage.AEnclosingConfig;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan(basePackageClasses=AEnclosingConfig.class)
|
||||
public class ParentWithComponentScanConfig {
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author 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.context.annotation.spr10546;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
@Import(ImportedConfig.class)
|
||||
public class ParentWithImportConfig {
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author 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.context.annotation.spr10546;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
@ImportResource("classpath:org/springframework/context/annotation/spr10546/importedResource.xml")
|
||||
public class ParentWithImportResourceConfig {
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author 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.context.annotation.spr10546;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
public class ParentWithParentConfig extends ParentConfig {
|
||||
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author 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.context.annotation.spr10546;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.spr10546.scanpackage.AEnclosingConfig;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class Spr10546Tests {
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
@After
|
||||
public void closeContext() {
|
||||
if(context != null) {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
// These fail prior to fixing SPR-10546
|
||||
|
||||
@Test
|
||||
public void enclosingConfigFirstParentDefinesBean() {
|
||||
assertLoadsMyBean(AEnclosingConfig.class,AEnclosingConfig.ChildConfig.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prior to fixing SPR-10546 this might have succeeded depending on the ordering the
|
||||
* classes were picked up. If they are picked up in the same order as
|
||||
* {@link #enclosingConfigFirstParentDefinesBean()} then it would fail. This test is
|
||||
* mostly for illustration purposes, but doesn't hurt to continue using it.
|
||||
*
|
||||
* <p>We purposely use the {@link AEnclosingConfig} to make it alphabetically prior to the
|
||||
* {@link AEnclosingConfig.ChildConfig} which encourages this to occur with the
|
||||
* classpath scanning implementation being used by the author of this test.
|
||||
*/
|
||||
@Test
|
||||
public void enclosingConfigFirstParentDefinesBeanWithScanning() {
|
||||
AnnotationConfigApplicationContext ctx= new AnnotationConfigApplicationContext();
|
||||
context = ctx;
|
||||
ctx.scan(AEnclosingConfig.class.getPackage().getName());
|
||||
ctx.refresh();
|
||||
assertThat(context.getBean("myBean",String.class), equalTo("myBean"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enclosingConfigFirstParentDefinesBeanWithImportResource() {
|
||||
assertLoadsMyBean(AEnclosingWithImportResourceConfig.class,AEnclosingWithImportResourceConfig.ChildConfig.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class AEnclosingWithImportResourceConfig {
|
||||
@Configuration
|
||||
public static class ChildConfig extends ParentWithImportResourceConfig {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enclosingConfigFirstParentDefinesBeanWithComponentScan() {
|
||||
assertLoadsMyBean(AEnclosingWithComponentScanConfig.class,AEnclosingWithComponentScanConfig.ChildConfig.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class AEnclosingWithComponentScanConfig {
|
||||
@Configuration
|
||||
public static class ChildConfig extends ParentWithComponentScanConfig {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enclosingConfigFirstParentWithParentDefinesBean() {
|
||||
assertLoadsMyBean(AEnclosingWithGrandparentConfig.class,AEnclosingWithGrandparentConfig.ChildConfig.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class AEnclosingWithGrandparentConfig {
|
||||
@Configuration
|
||||
public static class ChildConfig extends ParentWithParentConfig {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void importChildConfigThenChildConfig() {
|
||||
assertLoadsMyBean(ImportChildConfig.class,ChildConfig.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ChildConfig extends ParentConfig {}
|
||||
|
||||
@Configuration
|
||||
@Import(ChildConfig.class)
|
||||
static class ImportChildConfig {}
|
||||
|
||||
|
||||
// These worked prior, but validating they continue to work
|
||||
|
||||
@Test
|
||||
public void enclosingConfigFirstParentDefinesBeanWithImport() {
|
||||
assertLoadsMyBean(AEnclosingWithImportConfig.class,AEnclosingWithImportConfig.ChildConfig.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class AEnclosingWithImportConfig {
|
||||
@Configuration
|
||||
public static class ChildConfig extends ParentWithImportConfig {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void childConfigFirst() {
|
||||
assertLoadsMyBean(AEnclosingConfig.ChildConfig.class, AEnclosingConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enclosingConfigOnly() {
|
||||
assertLoadsMyBean(AEnclosingConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void childConfigOnly() {
|
||||
assertLoadsMyBean(AEnclosingConfig.ChildConfig.class);
|
||||
}
|
||||
|
||||
private void assertLoadsMyBean(Class<?>... annotatedClasses) {
|
||||
context = new AnnotationConfigApplicationContext(annotatedClasses);
|
||||
assertThat(context.getBean("myBean",String.class), equalTo("myBean"));
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:c="http://www.springframework.org/schema/c"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="myBean" class="java.lang.String" c:_0="myBean"/>
|
||||
</beans>
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author 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.context.annotation.spr10546.scanpackage;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.spr10546.ParentConfig;
|
||||
|
||||
|
||||
/**
|
||||
* Note the name of {@link AEnclosingConfig} is chosen to help ensure scanning picks up
|
||||
* the enclosing configuration prior to {@link ChildConfig} to demonstrate this can happen
|
||||
* with classpath scanning.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
public class AEnclosingConfig {
|
||||
@Configuration
|
||||
public static class ChildConfig extends ParentConfig {}
|
||||
}
|
||||
+19
@@ -153,6 +153,25 @@ public class PropertyResourceConfigurerIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithNestedUnresolvableReference() {
|
||||
StaticApplicationContext ac = new StaticApplicationContext();
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("name", "name${var}");
|
||||
ac.registerSingleton("tb1", TestBean.class, pvs);
|
||||
pvs = new MutablePropertyValues();
|
||||
pvs.add("properties", "var=${m}var\nm=${var2}\nvar2=${m2}");
|
||||
ac.registerSingleton("configurer1", PropertyPlaceholderConfigurer.class, pvs);
|
||||
try {
|
||||
ac.refresh();
|
||||
fail("Should have thrown BeanDefinitionStoreException");
|
||||
}
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
// expected
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore // this test was breaking after the 3.0 repackaging
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithAutowireByType() {
|
||||
|
||||
+37
-4
@@ -39,8 +39,6 @@ import org.springframework.mock.env.MockPropertySource;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PropertySourcesPlaceholderConfigurer}.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
@@ -139,7 +137,9 @@ public class PropertySourcesPlaceholderConfigurerTests {
|
||||
|
||||
PropertySourcesPlaceholderConfigurer pc = new PropertySourcesPlaceholderConfigurer();
|
||||
pc.setPropertySources(propertySources);
|
||||
pc.setProperties(new Properties() {{ put("my.name", "local"); }});
|
||||
pc.setProperties(new Properties() {{
|
||||
put("my.name", "local");
|
||||
}});
|
||||
pc.setIgnoreUnresolvablePlaceholders(true);
|
||||
pc.postProcessBeanFactory(bf);
|
||||
assertThat(bf.getBean(TestBean.class).getName(), equalTo("${my.name}"));
|
||||
@@ -172,6 +172,38 @@ public class PropertySourcesPlaceholderConfigurerTests {
|
||||
assertThat(bf.getBean(TestBean.class).getName(), equalTo("${my.name}"));
|
||||
}
|
||||
|
||||
@Test(expected=BeanDefinitionStoreException.class)
|
||||
public void nestedUnresolvablePlaceholder() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("testBean",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${my.name}")
|
||||
.getBeanDefinition());
|
||||
|
||||
PropertySourcesPlaceholderConfigurer pc = new PropertySourcesPlaceholderConfigurer();
|
||||
pc.setProperties(new Properties() {{
|
||||
put("my.name", "${bogus}");
|
||||
}});
|
||||
pc.postProcessBeanFactory(bf); // should throw
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoredNestedUnresolvablePlaceholder() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("testBean",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${my.name}")
|
||||
.getBeanDefinition());
|
||||
|
||||
PropertySourcesPlaceholderConfigurer pc = new PropertySourcesPlaceholderConfigurer();
|
||||
pc.setProperties(new Properties() {{
|
||||
put("my.name", "${bogus}");
|
||||
}});
|
||||
pc.setIgnoreUnresolvablePlaceholders(true);
|
||||
pc.postProcessBeanFactory(bf);
|
||||
assertThat(bf.getBean(TestBean.class).getName(), equalTo("${bogus}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withNonEnumerablePropertySource() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
@@ -213,7 +245,8 @@ public class PropertySourcesPlaceholderConfigurerTests {
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
if (override) {
|
||||
assertThat(bf.getBean(TestBean.class).getName(), equalTo("local"));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assertThat(bf.getBean(TestBean.class).getName(), equalTo("enclosing"));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -26,8 +26,6 @@ import org.joda.time.format.DateTimeFormatter;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests for {@link DateTimeFormatterFactoryBean}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
@@ -60,4 +58,5 @@ public class DateTimeFormatterFactoryBeanTests {
|
||||
factory.setStyle("LL");
|
||||
assertThat(factory.getObject(), is(sameInstance(formatter)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-2
@@ -30,8 +30,6 @@ import org.junit.Test;
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
|
||||
/**
|
||||
* Tests for {@link DateTimeFormatterFactory}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
@@ -100,4 +98,5 @@ public class DateTimeFormatterFactoryTests {
|
||||
private DateTimeFormatter applyLocale(DateTimeFormatter dateTimeFormatter) {
|
||||
return dateTimeFormatter.withLocale(Locale.US);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ public class JodaTimeFormattingTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBindLocalDateWithSpecifcFormatter() throws Exception {
|
||||
public void testBindLocalDateWithSpecificFormatter() throws Exception {
|
||||
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
|
||||
registrar.setDateFormatter(org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd"));
|
||||
setUp(registrar);
|
||||
|
||||
+7
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,6 +23,8 @@ import javax.management.modelmbean.RequiredModelMBean;
|
||||
import javax.management.modelmbean.ModelMBeanInfo;
|
||||
import javax.management.modelmbean.ModelMBeanInfoSupport;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.jmx.AbstractMBeanServerTests;
|
||||
import org.springframework.jmx.JmxTestBean;
|
||||
import org.springframework.jmx.export.naming.ObjectNamingStrategy;
|
||||
@@ -36,6 +38,7 @@ import static org.junit.Assert.*;
|
||||
*/
|
||||
public class MBeanExporterOperationsTests extends AbstractMBeanServerTests {
|
||||
|
||||
@Test
|
||||
public void testRegisterManagedResourceWithUserSuppliedObjectName() throws Exception {
|
||||
ObjectName objectName = ObjectNameManager.getInstance("spring:name=Foo");
|
||||
|
||||
@@ -50,6 +53,7 @@ public class MBeanExporterOperationsTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Incorrect name on MBean", name, bean.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterExistingMBeanWithUserSuppliedObjectName() throws Exception {
|
||||
ObjectName objectName = ObjectNameManager.getInstance("spring:name=Foo");
|
||||
ModelMBeanInfo info = new ModelMBeanInfoSupport("myClass", "myDescription", null, null, null, null);
|
||||
@@ -63,6 +67,7 @@ public class MBeanExporterOperationsTests extends AbstractMBeanServerTests {
|
||||
assertEquals(info, infoFromServer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterManagedResourceWithGeneratedObjectName() throws Exception {
|
||||
final ObjectName objectNameTemplate = ObjectNameManager.getInstance("spring:type=Test");
|
||||
|
||||
@@ -88,6 +93,7 @@ public class MBeanExporterOperationsTests extends AbstractMBeanServerTests {
|
||||
assertObjectNameMatchesTemplate(objectNameTemplate, reg2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterManagedResourceWithGeneratedObjectNameWithoutUniqueness() throws Exception {
|
||||
final ObjectName objectNameTemplate = ObjectNameManager.getInstance("spring:type=Test");
|
||||
|
||||
|
||||
@@ -16,26 +16,26 @@
|
||||
|
||||
package org.springframework.ui;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rick Evans
|
||||
* @author Juergen Hoeller
|
||||
@@ -226,12 +226,12 @@ public final class ModelMapTests {
|
||||
public void testAopCglibProxy() throws Exception {
|
||||
ModelMap map = new ModelMap();
|
||||
ProxyFactory factory = new ProxyFactory();
|
||||
Date date = new Date();
|
||||
factory.setTarget(date);
|
||||
SomeInnerClass val = new SomeInnerClass();
|
||||
factory.setTarget(val);
|
||||
factory.setProxyTargetClass(true);
|
||||
map.addAttribute(factory.getProxy());
|
||||
assertTrue(map.containsKey("date"));
|
||||
assertEquals(date, map.get("date"));
|
||||
assertTrue(map.containsKey("someInnerClass"));
|
||||
assertEquals(val, map.get("someInnerClass"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -288,11 +288,20 @@ public final class ModelMapTests {
|
||||
}
|
||||
|
||||
|
||||
private static class SomeInnerClass {
|
||||
public static class SomeInnerClass {
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
return (obj instanceof SomeInnerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return SomeInnerClass.class.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class UKInnerClass {
|
||||
public static class UKInnerClass {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.format.Formatter;
|
||||
import org.springframework.format.number.NumberFormatter;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -614,8 +615,8 @@ public class DataBinderTests extends TestCase {
|
||||
assertNull(rod.getSomeMap().get("key4"));
|
||||
String[] disallowedFields = binder.getBindingResult().getSuppressedFields();
|
||||
assertEquals(2, disallowedFields.length);
|
||||
assertEquals("someMap[key3]", disallowedFields[0]);
|
||||
assertEquals("someMap[key4]", disallowedFields[1]);
|
||||
assertTrue(ObjectUtils.containsElement(disallowedFields, "someMap[key3]"));
|
||||
assertTrue(ObjectUtils.containsElement(disallowedFields, "someMap[key4]"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author 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.cglib.transform.impl;
|
||||
|
||||
import org.springframework.cglib.core.ClassGenerator;
|
||||
import org.springframework.cglib.core.DefaultGeneratorStrategy;
|
||||
import org.springframework.cglib.core.TypeUtils;
|
||||
import org.springframework.cglib.transform.ClassTransformer;
|
||||
import org.springframework.cglib.transform.MethodFilter;
|
||||
import org.springframework.cglib.transform.MethodFilterTransformer;
|
||||
import org.springframework.cglib.transform.TransformingClassGenerator;
|
||||
|
||||
/**
|
||||
* Memory safe variant of {@link UndeclaredThrowableStrategy} ported from the latest
|
||||
* as yet unreleased cglib code.
|
||||
*/
|
||||
public class MemorySafeUndeclaredThrowableStrategy extends DefaultGeneratorStrategy {
|
||||
|
||||
private static final MethodFilter TRANSFORM_FILTER = new MethodFilter() {
|
||||
public boolean accept(int access, String name, String desc, String signature,
|
||||
String[] exceptions) {
|
||||
return !TypeUtils.isPrivate(access) && name.indexOf('$') < 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private Class wrapper;
|
||||
|
||||
|
||||
public MemorySafeUndeclaredThrowableStrategy(Class wrapper) {
|
||||
this.wrapper = wrapper;
|
||||
}
|
||||
|
||||
|
||||
protected ClassGenerator transform(ClassGenerator cg) throws Exception {
|
||||
ClassTransformer tr = new UndeclaredThrowableTransformer(wrapper);
|
||||
tr = new MethodFilterTransformer(TRANSFORM_FILTER, tr);
|
||||
return new TransformingClassGenerator(cg, tr);
|
||||
}
|
||||
}
|
||||
+9
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.core;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.MalformedParameterizedTypeException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
@@ -446,8 +447,13 @@ public abstract class GenericCollectionTypeResolver {
|
||||
return null;
|
||||
}
|
||||
if (clazz.getSuperclass() != null && isIntrospectionCandidate(clazz.getSuperclass())) {
|
||||
return extractType(clazz.getGenericSuperclass(), source, typeIndex, typeVariableMap, typeIndexesPerLevel,
|
||||
nestingLevel, currentLevel);
|
||||
try {
|
||||
return extractType(clazz.getGenericSuperclass(), source, typeIndex, typeVariableMap,
|
||||
typeIndexesPerLevel, nestingLevel, currentLevel);
|
||||
}
|
||||
catch (MalformedParameterizedTypeException ex) {
|
||||
// from getGenericSuperclass() - ignore and continue with interface introspection
|
||||
}
|
||||
}
|
||||
Type[] ifcs = clazz.getGenericInterfaces();
|
||||
if (ifcs != null) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.core;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.MalformedParameterizedTypeException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
@@ -74,12 +75,12 @@ public abstract class GenericTypeResolver {
|
||||
* @param clazz the class to resolve type variables against
|
||||
* @return the corresponding generic parameter or return type
|
||||
*/
|
||||
public static Class<?> resolveParameterType(MethodParameter methodParam, Class clazz) {
|
||||
public static Class<?> resolveParameterType(MethodParameter methodParam, Class<?> clazz) {
|
||||
Type genericType = getTargetType(methodParam);
|
||||
Assert.notNull(clazz, "Class must not be null");
|
||||
Map<TypeVariable, Type> typeVariableMap = getTypeVariableMap(clazz);
|
||||
Type rawType = getRawType(genericType, typeVariableMap);
|
||||
Class result = (rawType instanceof Class ? (Class) rawType : methodParam.getParameterType());
|
||||
Class<?> result = (rawType instanceof Class ? (Class) rawType : methodParam.getParameterType());
|
||||
methodParam.setParameterType(result);
|
||||
methodParam.typeVariableMap = typeVariableMap;
|
||||
return result;
|
||||
@@ -227,7 +228,7 @@ public abstract class GenericTypeResolver {
|
||||
* @param genericIfc the generic interface or superclass to resolve the type argument from
|
||||
* @return the resolved type of the argument, or {@code null} if not resolvable
|
||||
*/
|
||||
public static Class<?> resolveTypeArgument(Class clazz, Class genericIfc) {
|
||||
public static Class<?> resolveTypeArgument(Class<?> clazz, Class<?> genericIfc) {
|
||||
Class[] typeArgs = resolveTypeArguments(clazz, genericIfc);
|
||||
if (typeArgs == null) {
|
||||
return null;
|
||||
@@ -248,11 +249,11 @@ public abstract class GenericTypeResolver {
|
||||
* @return the resolved type of each argument, with the array size matching the
|
||||
* number of actual type arguments, or {@code null} if not resolvable
|
||||
*/
|
||||
public static Class[] resolveTypeArguments(Class clazz, Class genericIfc) {
|
||||
public static Class[] resolveTypeArguments(Class<?> clazz, Class<?> genericIfc) {
|
||||
return doResolveTypeArguments(clazz, clazz, genericIfc);
|
||||
}
|
||||
|
||||
private static Class[] doResolveTypeArguments(Class ownerClass, Class classToIntrospect, Class genericIfc) {
|
||||
private static Class[] doResolveTypeArguments(Class<?> ownerClass, Class<?> classToIntrospect, Class<?> genericIfc) {
|
||||
while (classToIntrospect != null) {
|
||||
if (genericIfc.isInterface()) {
|
||||
Type[] ifcs = classToIntrospect.getGenericInterfaces();
|
||||
@@ -264,10 +265,15 @@ public abstract class GenericTypeResolver {
|
||||
}
|
||||
}
|
||||
else {
|
||||
Class[] result = doResolveTypeArguments(
|
||||
ownerClass, classToIntrospect.getGenericSuperclass(), genericIfc);
|
||||
if (result != null) {
|
||||
return result;
|
||||
try {
|
||||
Class[] result = doResolveTypeArguments(ownerClass, classToIntrospect.getGenericSuperclass(), genericIfc);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
catch (MalformedParameterizedTypeException ex) {
|
||||
// from getGenericSuperclass() - return null to skip further superclass traversal
|
||||
return null;
|
||||
}
|
||||
}
|
||||
classToIntrospect = classToIntrospect.getSuperclass();
|
||||
@@ -275,7 +281,7 @@ public abstract class GenericTypeResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class[] doResolveTypeArguments(Class ownerClass, Type ifc, Class genericIfc) {
|
||||
private static Class[] doResolveTypeArguments(Class<?> ownerClass, Type ifc, Class<?> genericIfc) {
|
||||
if (ifc instanceof ParameterizedType) {
|
||||
ParameterizedType paramIfc = (ParameterizedType) ifc;
|
||||
Type rawType = paramIfc.getRawType();
|
||||
@@ -301,7 +307,7 @@ public abstract class GenericTypeResolver {
|
||||
/**
|
||||
* Extract a class instance from given Type.
|
||||
*/
|
||||
private static Class extractClass(Class ownerClass, Type arg) {
|
||||
private static Class<?> extractClass(Class<?> ownerClass, Type arg) {
|
||||
if (arg instanceof ParameterizedType) {
|
||||
return extractClass(ownerClass, ((ParameterizedType) arg).getRawType());
|
||||
}
|
||||
@@ -368,7 +374,7 @@ public abstract class GenericTypeResolver {
|
||||
* {@link Class concrete classes} for the specified {@link Class}. Searches
|
||||
* all super types, enclosing types and interfaces.
|
||||
*/
|
||||
public static Map<TypeVariable, Type> getTypeVariableMap(Class clazz) {
|
||||
public static Map<TypeVariable, Type> getTypeVariableMap(Class<?> clazz) {
|
||||
Map<TypeVariable, Type> typeVariableMap = typeVariableCache.get(clazz);
|
||||
|
||||
if (typeVariableMap == null) {
|
||||
@@ -377,28 +383,37 @@ public abstract class GenericTypeResolver {
|
||||
// interfaces
|
||||
extractTypeVariablesFromGenericInterfaces(clazz.getGenericInterfaces(), typeVariableMap);
|
||||
|
||||
// super class
|
||||
Type genericType = clazz.getGenericSuperclass();
|
||||
Class type = clazz.getSuperclass();
|
||||
while (type != null && !Object.class.equals(type)) {
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
ParameterizedType pt = (ParameterizedType) genericType;
|
||||
populateTypeMapFromParameterizedType(pt, typeVariableMap);
|
||||
try {
|
||||
// super class
|
||||
Class<?> type = clazz;
|
||||
while (type.getSuperclass() != null && !Object.class.equals(type.getSuperclass())) {
|
||||
Type genericType = type.getGenericSuperclass();
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
ParameterizedType pt = (ParameterizedType) genericType;
|
||||
populateTypeMapFromParameterizedType(pt, typeVariableMap);
|
||||
}
|
||||
extractTypeVariablesFromGenericInterfaces(type.getSuperclass().getGenericInterfaces(), typeVariableMap);
|
||||
type = type.getSuperclass();
|
||||
}
|
||||
extractTypeVariablesFromGenericInterfaces(type.getGenericInterfaces(), typeVariableMap);
|
||||
genericType = type.getGenericSuperclass();
|
||||
type = type.getSuperclass();
|
||||
}
|
||||
catch (MalformedParameterizedTypeException ex) {
|
||||
// from getGenericSuperclass() - ignore and continue with member class check
|
||||
}
|
||||
|
||||
// enclosing class
|
||||
type = clazz;
|
||||
while (type.isMemberClass()) {
|
||||
genericType = type.getGenericSuperclass();
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
ParameterizedType pt = (ParameterizedType) genericType;
|
||||
populateTypeMapFromParameterizedType(pt, typeVariableMap);
|
||||
try {
|
||||
// enclosing class
|
||||
Class<?> type = clazz;
|
||||
while (type.isMemberClass()) {
|
||||
Type genericType = type.getGenericSuperclass();
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
ParameterizedType pt = (ParameterizedType) genericType;
|
||||
populateTypeMapFromParameterizedType(pt, typeVariableMap);
|
||||
}
|
||||
type = type.getEnclosingClass();
|
||||
}
|
||||
type = type.getEnclosingClass();
|
||||
}
|
||||
catch (MalformedParameterizedTypeException ex) {
|
||||
// from getGenericSuperclass() - ignore and preserve previously accumulated type variables
|
||||
}
|
||||
|
||||
typeVariableCache.put(clazz, typeVariableMap);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -54,6 +54,11 @@ public abstract class JdkVersion {
|
||||
*/
|
||||
public static final int JAVA_17 = 4;
|
||||
|
||||
/**
|
||||
* Constant identifying the 1.8 JVM (Java 8).
|
||||
*/
|
||||
public static final int JAVA_18 = 5;
|
||||
|
||||
|
||||
private static final String javaVersion;
|
||||
|
||||
@@ -62,7 +67,10 @@ public abstract class JdkVersion {
|
||||
static {
|
||||
javaVersion = System.getProperty("java.version");
|
||||
// version String should look like "1.4.2_10"
|
||||
if (javaVersion.contains("1.7.")) {
|
||||
if (javaVersion.contains("1.8.")) {
|
||||
majorJavaVersion = JAVA_18;
|
||||
}
|
||||
else if (javaVersion.contains("1.7.")) {
|
||||
majorJavaVersion = JAVA_17;
|
||||
}
|
||||
else if (javaVersion.contains("1.6.")) {
|
||||
@@ -87,7 +95,7 @@ public abstract class JdkVersion {
|
||||
|
||||
/**
|
||||
* Get the major version code. This means we can do things like
|
||||
* {@code if (getMajorJavaVersion() < JAVA_14)}.
|
||||
* {@code if (getMajorJavaVersion() >= JAVA_17)}.
|
||||
* @return a code comparable to the JAVA_XX codes in this class
|
||||
* @see #JAVA_13
|
||||
* @see #JAVA_14
|
||||
|
||||
+9
-2
@@ -114,8 +114,15 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Exception thrown while reading '.class' file for class [" + clazz
|
||||
+ "] - unable to determine constructors/methods parameter names", ex);
|
||||
logger.debug("Exception thrown while reading '.class' file for class [" + clazz +
|
||||
"] - unable to determine constructors/methods parameter names", ex);
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("ASM ClassReader failed to parse class file [" + clazz +
|
||||
"], probably due to a new Java class file version that isn't supported yet " +
|
||||
"- unable to determine constructors/methods parameter names", ex);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
||||
+23
-31
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author 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,7 +24,7 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* The purpose of this class is to enable capturing and passing a generic
|
||||
* {@link Type}. In order to capture the generic type and retain it at runtime,
|
||||
* you need to create a sub-class as follows:
|
||||
* you need to create a subclass as follows:
|
||||
*
|
||||
* <pre class="code">
|
||||
* ParameterizedTypeReference<List<String>> typeRef = new ParameterizedTypeReference<List<String>>() {};
|
||||
@@ -37,54 +37,31 @@ import org.springframework.util.Assert;
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*
|
||||
* @see <a href="http://gafter.blogspot.nl/2006/12/super-type-tokens.html">Neal Gafter on Super Type Tokens</a>
|
||||
*/
|
||||
public abstract class ParameterizedTypeReference<T> {
|
||||
|
||||
private final Type type;
|
||||
|
||||
|
||||
protected ParameterizedTypeReference() {
|
||||
Class<?> parameterizedTypeReferenceSubClass = findParameterizedTypeReferenceSubClass(getClass());
|
||||
|
||||
Type type = parameterizedTypeReferenceSubClass.getGenericSuperclass();
|
||||
Class<?> parameterizedTypeReferenceSubclass = findParameterizedTypeReferenceSubclass(getClass());
|
||||
Type type = parameterizedTypeReferenceSubclass.getGenericSuperclass();
|
||||
Assert.isInstanceOf(ParameterizedType.class, type);
|
||||
|
||||
ParameterizedType parameterizedType = (ParameterizedType) type;
|
||||
Assert.isTrue(parameterizedType.getActualTypeArguments().length == 1);
|
||||
|
||||
this.type = parameterizedType.getActualTypeArguments()[0];
|
||||
}
|
||||
|
||||
private static Class<?> findParameterizedTypeReferenceSubClass(Class<?> child) {
|
||||
|
||||
Class<?> parent = child.getSuperclass();
|
||||
|
||||
if (Object.class.equals(parent)) {
|
||||
throw new IllegalStateException("Expected ParameterizedTypeReference superclass");
|
||||
}
|
||||
else if (ParameterizedTypeReference.class.equals(parent)) {
|
||||
return child;
|
||||
}
|
||||
else {
|
||||
return findParameterizedTypeReferenceSubClass(parent);
|
||||
}
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o instanceof ParameterizedTypeReference) {
|
||||
ParameterizedTypeReference<?> other = (ParameterizedTypeReference<?>) o;
|
||||
return this.type.equals(other.type);
|
||||
}
|
||||
return false;
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj || (obj instanceof ParameterizedTypeReference &&
|
||||
this.type.equals(((ParameterizedTypeReference) obj).type)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,4 +73,19 @@ public abstract class ParameterizedTypeReference<T> {
|
||||
public String toString() {
|
||||
return "ParameterizedTypeReference<" + this.type + ">";
|
||||
}
|
||||
|
||||
|
||||
private static Class<?> findParameterizedTypeReferenceSubclass(Class<?> child) {
|
||||
Class<?> parent = child.getSuperclass();
|
||||
if (Object.class.equals(parent)) {
|
||||
throw new IllegalStateException("Expected ParameterizedTypeReference superclass");
|
||||
}
|
||||
else if (ParameterizedTypeReference.class.equals(parent)) {
|
||||
return child;
|
||||
}
|
||||
else {
|
||||
return findParameterizedTypeReferenceSubclass(parent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ public class AnnotationAwareOrderComparator extends OrderComparator {
|
||||
}
|
||||
if (obj != null) {
|
||||
Class<?> clazz = (obj instanceof Class ? (Class) obj : obj.getClass());
|
||||
Order order = clazz.getAnnotation(Order.class);
|
||||
Order order = AnnotationUtils.findAnnotation(clazz, Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.core.annotation;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
@@ -121,24 +120,24 @@ public abstract class AnnotationUtils {
|
||||
*/
|
||||
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
|
||||
A annotation = getAnnotation(method, annotationType);
|
||||
Class<?> cl = method.getDeclaringClass();
|
||||
Class<?> clazz = method.getDeclaringClass();
|
||||
if (annotation == null) {
|
||||
annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces());
|
||||
annotation = searchOnInterfaces(method, annotationType, clazz.getInterfaces());
|
||||
}
|
||||
while (annotation == null) {
|
||||
cl = cl.getSuperclass();
|
||||
if (cl == null || cl == Object.class) {
|
||||
clazz = clazz.getSuperclass();
|
||||
if (clazz == null || clazz.equals(Object.class)) {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
Method equivalentMethod = cl.getDeclaredMethod(method.getName(), method.getParameterTypes());
|
||||
Method equivalentMethod = clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
|
||||
annotation = getAnnotation(equivalentMethod, annotationType);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
// No equivalent method found
|
||||
}
|
||||
if (annotation == null) {
|
||||
annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces());
|
||||
annotation = searchOnInterfaces(method, annotationType, clazz.getInterfaces());
|
||||
}
|
||||
}
|
||||
return annotation;
|
||||
@@ -217,7 +216,7 @@ public abstract class AnnotationUtils {
|
||||
}
|
||||
}
|
||||
Class<?> superClass = clazz.getSuperclass();
|
||||
if (superClass == null || superClass == Object.class) {
|
||||
if (superClass == null || superClass.equals(Object.class)) {
|
||||
return null;
|
||||
}
|
||||
return findAnnotation(superClass, annotationType);
|
||||
@@ -273,25 +272,22 @@ public abstract class AnnotationUtils {
|
||||
* @return the first {@link Class} in the inheritance hierarchy of the specified
|
||||
* {@code clazz} which declares an annotation of at least one of the specified
|
||||
* {@code annotationTypes}, or {@code null} if not found
|
||||
* @since 3.2.2
|
||||
* @see Class#isAnnotationPresent(Class)
|
||||
* @see Class#getDeclaredAnnotations()
|
||||
* @see #findAnnotationDeclaringClass(Class, Class)
|
||||
* @see #isAnnotationDeclaredLocally(Class, Class)
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public static Class<?> findAnnotationDeclaringClassForTypes(List<Class<? extends Annotation>> annotationTypes,
|
||||
Class<?> clazz) {
|
||||
public static Class<?> findAnnotationDeclaringClassForTypes(List<Class<? extends Annotation>> annotationTypes, Class<?> clazz) {
|
||||
Assert.notEmpty(annotationTypes, "The list of annotation types must not be empty");
|
||||
if (clazz == null || clazz.equals(Object.class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Class<? extends Annotation> annotationType : annotationTypes) {
|
||||
if (isAnnotationDeclaredLocally(annotationType, clazz)) {
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
||||
return findAnnotationDeclaringClassForTypes(annotationTypes, clazz.getSuperclass());
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.core.convert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
@@ -38,7 +39,10 @@ import org.springframework.util.ObjectUtils;
|
||||
* @author Sam Brannen
|
||||
* @since 3.0
|
||||
*/
|
||||
public class TypeDescriptor {
|
||||
public class TypeDescriptor implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -437,7 +437,7 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
|
||||
|
||||
public <T> T getProperty(String key, Class<T> targetType, T defaultValue) {
|
||||
return this.propertyResolver.getProperty(key, targetType, defaultValue);
|
||||
};
|
||||
}
|
||||
|
||||
public <T> Class<T> getPropertyAsClass(String key, Class<T> targetType) {
|
||||
return this.propertyResolver.getPropertyAsClass(key, targetType);
|
||||
|
||||
+40
-26
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author 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,25 +16,22 @@
|
||||
|
||||
package org.springframework.core.env;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.springframework.util.SystemPropertyUtils.PLACEHOLDER_PREFIX;
|
||||
import static org.springframework.util.SystemPropertyUtils.PLACEHOLDER_SUFFIX;
|
||||
import static org.springframework.util.SystemPropertyUtils.VALUE_SEPARATOR;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.util.PropertyPlaceholderHelper;
|
||||
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
|
||||
import org.springframework.util.SystemPropertyUtils;
|
||||
|
||||
/**
|
||||
* Abstract base class for resolving properties against any underlying source.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
public abstract class AbstractPropertyResolver implements ConfigurablePropertyResolver {
|
||||
@@ -44,15 +41,20 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
|
||||
protected ConfigurableConversionService conversionService = new DefaultConversionService();
|
||||
|
||||
private PropertyPlaceholderHelper nonStrictHelper;
|
||||
|
||||
private PropertyPlaceholderHelper strictHelper;
|
||||
|
||||
private boolean ignoreUnresolvableNestedPlaceholders = false;
|
||||
|
||||
private String placeholderPrefix = PLACEHOLDER_PREFIX;
|
||||
private String placeholderSuffix = PLACEHOLDER_SUFFIX;
|
||||
private String valueSeparator = VALUE_SEPARATOR;
|
||||
private String placeholderPrefix = SystemPropertyUtils.PLACEHOLDER_PREFIX;
|
||||
|
||||
private String placeholderSuffix = SystemPropertyUtils.PLACEHOLDER_SUFFIX;
|
||||
|
||||
private String valueSeparator = SystemPropertyUtils.VALUE_SEPARATOR;
|
||||
|
||||
private final Set<String> requiredProperties = new LinkedHashSet<String>();
|
||||
|
||||
|
||||
public ConfigurableConversionService getConversionService() {
|
||||
return this.conversionService;
|
||||
}
|
||||
@@ -63,12 +65,12 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
|
||||
|
||||
public String getProperty(String key, String defaultValue) {
|
||||
String value = getProperty(key);
|
||||
return value == null ? defaultValue : value;
|
||||
return (value != null ? value : defaultValue);
|
||||
}
|
||||
|
||||
public <T> T getProperty(String key, Class<T> targetType, T defaultValue) {
|
||||
T value = getProperty(key, targetType);
|
||||
return value == null ? defaultValue : value;
|
||||
return (value != null ? value : defaultValue);
|
||||
}
|
||||
|
||||
public void setRequiredProperties(String... requiredProperties) {
|
||||
@@ -92,7 +94,7 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
|
||||
public String getRequiredProperty(String key) throws IllegalStateException {
|
||||
String value = getProperty(key);
|
||||
if (value == null) {
|
||||
throw new IllegalStateException(format("required key [%s] not found", key));
|
||||
throw new IllegalStateException(String.format("required key [%s] not found", key));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -100,7 +102,7 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
|
||||
public <T> T getRequiredProperty(String key, Class<T> valueType) throws IllegalStateException {
|
||||
T value = getProperty(key, valueType);
|
||||
if (value == null) {
|
||||
throw new IllegalStateException(format("required key [%s] not found", key));
|
||||
throw new IllegalStateException(String.format("required key [%s] not found", key));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -130,17 +132,17 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
|
||||
}
|
||||
|
||||
public String resolvePlaceholders(String text) {
|
||||
if (nonStrictHelper == null) {
|
||||
nonStrictHelper = createPlaceholderHelper(true);
|
||||
if (this.nonStrictHelper == null) {
|
||||
this.nonStrictHelper = createPlaceholderHelper(true);
|
||||
}
|
||||
return doResolvePlaceholders(text, nonStrictHelper);
|
||||
return doResolvePlaceholders(text, this.nonStrictHelper);
|
||||
}
|
||||
|
||||
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
|
||||
if (strictHelper == null) {
|
||||
strictHelper = createPlaceholderHelper(false);
|
||||
if (this.strictHelper == null) {
|
||||
this.strictHelper = createPlaceholderHelper(false);
|
||||
}
|
||||
return doResolvePlaceholders(text, strictHelper);
|
||||
return doResolvePlaceholders(text, this.strictHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,15 +156,19 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
|
||||
|
||||
/**
|
||||
* Resolve placeholders within the given string, deferring to the value of
|
||||
* {@link #setIgnoreUnresolvableNestedPlaceholders(boolean)} to determine whether any
|
||||
* {@link #setIgnoreUnresolvableNestedPlaceholders} to determine whether any
|
||||
* unresolvable placeholders should raise an exception or be ignored.
|
||||
* <p>Invoked from {@link #getProperty} and its variants, implicitly resolving
|
||||
* nested placeholders. In contrast, {@link #resolvePlaceholders} and
|
||||
* {@link #resolveRequiredPlaceholders} do <emphasis>not</emphasis> delegate
|
||||
* to this method but rather perform their own handling of unresolvable
|
||||
* placeholders, as specified by each of those methods.
|
||||
* @since 3.2
|
||||
* @see #setIgnoreUnresolvableNestedPlaceholders(boolean)
|
||||
* @see #setIgnoreUnresolvableNestedPlaceholders
|
||||
*/
|
||||
protected String resolveNestedPlaceholders(String value) {
|
||||
return this.ignoreUnresolvableNestedPlaceholders ?
|
||||
this.resolvePlaceholders(value) :
|
||||
this.resolveRequiredPlaceholders(value);
|
||||
resolvePlaceholders(value) : resolveRequiredPlaceholders(value);
|
||||
}
|
||||
|
||||
private PropertyPlaceholderHelper createPlaceholderHelper(boolean ignoreUnresolvablePlaceholders) {
|
||||
@@ -171,11 +177,19 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
|
||||
}
|
||||
|
||||
private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
|
||||
return helper.replacePlaceholders(text, new PlaceholderResolver() {
|
||||
return helper.replacePlaceholders(text, new PropertyPlaceholderHelper.PlaceholderResolver() {
|
||||
public String resolvePlaceholder(String placeholderName) {
|
||||
return getProperty(placeholderName);
|
||||
return getPropertyAsRawString(placeholderName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the specified property as a raw String,
|
||||
* i.e. without resolution of nested placeholders.
|
||||
* @param key the property name to resolve
|
||||
* @return the property value or {@code null} if none found
|
||||
*/
|
||||
protected abstract String getPropertyAsRawString(String key);
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user